存档

‘数据库’ 分类的存档

欧盟真的批准Oracle收购Sun了?

2010年1月21日

  欧盟真的批准Oracle收购Sun了?那么MySQL也落入了Oracle的手里。据国外媒体报道,甲骨文以70亿美元的价格收购Sun的交易今天获得了欧盟无条件批准。
  这笔交易将改变科技产业的格局,这意味着全球第二大商用软件提供商甲骨文进入了硬件产业。在规模达170亿美元的高端计算机服务器市场,Sun是市场的领先者。

  去年12月份,甲骨文做出多项承诺,包括收购Sun之后仍将保持MySQL开源数据库的开放性,在接下来三年里投入更多资金用于MySQL数据库的研发工作,并为MySQL 用户专门建立一个客户咨询团队。

  欧盟于去年9月份开始对这笔效果进行深入调查。欧盟的主要担心在于,甲骨文收购Sun将给MySQL市场的竞争带来不利影响。

  批准这笔交易后,欧盟委员会反垄断事务委员尼莉·克劳斯(Neelie Kroes)在一份声明中表示:“甲骨文收购Sun之后,市场的竞争和创新不会受到影响,我对此感到满意。这笔交易可以激活一些重要资产,创造出全新的创新产品。”

  欧盟表示,在做出这一决定时考虑到了甲骨文做出的承诺,而且甲骨文已经采取措施,落实了部分承诺。

  去年8月份,甲骨文收购Sun的交易获得了美国司法部的批准。目前,中国和俄罗斯的监管机构尚未批准这笔交易。

  对于网上传播的MySQL创始人给中国开发者写信请求签名拒绝Oracle收购MySQL的计划可能要落空了。但愿MySQL在oracle手里会存活下来。让我们祝福MySQL吧。

MySQL , ,

SQL Server 2008中已中止及不推荐的功能

2010年1月13日

  每个新版本的SQL Server 都会有一些功能被更改或删除,因为他们对新的功能集来说已不再有必要存在。中止(Discontinued)意味着早期版本的SQL Server可用的功能在SQL Server 2008中已不再被支持。不推荐(Deprecated)意味着此功能在SQL Server 2008版本中仍被支持,但它将在未来的版本中被删除。不推荐的级别的两个:一个是在下一版本将移除的功能列表;另一个是在当前版本仍支持,但将会在某个未来的版本移除。

  SQL Server的联机丛书已经详细列出这三种内容了,这里再强调一下:

  最终将移除的功能(不推荐):这些功能将某个未来的版本移除,你可以尝试从代码中将其替换(用其实支持的方式来实现)。

  • SQLOLEDB
  • Timestamp(尽管其同义词rowversion仍将被支持)
  • Text, ntext,和 image数据类型
  • 旧的全文搜索目录命令
  • Sp_configure ‘user instances enabled’
  • Sp_lock
  • SQL-DMO
  • 以SP开头的存储过程,如sp_adduser
  • Set user(替换为Execute as)
  • 系统表
  • Group by all

  马上移除的功能(不推荐):下列功能在下个版本的SQL Server中将被移除,你应该立即从代码中删除这些命令。

  • 旧的备份和恢复选项
  • SQL Server 2000的兼容级别
  • DATABASEPROPERTY命令
  • sp_dboption
  • FastFirstRow查询提示(请改为Option(Fast n))
  • ANSI-89的外连接语法 (*=, =*)
  • Raiserror
  • 使用 DB-Lib的客户端连接,用于C语言的嵌入SQL

  已经移除的功能(中止):下列功能在SQL Server 2008中已经被移除。

  • SQL Server 6, 6.5, and 7的兼容级别
  • 外围配置工具(Surface Area Configuration Tool)
  • 通知服务
  • Dump 和Load命令
  • Backup log with No-Log语法
  • Backup log with truncate_only语法
  • Backup transaction语法
  • DBCC并发性冲突
  • sp_addgroup、sp_changegroup、 sp_dropgroup及sp_helpgroup

 

  首发张文杰的博客:http://zhangwenjie.net(转载请保留,谢谢)

SQL Server

SQL Server 2008中的十大新特性

2010年1月13日

  其实SQL Server 2008本身有远不止10项目增强与新特性。下面是我所认为的比较重要的新特性,欢迎拍砖:

  10、PowerShell。PPwerShell是Windows下的新的脚本语言,现在已经集成到SQL Server 2008里了。如果你是一个DBA且愿学习PowerShell,那么这项技术将显著改善你的日常工作。

  9、新的数据类型。新的数据类型中最令人兴奋的可能是Date、Time、DateTime2,可能还有Spatial、HierarchyID。

  8、Tablix。一个混合了表和矩阵的格式,随着SQL Server 2008报表服务的发布而推出。

  7、查询处理优化。新的星型连接对某些查询提供难以置信的性能提升;而且,虽然在SQL Server 2005中已经引入了分区表,在SQL Server 2008中的查询执行计划的性能改进及为分区表设计的新UI工具将增强分区表的采用率。

  6、筛选索引(Filtered indexes)。可以为一个非常大的表创建小的目标非聚集索引(targeted nonclustered index)的能力是对索引的完美逻辑扩展。这将一个最爱欢迎的特性之一。

  5、数据仓库管理。由Performance Studio或自定义报表收集性能数据的新的一致方法,供以后进一步分析使用。同时,第三方在此基础上可以做更多事情。

  4、数据压缩。为减少IO而改善CPU周期的能力将显著增强企业数据库的可扩展性。这项实用功能为将数据库升级到SQL Server 2008企业版提供令人信服的理由。

  3、Management Studio。这个工具集成了许多功能,包括与多服务器的查询、服务器配置、智能感知、T-SQL 调试器、可自定义的查询编辑器选项卡、查询编辑器的错误列表、方便导出查询结果的数据,通过查询启动 profiler、对象搜索、显著改进的对象资源管理器详细信息页、一个新的活动监视器、使用查询计划的改进的方法;同时,它比以前更快。

  2、Merge and Table-valued parameters。Table-valued parameters革新了应用程序事务与数据库通信的方法。新的merge命令地一个事务中合并了insert, update, and delete操作。

  1、Policy-based management (PBM)。PBM意味着服务器和数据库可以以应用和执行一致的政策的方式来声明式的管理,不再是运行一些特别的脚本。这个特性将明显改变企业DBA每天的工作方式。

  首发张文杰的博客:http://zhangwenjie.net(转载请保留,谢谢)。

