您好,欢迎来到思海网络,我们将竭诚为您提供优质的服务! 诚征网络推广 | 网站备案 | 帮助中心 | 软件下载 | 购买流程 | 付款方式 | 联系我们 [ 会员登录/注册 ]
促销推广
客服中心
业务咨询
有事点击这里…  531199185
有事点击这里…  61352289
点击这里给我发消息  81721488
有事点击这里…  376585780
有事点击这里…  872642803
有事点击这里…  459248018
有事点击这里…  61352288
有事点击这里…  380791050
技术支持
有事点击这里…  714236853
有事点击这里…  719304487
有事点击这里…  1208894568
有事点击这里…  61352289
在线客服
有事点击这里…  531199185
有事点击这里…  61352288
有事点击这里…  983054746
有事点击这里…  893984210
当前位置:首页 >> 技术文章 >> 文章浏览
技术文章

SQL Server 2000 XML之三种模式

添加时间:2013-4-28 17:36:57  添加: 思海网络 

XML,已成为近来最热门的Web技术,它是SQL Server 2000中的重要部分。本文将综合七条SQL Server 2000中最重要的XML综合特性组成XML之七种兵器。
  兵器之一:FOR XML

  在SQL Server 2000中,标准的T-SQL SELECT语句包括FOR XML子句,它以XML文档形式返回一个查询结果。新的FOR XML子句有三种模式——RAW,AUTO,和EXPLICIT,每个都能对XML文档格式提供附加标准的控制。

  下面首先介绍“FOR XML”的使用方法。

  为了从SQL Server提取XML格式的数据,T-SQL中加入了一个FOR XML命令。在查询命令中使用FOR XML命令使得查询结果以XML格式出现。FOR XML命令有三种模式:RAW,AUTO和EXPLICIT。图1所显示的SQL命令访问SQL Server提供的Pubs示例数据库。有关Pubs数据库的更多信息,请参见MSDN说明。如果我们依次指定该SQL命令的模式为三种允许的模式之一,就可以得到各种模式所支持的不同XML输出。

【图1 】



SELECT store.stor_id as Id, stor_name as Name,

sale.ord_num as OrderNo,sale.qty as Qty

FROM stores store inner join

sales sale on store.stor_id = sale.stor_id

ORDER BY stor_name

FOR XML <模式>

  该查询命令所生成的结果包含所有销售记录及其对应的商店,结果以商店名称的字母升序排列。查询的最后加上了FOR XML命令以及具体的模式,比如FOR XML RAW。

  理想情况下,SQL命令所生成的XML文档应具有如下结构:

<Stores>

<Store Id=&single;&single; Name=&single;&single;>

</Sale OrderNo=&single;&single; Qty=&single;&single;>

</Store>

</Stores>

  下面我们来看看具体的处理方法。

  RAW模式

  下面是指定RAW模式时结果XML文档的一个片断。





  查询结果集中每一个记录包含唯一的元素<row>。由于我们无法控制元素名字和文档结构,因此这种模式不是很有用。RAW模式所生成的文档结构与我们所希望的不符,而且它的用途也非常有限。

  AUTO模式

  下面是指定AUTO模式时结果文档的一个片断:



  可以看到,<Stroe>和<Sale>两个元素是父-子关系,形成了我们所希望的层次结构。这种节点关系由查询中表的声明次序决定,后声明的表成为前声明表的孩子。

  再参考图1,我们可以看出查询命令所指定的别名决定了XML文档中的名字。根据这一点,我们可以控制XML文档元素、属性的名字,使得这些名字符合我们所要求的命名惯例。

  可见AUTO模式能够创建出我们所需要的XML文档。不过它存在以下缺点:

  虽然可以得到层次结构,但这种层次结构是线性的,即每个父节点只能有一个子节点,反之亦然。

  通过别名指定元素名字不太方便,而且有时候会影响查询命令本身的可读性。

  无法在文档中同时生成元素和属性。要么全部是元素(通过ELEMENTS关键词指定),要么全部是属性(默认)。 EXPLICIT模式解决了上述不足。


 EXPLICIT模式



  EXPLICIT模式比较复杂,我们将用另外一种方法来表达图1所显示的查询。这种方法使得我们能够完全地控制查询所生成的XML文档。首先我们将介绍如何改用EXPLICIT模式编写图1所显示的查询,然后看看这种方法如何赋予我们远远超过AUTO模式的能力。

  下面是图1查询用EXPLICIT模式表达的代码:

【图2 】

