<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>张文杰的博客 &#187; T-SQL</title>
	<atom:link href="http://zhangwenjie.net/archives/tag/t-sql/feed" rel="self" type="application/rss+xml" />
	<link>http://zhangwenjie.net</link>
	<description>技术、生活博客</description>
	<lastBuildDate>Mon, 24 Oct 2011 14:23:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>SQL Server 2008中的XML-XML数据类型</title>
		<link>http://zhangwenjie.net/archives/133</link>
		<comments>http://zhangwenjie.net/archives/133#comments</comments>
		<pubDate>Sat, 05 Dec 2009 14:24:35 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[foreign keys]]></category>
		<category><![CDATA[primary keys]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[主键]]></category>
		<category><![CDATA[外键]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=133</guid>
		<description><![CDATA[SQL server 2005中引入了一个新的数据类型:xml.这个新数据类型是用来操作XML数据的，现在SQL Server 2008进一步增强了它的功能。使用这种新的数据类型，可以以本机格式存储 XML、 查询 XML 中的数据、 轻松有效地修改 XML 中的数据且无需涉及改动全部的内容，同样也可以索引XML中数据...]]></description>
			<content:encoded><![CDATA[<p>　　SQL server 2005中引入了一个新的数据类型:xml.这个新数据类型是用来操作XML数据的，现在SQL Server 2008进一步增强了它的功能。使用这种新的数据类型，可以以本机格式存储 XML、 查询 XML 中的数据、 轻松有效地修改 XML 中的数据且无需涉及改动全部的内容，同样也可以索引XML中的数据。您可以以下方式使用 xml ：</p>
<ul>
<li>一个变量</li>
<li>在存储过程或自定义函数中作为参数</li>
<li>自定义函数的返回值</li>
<li>一个表的一列</li>
</ul>
<p>　　在这里您也应应意识到 xml 数据类型的一些限制。虽然xml数据类型可以包含NULL值，但不像其它的本机数据类型，您不能直接比较两个 xml 数据类型的实例。（不过您可以将xml实例转换为 TEXT 数据类型，然后再做比较。）任何相等比较需要先将xml 类型转换为字符类型。此限制也意味着您不能在 ORDER BY 或 GROUP BY子句中使用xml 数据类型。还有几个其他限制，我们稍后会更详细地讨论。</p>
<p>　　这似乎是相当严重的限制，但在正确使用时他们不会真正影响到 xml 数据类型。xml 数据类型也有一个丰富的功能集，这算是对这些限制的一些补偿。</p>
<p>　　<strong>作为变量使用XML数据类型</strong></p>
<p><strong>　　</strong>让我们首先编写一些使用新的 xml 数据类型的变量的代码。和使用任何其他 TRANSACT-SQL (T-SQL) 变量一样,您只需声明它,然后分配值给它，如在下面的示例中，使用一段XML来表示一个销售代表的数据为：<br />
　　DECLARE @xmlData AS XML;<br />
　　SET @xmlData=&#8217;<br />
　　　&lt;Customers&gt;<br />
　　　  &lt;CustomerID&gt;TELRK&lt;/CustomerID&gt;<br />
　　　  &lt;CompanyName&gt;Telerik, Inc&lt;/CompanyName&gt;<br />
　　　  &lt;ContactName&gt;Stephen Forte&lt;/ContactName&gt;<br />
　　　  &lt;ContactTitle&gt;Sales Representative&lt;/ContactTitle&gt;<br />
　　　  &lt;Address&gt;5-9 Union Square West&lt;/Address&gt;<br />
　　　  &lt;City&gt;New York&lt;/City&gt;<br />
　　　  &lt;PostalCode&gt;10028&lt;/PostalCode&gt;<br />
　　　  &lt;Country&gt;USA&lt;/Country&gt;<br />
　　　  &lt;Phone&gt;030-0074321&lt;/Phone&gt;<br />
　　　  &lt;Fax&gt;030-0076545&lt;/Fax&gt;<br />
　  &lt;/Customers&gt;&#8217;;<br />
　　SELECT @xmlData;<br />
　　</p>
<p>　　这个很基本的示例显示了像声明任何其他任何本机 SQL Server 数据类型一样使用 DECLARE 语句声明一个 XML 变量。该变量然后被分配了一个值。很奇怪的是，一个表示XML 数据的字符串分配给了xml 的数据类型，xml数据奖这个字符串解析成 XML。（同样，基于公共语言运行库用户定义类型也支持且需要相同的功能。）该示例同时还检查XML格式的正确性，如验证元素的开始和结束标记是否匹配。</p>
<p>　　最后一个语句通过一个SELECT 语句将XML返回给调用方，结果将在单行单列中显示xml数据。让数据库认识到您正在使用 XML数据 （而不是恰好是 XML的原始文本）的另一个好处是xml数据在 SQL Server Management Studio 呈现为超链接。点击超链接会打开一个新窗口，包含了格式化好的xml数据（使用 Windows Internet Explorer XML 模板），同时带有颜色高亮及可折叠/可展开节点。如果您然后在XML 结果窗口的标题栏上右键单击，您将看到一些有用的选项，如将 XML 保存到文件。</p>
<p>　　<strong>在表中使用XML数据</strong></p>
<p><strong>　　</strong>如之前所说，您也可以像如下的例子一样在一个表中将一列定义为xml:</p>
<p>　　USE AdventureWorks2008</p>
<p>　　GO</p>
<p>　　CREATE TABLE OrdersXML<br />
　　  (OrderDocID int PRIMARY KEY,<br />
　　   xOrders <span>xml</span> NOT NULL)</p>
<p>　　如刚才所说，xml数据类型存在一些限制，在将xml定义为表的一列时限制如下：</p>
<ul>
<li>它不能定义为主键</li>
<li>它不能定义为外键</li>
<li>不能将它定义为惟一约束(UNIQUE constraint)</li>
<li>不能在定义中使用COLLATE关键字</li>
</ul>
<p>　　我们之前说过不能比较两个xml实例的相等性。主键、外键、惟一约束都需要能比较包含的数据，因此xml数据不能在这些情况下使用。SQL Server的<span>COLLATE语句对xml数据类型来说是没有意义的，因为SQL Server并不是将xml数存储为文本，而是使用特定于xml的编码。</span></p>
<p><span>　　现在让我们在此列中插入一些数据。这个例子使用硬编码的xml数据，先存放到一个xml变量中，然后插入到我们刚刚创建的<span>OrdersXML表中：</span></span></p>
<p><span><span>　　DECLARE @xmlData AS XML；<br />
 　　SET @xmlData = &#8216;<br />
　　　&lt;Orders&gt;<br />
　　　  &lt;Order&gt;<br />
　　　    &lt;OrderID&gt;5&lt;/OrderID&gt;<br />
　　　    &lt;CustomerID&gt;65&lt;/CustomerID&gt;<br />
　　　    &lt;OrderAmount&gt;25&lt;/OrderAmount&gt;<br />
　　  &lt;/Order&gt;<br />
　　&lt;/Orders&gt;&#8217;；</span></span></p>
<p>　　INSERT INTO OrdersXML (OrderDocID, xOrders) Values (1, @xmlData)；</p>
<p><span><span>　　你可以有多种方式将xml数据插入到列中：XML Bulk Load（我们稍候会讨论） ；从XML变量中加载（如例子所示）；使用FOR XML TYPE特性从SELECT语句中加载，这个一会将讲到。只的格式良好的XML（包括片段）才能插入到表中，任何将非法格式XML数据插入表的尝试将导致一个异常，如下所示：</span></span></p>
<p><span><span>　　INSERT INTO OrdersXML (OrderDocID, xOrders) VALUES (3, &#8216;&lt;nm&gt;steve&lt;/NM&gt;&#8217;)；</span></span></p>
<p><span><span>　　这将产生如下的错误消息：</span></span></p>
<div>
<pre>　　Msg 9436, Level 16, State 1, Line 1
　　XML parsing: line 1, character 14, end tag does not match start tag</pre>
</div>
<p>　　(末完待续&#8230;)</p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/133/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft SQL Server 2008中T-SQL对CTE的增强(续)</title>
		<link>http://zhangwenjie.net/archives/119</link>
		<comments>http://zhangwenjie.net/archives/119#comments</comments>
		<pubDate>Fri, 20 Nov 2009 13:39:36 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[CTE]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=119</guid>
		<description><![CDATA[CTEs的真正强大之处在于对树状结构的数据上执行的分层(hierarchical)递归查询。实事上，除了符合ANSI SQL-92标准之外，这也是Microsoft构建CTEs的主要原因...]]></description>
			<content:encoded><![CDATA[<p>　　CTEs的真正强大之处在于对树状结构的数据上执行的分层(hierarchical)递归查询。实事上，除了符合ANSI SQL-92标准之外，这也是Microsoft构建CTEs的主要原因。一个递归CTE同至少两部分查询组成:首先，锚成员(anchor member)是一个非递归查询；第二个，递归成员(recursive member)是一个递归查询。在CTE定义的括号里(AS语句之后),查询定义为独立的或引用同一CTE。锚成员或递归成员由UNION ALL语句分开。锚成员只会被调用一次；递归成员会被重复调用，直到没有行被返回。下面是语法:</p>
<p>WITH SimpleRecursive(field names)<br />
AS<br />
(<br />
   &lt;Select Statement for the Anchor Member&gt;</p>
<p>   UNION ALL</p>
<p>   &lt;Select Statement for the Recursive Member&gt;<br />
)</p>
<p>SELECT * FROM SimpleRecursive</p>
<p>下面的代码将演示这些特性。下面的代码创建了一个employees表，表中有一个自引用到<span>EmployeeID的字段：<span>ReportsTo。我们将编写一个查询得到所有向Stephen (<span>EmployeeID=2</span><a name="who report"></a>)报告的员工及向Stephen下级报告的员工。</span></span></p>
<p><em> 测试表：</em></p>
<table border="1" cellspacing="0" cellpadding="5" width="*">
<tbody>
<tr>
<td>
<pre>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)</pre>
</td>
</tr>
</tbody>
</table>
<p><em> 递归查询代码：</em></p>
<table border="1" cellspacing="0" cellpadding="5" width="*">
<tbody>
<tr>
<td>
<pre>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</pre>
</td>
</tr>
</tbody>
</table>
<p>下面是查询结果：</p>
<pre>Employee    Boss
<span>----------- ------------</span>
Stephen     Richard
Clemens     Stephen
Malek       Stephen
Goksin      Malek
Ramesh      Goskin</pre>
<p>　　递归查询以EmployeeID = 2开始(SELECT之后的锚成员),此查询将获取相应的记录，然后由递归查询获取向Stephen报告的员工记录及相应记录的下级。(例如Goksin向Malek汇报, 以及 Malek 向Stephen汇报.)。然后每个子递归尝试获取上次递归找到的员工的下级。最后，递归将返回空记录，这将导致递归结束(这就是为什么没有Kimberly记录的原因)。如果将上述代码中的的锚成员改为<span><a name="EmployeeID"></a>EmployeeID = 1，查询将返回Kimberly记录。</span></p>
<p><span>　　从设计上讲，递归成员将一直查询下级员工(对本例来说)并无限持续下去。如果你怀疑递归过多并想限制递归调用的次数，你可以在CTE的外查询(见下例)中指定OPTION子句的<span>MAXRECURSION选项。如:OPTION(MAXRECURSION 25)</span></span></p>
<p><span><span>　　这个选项将促使SQL Server在递归深度超过指定限制时产生一个错误。缺省时，这个限制是100(就是在你忽略这个选项时)。如果你想彻底取消此选项的作用，你需要指定<span>MAXRECURSION为０。你可以通过指定<span>MAXRECURSION选项</span>用和上面一样的代码来取得最上两级员工：</span></span></span></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="5" width="*">
<tbody>
<tr>
<td>
<pre>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
<span>OPTION(MAXRECURSION 2)</span></pre>
</td>
</tr>
</tbody>
</table>
<p>下面中结果:<br />
Employee Boss<br />
<span>&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;</span><br />
Stephen Richard<br />
Clemens Stephen<br />
Malek Stephen<br />
Goksin Malek</p>
<p>　　你同时会看到如下的错误信息：</p>
<p>Msg 530, Level 16, State 1, Line 2<br />
The statement terminated. The maximum recursion 2 has been exhausted<br />
before statement completion.</p>
<p>　    为了避免这种错误，一种方法是用一个产生列(generated column)来跟踪当前的层级并在WHERE子句中使用这个产生列作为限制条件,而不使用<span>MAXRECURSION选项。下面是修改过的代码，它将返回和上述同样的数据，但不会产生错误信息：</span></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="5" width="*">
<tbody>
<tr>
<td>
<pre>WITH SimpleRecursive(EmployeeID, EmployeeName, ReportsTo, <span>SubLevel</span>)
AS
(
  SELECT EmployeeID, EmployeeName, ReportsTo, <span>0</span>
   FROM EmployeeTree WHERE EmployeeID = 2
  UNION ALL
  SELECT p.EmployeeID, p.EmployeeName, p.ReportsTo, <span>SubLevel + 1</span>
   FROM EmployeeTree AS P
    INNER JOIN SimpleRecursive A ON A.EmployeeID = P.ReportsTo
    <span>WHERE SubLevel &lt;= 2</span>
)
SELECT sr.EmployeeName AS Employee, et.EmployeeName AS Boss
 FROM SimpleRecursive sr
  INNER JOIN EmployeeTree AS et ON sr.ReportsTo = et.EmployeeID</pre>
</td>
</tr>
</tbody>
</table>
<p>　　另外，SQL Server 2008引入了一个<span>hierarchyid新数据类型，可以比我们刚才看到的递归代码实现更强大树形结构数据。等有机会我们再探讨。</span></p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/119/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>推荐两本关于SQL Server 2008的经典书</title>
		<link>http://zhangwenjie.net/archives/105</link>
		<comments>http://zhangwenjie.net/archives/105#comments</comments>
		<pubDate>Fri, 23 Oct 2009 16:19:18 +0000</pubDate>
		<dc:creator>zhangwenjie</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[DBCC]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://zhangwenjie.net/?p=105</guid>
		<description><![CDATA[在此，我向大家推荐两本关于SQL Server 2008的经典书箱:Microsoft SQL Server 2008 Internals及Microsoft SQL Server 2008 T-SQL Fundamentals...]]></description>
			<content:encoded><![CDATA[<p>　　 SQL Server 2008是微软最新推出的数据库系统，它比SQL Server 2005更成熟、更强大，性能也更好。对于Windows平台下的程序员，学习SQL Server将是不可避免的。于是，选择经典、权威的书籍将事半功倍。尽管我将的书籍是英文原版的，但它仍然是不可替代的。另外，学习英文也是程序员的一项基础功能。</p>
<ul>
<li><strong>Microsoft SQL Server 2008 Internals</strong>。这本书是由六位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内幕的开发人员，此书绝对是不可少的。</li>
</ul>
<p>　　　本书是讲述SQL Server关系数据库引擎内部机理和架构的权威指南。书中详细阐述了SQL Server处理查询、管理数据的相关内容，包括SQL   Server架构和配置、跟踪/扩展事件、日志和恢复、索引、表格、查询优化、事务/并发以及DBCC。.</p>
<p>　　　本书适合中高级数据库开发人员阅读。</p>
<p>　</p>
<div id="attachment_106" class="wp-caption aligncenter" style="width: 254px"><img class="size-medium wp-image-106" title="microsoft sql server 2008 internals" src="http://zhangwenjie.net/wp-content/uploads/2009/10/sqlserver-244x300.jpg" alt="microsoft sql server 2008 internals" width="244" height="300" /><p class="wp-caption-text">microsoft sql server 2008 internals</p></div>
<ul>
<li><span><strong>Microsoft SQL Server 2008 T-SQL Fundamentals</strong>。此书是由Itzik Ben-Gan写的，是一本讲解SQL Server 2008基础知识的书，但这不意味着它很简单；相反此书却相当有深度，也就是对基础知识后面的逻辑知识有深入的介绍，同时也提供了难得的在真实开发中使用SQL的经验和建议。正如作者所说：For me, T-SQL is more than just a language—it&#8217;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》。这本书在网上已经有下载。</span></li>
</ul>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Microsoft SQL Server 2008 T-SQL Fundamentals" src="http://ec4.images-amazon.com/images/I/51WsPQxvHJL._AA500_.jpg" alt="Microsoft SQL Server 2008 T-SQL Fundamentals" width="500" height="500" /><p class="wp-caption-text">Microsoft SQL Server 2008 T-SQL Fundamentals</p></div>
<p>　　这两本书均无可争议是关于SQL Server 2008方面的经典技术书籍，绝对值得大家一读和收藏。</p>
]]></content:encoded>
			<wfw:commentRss>http://zhangwenjie.net/archives/105/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