SQL Server ,

SQL Server 2008中的XML-XML数据类型(续)

2009年12月12日

  SQL server 2005中引入了一个新的数据类型:xml.这个新数据类型是用来操作XML数据的,现在SQL Server 2008进一步增强了它的功能。使用这种新的数据类型,可以以本机格式存储 XML、 查询 XML 中的数据、 轻松有效地修改 XML 中的数据且无需涉及改动全部的内容,同样也可以索引XML中的数据。

  XML数据类型可以像其它数据一样也可以设置是否可空、设置其默认值以及设置它的约束。如果你想使一个xml字段必须有值且为它提供默认值,你只要像如下指定即可:

  

  CREATE TABLE OrdersXML
     (OrderDocID INT PRIMARY KEY,
     xOrders XML NOT NULL DEFAULT '<Orders/>')
  下列代码也成功运行,是因为它使用了xOrders字段的默认值:
  INSERT INTO OrdersXML (OrderDocID, xOrders) VALUES (3, '<blah>steve</blah>')
  XML架构(XML Schemas)

  XML数据类型的一个强大之处是可以在XML文档中输入强数据类型的能力。XSD(XML架构定义)定义了一组标准,这个标准必须在所有的XML 文档中支持的数据类型。您可以为您的数据创建 XML 架构,要求数据符合一组指定的规则。这使 XML 优越于几乎所有其他数据传输/数据描述方法,也是XML 标准成功一个主要因素。

  如果没有XML架构,XML可能只是相对先进、以文本分隔的格式。XML 架构定义了数据应该是什么样子,什么元素是必须的,会有哪些数据类型。类似 SQL Server 中的表定义提供如何对关系数据的结构和类型进行验证, XML 架构提供 XML 数据的结构和类型验证。

  我们无法在这里完全描述XML 架构的所有功能,因为这需要大量篇幅。您可以在 http://www.w3.org/2001/XMLSchema 找到  XSD 规范。几个受欢迎的架构是公开的,提供包括一个为博客、blogcasts提供支持的真正简单聚合协议 (Really Simple ,RSS),和为二进制文件和文本聚合提供支持的协议,另一个用于该指示 XML Web 服务如何传递信息的 SOAP。

  您可以选择如何构建您的 XSD。XSD 可以创建必需的元素,并设置限制,允许哪些数据类型和范围。它甚至可以允许文档片段。

  SQL Server 架构集合(Schema Collections)

  SQL Server 2005 提供了创建您自己的架构,作为数据库对象并将其存储在数据库中的能力,且为任何 XML 实例提供验证,包括表中的XML字段和 SQL Server 变量。这使您可以更好地控制要存储到数据库中的 XML数据,并可以使XML 实例是强类型的。SQL Server 2008以下列 增强了这种支持:

  • 保留 xsd:dateTime 值中的时区
  • 宽松的验证
  • 架构中的联合和列表类型

  在你深入研究这些新的特性之前,你应该回顾一下架构是如何与SQL Server一起工作的。开始之间,你要先创建一个简单的架构,并将其添加到架构集合中:

 

--syntax for adding a schema
--schema can disallow fragments if you say so
CREATE XML SCHEMA COLLECTION dbo.order_xsd
AS
'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:simpleType name="orderAmt" >
     <xsd:restriction base="xsd:int" >
       <xsd:maxExclusive value="5000" />
       <xsd:minInclusive value="1" />
     </xsd:restriction>
   </xsd:simpleType>
   <xsd:element name="Order">
  <xsd:complexType>
    <xsd:sequence>
    <xsd:element name="CustomerName" type="xsd:string" />
    <xsd:element name="OrderDate" type="xsd:dateTime"/>
    <xsd:element name="OrderAmt" type="orderAmt"/>
    </xsd:sequence>
  </xsd:complexType>
   </xsd:element>
</xsd:schema>'
GO

 

  此架构命名为 order_xsd,并可以在包括变量、 参数、 返回值和特别是表中的列上的xml 类型上使用它。此架构定义了名为 CustomerName、 OrderDate 和 OrderAmt 的元素。OrderAmt 使用了orderAmt类型,orderAmt定义为一个 int 数据类型,它的最小值为 1,它的最大值是 4999 的 orderAmt 类型。(我们知道您将很可能不会这样为您的数据建模,这样一来,但您可能处于用于显示等的目的需要将您关系数据转换成 XML,然后通过一个 XSD 类型进行限制,这是非常有价值的)。接下来,创建一个简单的表并应用架构到 XML 列,这需要在CREATE TABLE 语句中的 xml 数据类型后的括号中引用架构名称,如下所示:

 

--create table with xml column and use schema as a rule for a particular column
CREATE TABLE xml_schematest (
   Order_ID int PRIMARY KEY,
   Order_XML xml(order_xsd) --XML Schema Name
)
GO

 

  在此示例中,您可以看到,Order_XML 列定义为 xml(order_xsd) 而不是简单的 xml。xml 数据类型有一个可选的参数,允许您指定绑定的架构。如果您要将架构绑定到一个变量或参数等之类的 xml 数据类型,也是的同样方法。这样SQL Server 在 Order_XML 列中允许只是强类型化的 XML 文档。这方法比CHECK约束要好。使用 XML 架构的优点是确保只有正确的 XML 数据才能存储到表中。如果使用了 CHECK 约束,你将需要为你想要执行的每个验证绑定一个单独的 CHECK 约束。

  注意:在创建 xml 列时您定义的任何默认值必须是有效的,并和该列绑定的架构没有冲突; 否则,默认值总是失败的。此外,请确保定义的任何约束也是有效的,并和该列绑定的架构没有冲突; 否则,插入或更新数据的所有尝试可能会都失败。

  让我们看一个有关架构的例子:

  

 