--商店数据
SELECT 1 as Tag,
NULL as Parent,
s.stor_id as [store!1!Id],
s.stor_name as [store!1!Name],
NULL as[sale!2!OrderNo],
NULL as [sale!2!Qty]
FROM stores s
UNION ALL
-- 销售数据
SELECT 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty
FROM stores s, sales sa
WHERE s.stor_id = sa.stor_id
ORDER BY [store!1!name]
FOR XML EXPLICIT

  这个查询初看起来有点复杂,其实它只是把不同的数据集(即这里的Store和Sale)分解到了独立的SELECT语句里,然后再用UNION ALL操作符连结成一个查询。

  我们之所以要把查询写成上面的形式,是为了让查询结果不仅包含XML文档所描述的数据,而且还包含描述XML文档结构的元数据。上述查询所生成的表称为Universal表,sqlxml.dll生成XML文档时需要这种格式。Universal表对于编写代码的人来说是透明的,但了解这个表还是很有意义的,它将有助于代码的开发和调试。下面是Universal表的一个例子:

Tag Parent store!1!id store!1!name sale!2!orderno sale!2!qty
1 NULL 7066 Barnum&single;s NULL NULL
2 1 7066 Barnum&single;s A297650 50
2 1 7066 Barnum&single;s QA7442 375
1 NULL 8042 Bookbeat NULL NULL
2 1 8042 Bookbeat 423LL9 2215

  Universal表和EXPLICIT模式查询的元数据部分都以红色表示,黑色表示数据。比较查询和表就可以找出sqlxml.dll生成XML文档所需要的元素。我们来仔细地分析一下它们描述的是什么。

  Tag和Parent列是XML文档层次结构方面的信息,我们可以认为图2中的每个SELECT语句代表了一个XML节点,而Tag和Parent列让我们指定节点在文档层次结构中的位置。如果在第二个SELECT语句中指定Tag为2、指定Parent为1,就表示为这些数据加上了一个值为2的标签,而这些数据的父亲是那些标签为1的数据(即第一个SELECT语句)。这就使得我们能够构造出<Store>和<Sale>之间的父-子关系,而且正如你可能猜想到的,它使得我们可以生成任意合法的XML文档结构。注意第一个SELECT命令的parent列设置成了NULL,这表示<Store>元素处于最顶层的位置。

  以黑色表示的数据将成为节点的属性或元素,例如,Store_ID就通过列名提供了这方面的信息。列名字中的“!”是分隔符,总共可分成四项(四个参数),其中第四个参数是可选的。这些参数描述的是:

  第一个参数描述该列所属元素的名字,在这里是<Store>元素。

  第二个是标签编号,它指定了该列信息在XML树形结构中所处位置。

  第三个参数指定XML文档内的属性或元素名字。在这里名字指定为id。

  数据列默认被创建为参数2所指定节点的属性,即id将成为<Store>节点的属性。如果要指定id是<Store>的一个子元素,我们可以使用第四个可选的参数,这个参数的一个作用就是让我们把该项指定为元素,例如store!1!id!element。

  由于使用了UNION ALL操作符来连结SELECT语句,为了保证SQL查询的合法性,所有SELECT语句的选择结果必须具有相同数量的列。我们使用NULL关键词来补足SELECT语句,从而避免了重复数据。

  通过EXPLICIT模式查询所生成的XML文档和通过AUTO模式生成的完全相同,那么为什么要创建EXPLICIT模式查询呢?

  假设现在有人要求在XML文档中包含商店的打折信息。查看Pubs数据库,我们得知每个商店都可以有0到n范围内的折扣率。因此,一种合理的方法是在<Store>元素下面加上子元素<Discount>,这样我们就得到如下XML文档结构:

<STORES>
<STORE Id=&single;&single; Name=&single;&single;>
<DISCOUNT Type=&single;&single; LowQty=&single;&single; HighQty=&single;&single;>
<AMOUNT></AMOUNT>
</DISCOUNT>
<SALE OrdNo=&single;&single; Qty=&single;&single;>
</SALE>
</STORE>
</STORES>

  这里的改动包括:

  要在<Sale>元素所在的层次增加一个XML元素<Discount>,即<Discount>是<Stroe>的子元素。

  Amount嵌套在<Discount>里面,但不应该是<Discount>元素的属性。

  在AUTO模式中是不可能实现这些改动的。

  下面是创建这个新XML文档的EXPLICIT模式查询:

【图 2A】