INSERT INTO xml_schematest VALUES (1, '
<Order>
  <CustomerName>Bill Gates</CustomerName>
  <OrderDate>2008-10-10T14:22:27.25-05:00</OrderDate>
  <OrderAmt>100</OrderAmt>
</Order>')
--This will fail
INSERT INTO xml_schematest VALUES (2, '
<Order>
  <CustomerName>Steve Ballmer</CustomerName>
  <OrderDate>2008-10-10T14:22:27.25-05:00</OrderDate>
  <OrderAmt>10000</OrderAmt>
</Order>')

 

  SQL Server 执行插入和更新时将验证架构,确保数据的完整性。由于我们所提供的数据符合该架构,插入将会成功。如果您尝试插入或更新一个无效的数据片段,您将收到一个错误:

 

UPDATE xml_schematest
SET Order_XML='
<Order>
  <CustomerName>Bill Gates</CustomerName>
  <OrderDate>2008-10-10T14:22:27.25-05:00</OrderDate>
  <OrderAmt>10000</OrderAmt>
</Order>'
WHERE Order_ID=1

 

  SQL Server将报告如下的错误:

 Msg 6926, Level 16, State 1, Line 1
XML Validation: Invalid simple type value: ’10000′. Location: /*:Order[1]/*:OrderAmt[1]

 

  (未完待续)

  本文首发地址张文杰博客:http://zhangwenjie.net(转载请保留)

SQL Server, 数据库 ,

SQL Server 2008中的XML-XML数据类型

2009年12月5日

  SQL server 2005中引入了一个新的数据类型:xml.这个新数据类型是用来操作XML数据的,现在SQL Server 2008进一步增强了它的功能。使用这种新的数据类型,可以以本机格式存储 XML、 查询 XML 中的数据、 轻松有效地修改 XML 中的数据且无需涉及改动全部的内容,同样也可以索引XML中的数据。您可以以下方式使用 xml :

  • 一个变量
  • 在存储过程或自定义函数中作为参数
  • 自定义函数的返回值
  • 一个表的一列

  在这里您也应应意识到 xml 数据类型的一些限制。虽然xml数据类型可以包含NULL值,但不像其它的本机数据类型,您不能直接比较两个 xml 数据类型的实例。(不过您可以将xml实例转换为 TEXT 数据类型,然后再做比较。)任何相等比较需要先将xml 类型转换为字符类型。此限制也意味着您不能在 ORDER BY 或 GROUP BY子句中使用xml 数据类型。还有几个其他限制,我们稍后会更详细地讨论。

  这似乎是相当严重的限制,但在正确使用时他们不会真正影响到 xml 数据类型。xml 数据类型也有一个丰富的功能集,这算是对这些限制的一些补偿。

  作为变量使用XML数据类型

  让我们首先编写一些使用新的 xml 数据类型的变量的代码。和使用任何其他 TRANSACT-SQL (T-SQL) 变量一样,您只需声明它,然后分配值给它,如在下面的示例中,使用一段XML来表示一个销售代表的数据为:
  DECLARE @xmlData AS XML;
  SET @xmlData=’
   <Customers>
     <CustomerID>TELRK</CustomerID>
     <CompanyName>Telerik, Inc</CompanyName>
     <ContactName>Stephen Forte</ContactName>
     <ContactTitle>Sales Representative</ContactTitle>
     <Address>5-9 Union Square West</Address>
     <City>New York</City>
     <PostalCode>10028</PostalCode>
     <Country>USA</Country>
     <Phone>030-0074321</Phone>
     <Fax>030-0076545</Fax>
   </Customers>’;
  SELECT @xmlData;
  

  这个很基本的示例显示了像声明任何其他任何本机 SQL Server 数据类型一样使用 DECLARE 语句声明一个 XML 变量。该变量然后被分配了一个值。很奇怪的是,一个表示XML 数据的字符串分配给了xml 的数据类型,xml数据奖这个字符串解析成 XML。(同样,基于公共语言运行库用户定义类型也支持且需要相同的功能。)该示例同时还检查XML格式的正确性,如验证元素的开始和结束标记是否匹配。

  最后一个语句通过一个SELECT 语句将XML返回给调用方,结果将在单行单列中显示xml数据。让数据库认识到您正在使用 XML数据 (而不是恰好是 XML的原始文本)的另一个好处是xml数据在 SQL Server Management Studio 呈现为超链接。点击超链接会打开一个新窗口,包含了格式化好的xml数据(使用 Windows Internet Explorer XML 模板),同时带有颜色高亮及可折叠/可展开节点。如果您然后在XML 结果窗口的标题栏上右键单击,您将看到一些有用的选项,如将 XML 保存到文件。

  在表中使用XML数据

  如之前所说,您也可以像如下的例子一样在一个表中将一列定义为xml:

  USE AdventureWorks2008

  GO

  CREATE TABLE OrdersXML
    (OrderDocID int PRIMARY KEY,
     xOrders xml NOT NULL)

  如刚才所说,xml数据类型存在一些限制,在将xml定义为表的一列时限制如下:

  • 它不能定义为主键
  • 它不能定义为外键
  • 不能将它定义为惟一约束(UNIQUE constraint)
  • 不能在定义中使用COLLATE关键字

  我们之前说过不能比较两个xml实例的相等性。主键、外键、惟一约束都需要能比较包含的数据,因此xml数据不能在这些情况下使用。SQL Server的COLLATE语句对xml数据类型来说是没有意义的,因为SQL Server并不是将xml数存储为文本,而是使用特定于xml的编码。

  现在让我们在此列中插入一些数据。这个例子使用硬编码的xml数据,先存放到一个xml变量中,然后插入到我们刚刚创建的OrdersXML表中:

  DECLARE @xmlData AS XML;
   SET @xmlData = ‘
   <Orders>
     <Order>
       <OrderID>5</OrderID>
       <CustomerID>65</CustomerID>
       <OrderAmount>25</OrderAmount>
    </Order>
  </Orders>’;

  INSERT INTO OrdersXML (OrderDocID, xOrders) Values (1, @xmlData);

  你可以有多种方式将xml数据插入到列中:XML Bulk Load(我们稍候会讨论) ;从XML变量中加载(如例子所示);使用FOR XML TYPE特性从SELECT语句中加载,这个一会将讲到。只的格式良好的XML(包括片段)才能插入到表中,任何将非法格式XML数据插入表的尝试将导致一个异常,如下所示:

  INSERT INTO OrdersXML (OrderDocID, xOrders) VALUES (3, ‘<nm>steve</NM>’);

  这将产生如下的错误消息:

  Msg 9436, Level 16, State 1, Line 1
  XML parsing: line 1, character 14, end tag does not match start tag

  (末完待续…)

SQL Server , , , , , ,

Microsoft SQL Server 2008中T-SQL对CTE的增强(续)

2009年11月20日

  CTEs的真正强大之处在于对树状结构的数据上执行的分层(hierarchical)递归查询。实事上,除了符合ANSI SQL-92标准之外,这也是Microsoft构建CTEs的主要原因。一个递归CTE同至少两部分查询组成:首先,锚成员(anchor member)是一个非递归查询;第二个,递归成员(recursive member)是一个递归查询。在CTE定义的括号里(AS语句之后),查询定义为独立的或引用同一CTE。锚成员或递归成员由UNION ALL语句分开。锚成员只会被调用一次;递归成员会被重复调用,直到没有行被返回。下面是语法:

WITH SimpleRecursive(field names)
AS
(
   <Select Statement for the Anchor Member>

   UNION ALL

   <Select Statement for the Recursive Member>
)

SELECT * FROM SimpleRecursive

下面的代码将演示这些特性。下面的代码创建了一个employees表,表中有一个自引用到EmployeeID的字段:ReportsTo。我们将编写一个查询得到所有向Stephen (EmployeeID=2)报告的员工及向Stephen下级报告的员工。

 测试表:

CREATE TABLE EmployeeTree
 (EmployeeID int PRIMARY KEY,
  EmployeeName nvarchar(50),
  ReportsTo int)
GO

--insert some data, build a reporting tree
INSERT INTO EmployeeTree VALUES(1, 'Richard', NULL)
INSERT INTO EmployeeTree VALUES(2, 'Stephen', 1)
INSERT INTO EmployeeTree VALUES(3, 'Clemens', 2)
INSERT INTO EmployeeTree VALUES(4, 'Malek', 2)
INSERT INTO EmployeeTree VALUES(5, 'Goksin', 4)
INSERT INTO EmployeeTree VALUES(6, 'Kimberly', 1)
INSERT INTO EmployeeTree VALUES(7, 'Ramesh', 5)

 递归查询代码:

WITH SimpleRecursive(EmployeeID, EmployeeName, ReportsTo)
AS
(
  SELECT EmployeeID, EmployeeName, ReportsTo
   FROM EmployeeTree WHERE EmployeeID = 2
  UNION ALL
  SELECT p.EmployeeID, p.EmployeeName, p.ReportsTo
   FROM EmployeeTree AS P
    INNER JOIN SimpleRecursive A ON A.EmployeeID = P.ReportsTo
)
SELECT sr.EmployeeName AS Employee, et.EmployeeName AS Boss
 FROM SimpleRecursive AS sr
  INNER JOIN EmployeeTree AS et ON sr.ReportsTo = et.EmployeeID

下面是查询结果:

Employee    Boss
----------- ------------
Stephen     Richard
Clemens     Stephen
Malek       Stephen
Goksin      Malek
Ramesh      Goskin

  递归查询以EmployeeID = 2开始(SELECT之后的锚成员),此查询将获取相应的记录,然后由递归查询获取向Stephen报告的员工记录及相应记录的下级。(例如Goksin向Malek汇报, 以及 Malek 向Stephen汇报.)。然后每个子递归尝试获取上次递归找到的员工的下级。最后,递归将返回空记录,这将导致递归结束(这就是为什么没有Kimberly记录的原因)。如果将上述代码中的的锚成员改为EmployeeID = 1,查询将返回Kimberly记录。

  从设计上讲,递归成员将一直查询下级员工(对本例来说)并无限持续下去。如果你怀疑递归过多并想限制递归调用的次数,你可以在CTE的外查询(见下例)中指定OPTION子句的MAXRECURSION选项。如:OPTION(MAXRECURSION 25)

  这个选项将促使SQL Server在递归深度超过指定限制时产生一个错误。缺省时,这个限制是100(就是在你忽略这个选项时)。如果你想彻底取消此选项的作用,你需要指定MAXRECURSION为0。你可以通过指定MAXRECURSION选项用和上面一样的代码来取得最上两级员工:

 

WITH SimpleRecursive(EmployeeID, EmployeeName, ReportsTo)
AS
(
  SELECT EmployeeID, EmployeeName, ReportsTo
   FROM EmployeeTree WHERE EmployeeID = 2
  UNION ALL
  SELECT p.EmployeeID, p.EmployeeName, p.ReportsTo
   FROM EmployeeTree AS P
    INNER JOIN SimpleRecursive A ON A.EmployeeID = P.ReportsTo
)
SELECT sr.EmployeeName AS Employee, et.EmployeeName AS Boss
 FROM SimpleRecursive AS sr
  INNER JOIN EmployeeTree AS et ON sr.ReportsTo = et.EmployeeID
OPTION(MAXRECURSION 2)

下面中结果:
Employee Boss
———- ————
Stephen Richard
Clemens Stephen
Malek Stephen
Goksin Malek

  你同时会看到如下的错误信息:

Msg 530, Level 16, State 1, Line 2
The statement terminated. The maximum recursion 2 has been exhausted
before statement completion.

     为了避免这种错误,一种方法是用一个产生列(generated column)来跟踪当前的层级并在WHERE子句中使用这个产生列作为限制条件,而不使用MAXRECURSION选项。下面是修改过的代码,它将返回和上述同样的数据,但不会产生错误信息:

 

WITH SimpleRecursive(EmployeeID, EmployeeName, ReportsTo, SubLevel)
AS
(
  SELECT EmployeeID, EmployeeName, ReportsTo, 0
   FROM EmployeeTree WHERE EmployeeID = 2
  UNION ALL
  SELECT p.EmployeeID, p.EmployeeName, p.ReportsTo, SubLevel + 1
   FROM EmployeeTree AS P
    INNER JOIN SimpleRecursive A ON A.EmployeeID = P.ReportsTo
    WHERE SubLevel <= 2
)
SELECT sr.EmployeeName AS Employee, et.EmployeeName AS Boss
 FROM SimpleRecursive sr
  INNER JOIN EmployeeTree AS et ON sr.ReportsTo = et.EmployeeID

  另外,SQL Server 2008引入了一个hierarchyid新数据类型,可以比我们刚才看到的递归代码实现更强大树形结构数据。等有机会我们再探讨。

SQL Server , , ,

推荐两本关于SQL Server 2008的经典书

2009年10月24日

   SQL Server 2008是微软最新推出的数据库系统,它比SQL Server 2005更成熟、更强大,性能也更好。对于Windows平台下的程序员,学习SQL Server将是不可避免的。于是,选择经典、权威的书籍将事半功倍。尽管我将的书籍是英文原版的,但它仍然是不可替代的。另外,学习英文也是程序员的一项基础功能。

  • Microsoft SQL Server 2008 Internals。这本书是由六位SQL Server专家合著的。想必大家对其中的Kalen Delaney应该比较眼熟。她过的重要的书有《INSIDE MICROSOFT SQL SERVER 2005: QUERY TUNING AND OPTIMIZATION》、《INSIDE MICROSOFT SQL SERVER 2005: THE STORAGE ENGINE》以及早期的《INSIDE MICROSOFT SQL SERVER 2000》。由Kalen Delaney编写的微软SQL Server图书一直是同类图书中的佼佼者,是SQL Server 开发人员、架构师和DBA的案头必备书。如今,这本新书纳入微软阵容空前的“深入解析”(Internals)系列,增加5位SQL Server顶级专家,深入剖析了SQL Server 2008的底层机理及其对应用程序的影响,更具权威性。对于想更深入了解SQL Server内幕的开发人员,此书绝对是不可少的。

   本书是讲述SQL Server关系数据库引擎内部机理和架构的权威指南。书中详细阐述了SQL Server处理查询、管理数据的相关内容,包括SQL   Server架构和配置、跟踪/扩展事件、日志和恢复、索引、表格、查询优化、事务/并发以及DBCC。.

   本书适合中高级数据库开发人员阅读。

 

microsoft sql server 2008 internals

microsoft sql server 2008 internals

  • Microsoft SQL Server 2008 T-SQL Fundamentals。此书是由Itzik Ben-Gan写的,是一本讲解SQL Server 2008基础知识的书,但这不意味着它很简单;相反此书却相当有深度,也就是对基础知识后面的逻辑知识有深入的介绍,同时也提供了难得的在真实开发中使用SQL的经验和建议。正如作者所说:For me, T-SQL is more than just a language—it’s a way of thinking。(对我来说,T-SQL绝不仅仅只是一门语言,它是思考的方法)。另外,Itzik Ben-Gan也是SQL Server公认的专家,他写过的书有《INSIDE MICROSOFT SQL SERVER 2005: T-SQL PROGRAMMING》、《INSIDE MICROSOFT SQL SERVER 2005: T-SQL QUERYING》。这本书在网上已经有下载。
Microsoft SQL Server 2008 T-SQL Fundamentals

Microsoft SQL Server 2008 T-SQL Fundamentals

  这两本书均无可争议是关于SQL Server 2008方面的经典技术书籍,绝对值得大家一读和收藏。

SQL Server , , ,

Microsoft SQL Server 2008中T-SQL对CTE的增强

2009年9月20日

         公用表表达式(CTE)是微软在SQL Server 2005中首次引入的,其类似于一个非持久性的视图。这是您在查询中定义的一个临时命名结果集,且将会在查询的FROM子句中使用。每一个CTE只定义一次(但可以在生命期内被费用多次),且生命期持续到查询结束。您可以使用CTEs来执行递归操作。下面是创建一个CTE的语法:  

 

WITH <name of your CTE>(<column names>)
AS
(
<actual query>
)

SELECT * FROM <name of your CTE> 

注意:本文章中使用AdventureWorks2008作为示例数据库。请自行从codeplex下载此数据库并安装。

使用AdventureWorks2008示例数据库的一个简单CTE的例子如下:  

 

USE AdventureWorks2008
GO
WITH AllMRContacts
AS
(
  SELECT * FROM Person.Person WHERE Title = 'Mr.'
)
SELECT LastName + ', ' + FirstName AS Contact
 FROM AllMRContacts
 ORDER BY LastName

此例子的执行结果为: 

 

Contact
-------------------
Abbas, Syed
Achong, Gustavo
Adams, Jay
Adams, Ben
Adina, Ronald
Agcaoili, Samuel 

        下面的例子使用CTE统计AdventureWorks2008示例库中销售人员的销售订单数,然后此CTE和SalesPerson表进行内连接,返回更多销售人员的信息。此示例演示了如何在查询中连接CTE。不用CTE你也可以达到相同的目的,但想像一下你不得不费力创建临时表或最终要告诫的视图并再连接回去的过程。现在你可以使用CTE,并将聚合的复杂性限制在CTE中,因此简化了代码,如下: 

 

WITH OrderCountCTE(SalesPersonID, OrderCount)
AS
(
  SELECT SalesPersonID, COUNT(*)
   FROM Sales.SalesOrderHeader
   WHERE SalesPersonID IS NOT NULL
   GROUP BY SalesPersonID
)
SELECT
  sp.BusinessEntityID,
  FirstName + ' ' + LastName as SalesPerson,
  oc.OrderCount,
  sp.SalesYTD
 FROM Sales.vSalesPerson AS sp
  INNER JOIN OrderCountCTE AS oc ON oc.SalesPersonID = sp.BusinessEntityID
 ORDER BY oc.OrderCount DESC 

  代码执行结果就像如下所示: 

 

BusinessEntityID SalesPerson OrderCount SalesYTD
----------------- ------------------------ ----------- --------------
277 Jillian Carson 473 3857163.6332
275 Michael Blythe 450 4557045.0459
279 Tsvi Reiter 429 2811012.7151
276 Linda Mitchell 418 5200475.2313
289 Jae Pak 348 5015682.3752
282 José Saraiva 271 3189356.2465
281 Shu Ito 242 3018725.4858
278 Garrett Vargas 234 1764938.9859
283 David Campbell 189 3587378.4257
290 Ranjit Varkey Chudukatil 175 3827950.238
284 Tete Mensa-Annan 140 1931620.1835
288 Rachel Valdez 130 2241204.0424
286 Lynn Tsoflias 109 1758385.926
280 Pamela Ansman-Wolfe 95 0.00
274 Stephen Jiang 48 677558.4653
287 Amy Alberts 39 636440.251
285 Syed Abbas 16 219088.8836 

  CTEs也可以用来消除自连接。请看下面的例子,这个例子中我们创建一个Products表,将插入一些重复的数据:  

CREATE TABLE Products
 (ProductID int NOT NULL,
  ProductName varchar(25),
  Price money NULL,
  CONSTRAINT PK_Products PRIMARY KEY NONCLUSTERED (ProductID)
 )
GO
INSERT INTO Products VALUES (1, 'Widgets', 25)
INSERT INTO Products VALUES (2, 'Gadgets', 50)
INSERT INTO Products VALUES (3, 'Thingies', 75)
INSERT INTO Products VALUES (4, 'Whoozits', 90)
INSERT INTO Products VALUES (5, 'Whatzits', 5)
INSERT INTO Products VALUES (6, 'Gizmos', 15)
INSERT INTO Products VALUES (7, 'Widgets', 24)
INSERT INTO Products VALUES (8, 'Gizmos', 36)
INSERT INTO Products VALUES (9, 'Gizmos', 36) 

         数据库的一个常见问题是相同的产品名却有着不同的产品ID。如果你执行一个查找重复数据的查询,这个查询将返回所有的数据,包括重复的和正常的。这将增加自动删除重复数据的困难。如果你想查找ProductName的重复数据且不包括在表出现的第一个值,你可以使用自连接,见如下代码: 

SELECT * FROM Products WHERE ProductID NOT IN
(SELECT MIN(ProductID) FROM Products AS P
 WHERE Products.ProductName = P.ProductName)

 代码执行结果如下:

 

ProductID ProductName Price
--------- ----------- -----------
8         Gizmos      36.00
9         Gizmos      36.00
7         Widgets     24.00

        你可以使用CTE改写以上的代码,以消除看上支比较费解的自连接代码。这种技术相对自连接并不能得到性能上的好处,只是代码维护上更好一些。改写后的代码如下,注意我们将CTE与Products进行了连接:

WITH MinProductRecords AS
(
  SELECT MIN(ProductID) AS ProductID, ProductName
   FROM Products
   GROUP BY ProductName
   HAVING COUNT(*) > 1
)
SELECT P.*
 FROM Products AS P
  INNER JOIN MinProductRecords AS MP
  ON P.ProductName = MP.ProductName AND P.ProductID > MP.ProductID

        使用上面的CTE检查了重复数据后,你可能想删除它们。你可能也想使用重复数据的ProductID值更新那些相关表的外键。你可以通过改写上面的CTE–将SELECE *改为DELETE–达到删除重复数据的效果:

WITH MinProductRecords AS
(
  SELECT MIN(ProductID) AS ProductID, ProductName
   FROM Products
   GROUP BY ProductName
   HAVING COUNT(*) > 1
)
DELETE Products
 FROM Products AS P
  INNER JOIN MinProductRecords AS MP
  ON P.ProductName = MP.ProductName AND P.ProductID > MP.ProductID

 (未完待续...)

SQL Server

mysql的日期和时间函数大全

2009年8月15日
近期在使用PHP+MySQL开发一个小程序,使用到PHP和MySQL中的时间和日期函数。在网上查找 了一些资料,自己整理了一下,方便自己以后查找,也希望对大家有用。 
           DAYOFWEEK(date)
返回 date 的星期索引(1 = Sunday, 2 = Monday, … 7 = Saturday)。索引值符合 ODBC 的标准。

mysql> SELECT DAYOFWEEK('1998-02-03');
        -> 3

WEEKDAY(date)
返回 date 的星期索引(0 = Monday, 1 = Tuesday, … 6 = Sunday):

mysql> SELECT WEEKDAY('1998-02-03 22:23:00');
        -> 1
mysql> SELECT WEEKDAY('1997-11-05');
        -> 2

DAYOFMONTH(date)
返回 date 是一月中的第几天,范围为 131

mysql> SELECT DAYOFMONTH('1998-02-03');
        -> 3

DAYOFYEAR(date)
返回 date 是一年中的第几天,范围为 1366

mysql> SELECT DAYOFYEAR('1998-02-03');
        -> 34

MONTH(date)
返回 date 中的月份,范围为 112

mysql> SELECT MONTH('1998-02-03');
        -> 2

DAYNAME(date)
返回 date 的星期名:

mysql> SELECT DAYNAME("1998-02-05");
        -> 'Thursday'

MONTHNAME(date)
返回 date 的月份名:

mysql> SELECT MONTHNAME("1998-02-05");
        -> 'February'

QUARTER(date)
返回 date 在一年中的季度,范围为 14

mysql> SELECT QUARTER('98-04-01');
        -> 2

WEEK(date)
WEEK(date,first)
对于星期日是一周中的第一天的场合,如果函数只有一个参数调用,返回 date 为一年的第几周,返回值范围为 053 (是的,可能有第 53 周的开始)。两个参数形式的 WEEK() 允许你指定一周是否以星期日或星期一开始,以及返回值为 0-53 还是 1-52。 这里的一个表显示第二个参数是如何工作的:

含义
0 一周以星期日开始,返回值范围为 0-53
1 一周以星期一开始,返回值范围为 0-53
2 一周以星期日开始,返回值范围为 1-53
3 一周以星期一开始,返回值范围为 1-53 (ISO 8601)
mysql> SELECT WEEK('1998-02-20');
        -> 7
mysql> SELECT WEEK('1998-02-20',0);
        -> 7
mysql> SELECT WEEK('1998-02-20',1);
        -> 8
mysql> SELECT WEEK('1998-12-31',1);
        -> 53

注意,在版本 4.0 中,WEEK(#,0) 被更改为匹配 USA 历法。 注意,如果一周是上一年的最后一周,当你没有使用 2 或 3 做为可选参数时,MySQL 将返回 0:

mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
        -> 2000, 0
mysql> SELECT WEEK('2000-01-01',2);
        -> 52

你可能会争辩说,当给定的日期值实际上是 1999 年的第 52 周的一部分时,MySQL 对 WEEK() 函数应该返回 52。我们决定返回 0 ,是因为我们希望该函数返回“在指定年份中是第几周”。当与其它的提取日期值中的月日值的函数结合使用时,这使得 WEEK() 函数的用法可靠。 如果你更希望能得到恰当的年-周值,那么你应该使用参数 2 或 3 做为可选参数,或者使用函数 YEARWEEK()

mysql> SELECT YEARWEEK('2000-01-01');
        -> 199952
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
        -> 52

YEAR(date)
返回 date 的年份,范围为 10009999

mysql> SELECT YEAR('98-02-03');
        -> 1998
YEARWEEK(date)
YEARWEEK(date,first)
返回一个日期值是的哪一年的哪一周。第二个参数的形式与作用完全与 WEEK() 的第二个参数一致。注意,对于给定的日期参数是一年的第一周或最后一周的,返回的年份值可能与日期参数给出的年份不一致:

mysql> SELECT YEARWEEK('1987-01-01');
        -> 198653

注意,对于可选参数 0 或 1,周值的返回值不同于 WEEK() 函数所返回值(0), WEEK() 根据给定的年语境返回周值。

HOUR(time)
返回 time 的小时值,范围为 023

mysql> SELECT HOUR('10:05:03');
        -> 10

MINUTE(time)
返回 time 的分钟值,范围为 059

mysql> SELECT MINUTE('98-02-03 10:05:03');
        -> 5

SECOND(time)
返回 time 的秒值,范围为 059

mysql> SELECT SECOND('10:05:03');
        -> 3

PERIOD_ADD(P,N)
增加 N 个月到时期 P(格式为 YYMMYYYYMM)中。以 YYYYMM 格式返回值。 注意,期间参数 P 不是 一个日期值:

mysql> SELECT PERIOD_ADD(9801,2);
        -> 199803

PERIOD_DIFF(P1,P2)
返回时期 P1P2 之间的月数。P1P2 应该以 YYMMYYYYMM 指定。 注意,时期参数 P1P2 不是 日期值:

mysql> SELECT PERIOD_DIFF(9802,199703);
        -> 11

DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
ADDDATE(date,INTERVAL expr type)
SUBDATE(date,INTERVAL expr type)
这些函数执行日期的算术运算。ADDDATE()SUBDATE() 分别是 DATE_ADD()DATE_SUB() 的同义词。 在 MySQL 3.23 中,如果表达式的右边是一个日期值或一个日期时间型字段,你可以使用 +- 代替 DATE_ADD()DATE_SUB()(示例如下)。 参数 date 是一个 DATETIMEDATE 值,指定一个日期的开始。expr 是一个表达式,指定从开始日期上增加还是减去间隔值。expr 是一个字符串;它可以以一个 “-” 领头表示一个负的间隔值。type 是一个关键词,它标志着表达式以何格式被解释。 下表显示 typeexpr 参数是如何关联的:

type expr 期望的格式
SECOND SECONDS
MINUTE MINUTES
HOUR HOURS
DAY DAYS
MONTH MONTHS
YEAR YEARS
MINUTE_SECOND "MINUTES:SECONDS"
HOUR_MINUTE "HOURS:MINUTES"
DAY_HOUR "DAYS HOURS"
YEAR_MONTH "YEARS-MONTHS"
HOUR_SECOND "HOURS:MINUTES:SECONDS"
DAY_MINUTE "DAYS HOURS:MINUTES"
DAY_SECOND "DAYS HOURS:MINUTES:SECONDS"

expr 的格式中,MySQL 允许任何字符作为定界符。表中所显示的是建议的定界字符。如果 date 参数是一个 DATE 值,并且计算的间隔仅仅有 YEARMONTHDAY 部分(没有时间部分),那么返回值也是一个 DATE 值。否则返回值是一个 DATETIME 值:

mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
        -> 1998-01-01 00:00:00
mysql> SELECT INTERVAL 1 DAY + "1997-12-31";
        -> 1998-01-01
mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;
       -> 1997-12-31 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
    ->                 INTERVAL 1 SECOND);
        -> 1998-01-01 00:00:00
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
    ->                 INTERVAL 1 DAY);
        -> 1998-01-01 23:59:59
mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
    ->                 INTERVAL "1:1" MINUTE_SECOND);
        -> 1998-01-01 00:01:00
mysql> SELECT DATE_SUB("1998-01-01 00:00:00",
    ->                 INTERVAL "1 1:1:1" DAY_SECOND);
        -> 1997-12-30 22:58:59
mysql> SELECT DATE_ADD("1998-01-01 00:00:00",
    ->                 INTERVAL "-1 10" DAY_HOUR);
        -> 1997-12-30 14:00:00
mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
        -> 1997-12-02

如果你指定了一个太短的间隔值(没有包括 type 关键词所期望的所有间隔部分),MySQL 假设你遗漏了间隔值的最左边部分。例如,如果指定一个 typeDAY_SECOND,那么 expr 值被期望包含天、小时、分钟和秒部分。如果你象 "1:10" 样指定一个值,MySQL 假设天和小时部分被遗漏了,指定的值代表分钟和秒。换句话说,"1:10" DAY_SECOND 被解释为等价于 "1:10" MINUTE_SECOND。这类似于 MySQL 解释 TIME 值为经过的时间而不是一天的时刻。 注意,如果依着包含一个时间部分的间隔增加或减少一个日期值,该日期值将被自动地转换到一个日期时间值:

mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 DAY);
       -> 1999-01-02
mysql> SELECT DATE_ADD("1999-01-01", INTERVAL 1 HOUR);
       -> 1999-01-01 01:00:00

如果你使用了确定不正确的日期,返回结果将是 NULL。如果你增加 MONTHYEAR_MONTHYEAR,并且结果日期的天比新月份的最大天数还大,那么它将被调整到新月份的最大天数:

mysql> SELECT DATE_ADD('1998-01-30', INTERVAL 1 MONTH);
        -> 1998-02-28

注意,上面的例子中,单词 INTERVAL 和关键词 type 是不区分字母大小写的。 

EXTRACT(type FROM date)
EXTRACT() 函数使用与 DATE_ADD()DATE_SUB() 一致的间隔类型,但是它用于指定从日期中提取的部分,而不是进行日期算术运算。

mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
       -> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
       -> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
       -> 20102

TO_DAYS(date)
给出一个日期 date,返回一个天数(从 0 年开始的天数):

mysql> SELECT TO_DAYS(950501);
        -> 728779
mysql> SELECT TO_DAYS('1997-10-07');
        -> 729669

TO_DAYS() 无意于使用先于格里高里历法(即现行的阳历)(1582)出现的值,因为它不考虑当历法改变时所遗失的天数。 

FROM_DAYS(N)
给出一个天数 N,返回一个 DATE 值:

mysql> SELECT FROM_DAYS(729669);
        -> '1997-10-07'

FROM_DAYS() 无意于使用先于格里高里历法(1582)出现的值,因为它不考虑当历法改变时所遗失的天数。 

DATE_FORMAT(date,format)
依照 format 字符串格式化 date 值。下面的修饰符可被用于 format 字符串中:

修饰符 含义
%M 月的名字 (January..December)
%W 星期的名字 (Sunday..Saturday)
%D 有英文后缀的某月的第几天 (0th, 1st, 2nd, 3rd, etc.)
%Y 年份,数字的,4 位
%y 年份,数字的,2 位
%X 周值的年份,星期日是一个星期的第一天,数字的,4 位,与 ‘%V’ 一同使用
%x 周值的年份,星期一是一个星期的第一天,数字的,4 位,与 ‘%v’ 一同使用
%a 缩写的星期名 (Sun..Sat)
%d 月份中的天数,数字的 (00..31)
%e 月份中的天数,数字的 (0..31)
%m 月,数字的 (00..12)
%c 月,数字的 (0..12)
%b 缩写的月份名 (Jan..Dec)
%j 一年中的天数 (001..366)
%H 小时 (00..23)
%k 小时 (0..23)
%h 小时 (01..12)
%I 小时 (01..12)
%l 小时 (1..12)
%i 分钟,数字的 (00..59)
%r 时间,12 小时 (hh:mm:ss [AP]M)
%T 时间,24 小时 (hh:mm:ss)
%S 秒 (00..59)
%s 秒 (00..59)
%p AMPM
%w 一周中的天数 (0=Sunday..6=Saturday)
%U 星期 (00..53),星期日是一个星期的第一天
%u 星期 (00..53),星期一是一个星期的第一天
%V 星期 (01..53),星期日是一个星期的第一天。与 ‘%X’ 一起使用
%v 星期 (01..53),星期一是一个星期的第一天。与 ‘%x’ 一起使用
%% 一个字母 “%”

所有其它的字符不经过解释,直接复制到结果中:

mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
        -> 'Saturday October 1997'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
        -> '22:23:00'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%D %y %a %d %m %b %j');
        -> '4th 97 Sat 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%H %k %I %r %T %S %w');
        -> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
        -> '1998 52'

在 MySQL 3.23 中,在格式修饰符前需要字符 `%’。在更早的 MySQL 版本中,`%’ 是可选的。 月份与天修饰符的范围从零开始的原因是,在 MySQL 3.23 中,它允许存储不完善的日期值(例如 '2004-00-00')。 

TIME_FORMAT(time,format)
它的使用方法与上面的 DATE_FORMAT() 函数相似,但是 format 字符串只包含处理小时、分和秒的那些格式修饰符。使用其它的修饰符会产生一个 NULL 值或 0。 
CURDATE()
CURRENT_DATE
'YYYY-MM-DD'YYYYMMDD 格式返回当前的日期值,返回的格式取决于该函数是用于字符串还是数字语境中:

mysql> SELECT CURDATE();
        -> '1997-12-15'
mysql> SELECT CURDATE() + 0;
        -> 19971215

CURTIME()
CURRENT_TIME
'HH:MM:SS'HHMMSS 格式返回当前的时间值,返回的格式取决于该函数是用于字符串还是数字语境中:

mysql> SELECT CURTIME();
        -> '23:50:26'
mysql> SELECT CURTIME() + 0;
        -> 235026

NOW()
SYSDATE()
CURRENT_TIMESTAMP
'YYYY-MM-DD HH:MM:SS'YYYYMMDDHHMMSS 格式返回当前的日期时间值,返回的格式取决于该函数是用于字符串还是数字语境中:

mysql> SELECT NOW();
        -> '1997-12-15 23:50:26'
mysql> SELECT NOW() + 0;
        -> 19971215235026

注意,函数 NOW() 在每个查询中只计算一次,也就是在查询开始执行时。这就是说,如果在一个单独的查询中多次引用了 NOW(),它只会给出值都是一个相同的时间。 

UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
如果调用时没有参数,以无符号的整数形式返回一个 Unix 时间戳(从 '1970-01-01 00:00:00' GMT 开始的秒数)。如果以一个参数 date 调用 UNIX_TIMESTAMP(),它将返回该参数值从 '1970-01-01 00:00:00' GMT 开始经过的秒数值。date 可以是一个 DATE 字符串,一个 DATETIME 字符串,一个 TIMESTAMP,或者以一个 YYMMDDYYYYMMDD 显示的本地时间:

mysql> SELECT UNIX_TIMESTAMP();
        -> 882226357
mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
        -> 875996580

UNIX_TIMESTAMP 被用于一个 TIMESTAMP 列时,函数直接返回一个内部的时间戳值,而不进行一个隐含地 “string-to-unix-timestamp” 转换。如果你传递一个超出范围的日期参数给 UNIX_TIMESTAMP() ,它将返回 0,但是请注意,MySQL 对其仅仅进行基本的检验(年范围 1970-2037,月份 01-12,日期 01-31)。 如果你希望减去 UNIX_TIMESTAMP() 列,你应该需要将结果强制转换为一有符号整数。查看章节 6.3.5 Cast 函数。 

FROM_UNIXTIME(unix_timestamp [,format])
'YYYY-MM-DD HH:MM:SS'YYYYMMDDHHMMSS 格式返回一个 unix_timestamp 参数值,返回值的形式取决于该函数使用于字符串还是数字语境。 如果 format 给出,返回值依 format 字符串被格式。format 可以包含与 DATE_FORMAT() 函数同样的修饰符。

mysql> SELECT FROM_UNIXTIME(875996580);
        -> '1997-10-04 22:23:00'
mysql> SELECT FROM_UNIXTIME(875996580) + 0;
        -> 19971004222300
mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),
                            '%Y %D %M %h:%i:%s %x');
        -> '1997 23rd December 03:43:30 1997'

SEC_TO_TIME(seconds)
'HH:MM:SS'HHMMSS 格式返回参数 seconds 被转换到时分秒后的值,返回值的形式取决于该函数使用于字符串还是数字语境:

mysql> SELECT SEC_TO_TIME(2378);
        -> '00:39:38'
mysql> SELECT SEC_TO_TIME(2378) + 0;
        -> 3938

TIME_TO_SEC(time)
将参数 time 转换为秒数后返回:

mysql> SELECT TIME_TO_SEC('22:23:00');
        -> 80580
mysql> SELECT TIME_TO_SEC('00:39:38');
        -> 2378

MySQL , , , ,