SELECT 1 as Tag, NULL as Parent,
s.stor_id as [Store!1!id],
s.stor_name as [Store!1!name],
NULL as [Sale!2!orderno],
NULL as [Sale!2!1ty],
NULL as [Discount!3!type],
NULL as [Discount!3!lowqty],
NULL as [Discount!3!highqty],
NULL as [Discount!3!amount!element]
FROM stores s
UNION ALL
SELECT 2, 1,
s.stor_id,
s.stor_name,
sa.ord_num,
sa.qty,
NULL,
NULL,
NULL,
NULL
FROM stores s, sales sa
WHERE s.stor_id = sa.stor_id
UNION ALL
SELECT 3, 1,
NULL,
s.stor_name,
NULL,
NULL,
d.discounttype,
d.lowqty,
d.highqty,
d.discount
FROM stores s, discounts d
WHERE s.stor_id = d.stor_id
ORDER BY [store!1!name]
For XML EXPLICIT

  为了创建图2A所显示的EXPLICIT模式查询,我们对图2的查询进行了如下修改:

  增加了第三个子查询提取折扣数据,通过Tag列声明这些数据的标签值为3。

  通过指定Parent列为1将折扣数据设置成<Store>元素的子元素。

  注意在第三个SELECT子查询中我们只包含了那些必需的列,并用NULL补足空列。这个子查询包含store_name列,虽然Discount元素并不要用到这个列,但如果把这个列也设置为NULL,则结果Universal表将不会按照解析器所要求的那样以节点升序排序(不妨自己试一下看看)。Universal表的排序列也可以用Tag列替代。

  为维持结果Universal表的完整性,第一、二两个SELECT语句也用NULL补足以反映为折扣数据增加的列。

  为指定新折扣列的元数据修改了第一个SELECT语句。

  通过在第四个参数中声明element指定Amount列为Discount的一个元素(element是可在第四个参数中声明的多个指令之一)。

  下面这个XML文档只能用EXPLICIT模式生成:





  结果XML文档中不会显示出NULL数据,如折扣lowqty和highqty。

  看来上面的介绍,大家可能已经对FOR XML的语法有所了解。通过FOR XML 我们在能够在Query Analyzer 中直接返回一个XML格式的数据或者通过其他多样化表现方式将XML格式的数据显示出来,比如可以将数据显示在浏览器上。下面这个例子就使用FOR XML和ADO将数据输出到浏览器的例子。


Dim adoConn
Set adoConn = Server.CreateObject("ADODB.Connection")

Dim sConn
sConn = "Provider=SQLOLEDB;Data Source=192.168.0.160;Initial Catalog=Northwind;User ID=SA;Password=;"
adoConn.ConnectionString = sConn
adoConn.CursorLocation = adUseClient
adoConn.Open

Dim adoCmd
Set adoCmd = Server.CreateObject("ADODB.Command")
Set adoCmd.ActiveConnection = adoConn

Dim sQuery
‘定义 FOR XML的查询。具体的语法在以后的章节中将详细介绍。
sQuery = "<ROOT xmlns:sql='urn:schemas-microsoft-com:xml-sql'><sql:query>SELECT * FROM PRODUCTS ORDER BY PRODUCTNAME FOR XML AUTO</sql:query></ROOT>"

‘建立ADODB Stream 对象,ADODB Stream 对象需要ADO2.5以上版本支持,它可以将记录集转换为数据流。
Dim adoStreamQuery
Set adoStreamQuery = Server.CreateObject("ADODB.Stream")
adoStreamQuery.Open
adoStreamQuery.WriteText sQuery, adWriteChar
adoStreamQuery.Position = 0
adoCmd.CommandStream = adoStreamQuery
adoCmd.Dialect = "{5D531CB2-E6Ed-11D2-B252-00C04F681B71}"

Response.write "Pushing XML to client for processing " & "<BR/>"

adoCmd.Properties("Output Stream") = Response
‘输出XML格式的文本
Response.write "<XML ID=MyDataIsle>"
adoCmd.Execute , , adExecuteStream
Response.write "</XML>"

‘通过IE的XML解析器,使用DOM方法将XML的文本转换为HTML
关键字:SQL Server、XML、数据流

分享到:

顶部 】 【 关闭
版权所有:佛山思海电脑网络有限公司 ©1998-2024 All Rights Reserved.
联系电话:(0757)22630313、22633833
中华人民共和国增值电信业务经营许可证: 粤B1.B2-20030321 备案号:粤B2-20030321-1
网站公安备案编号:44060602000007 交互式栏目专项备案编号:200303DD003  
察察 工商 网安 举报有奖  警警  手机打开网站