D. 指定 xml 命令
除了不对包含数据进行实体编码外("<"字符仍是"<"),xml 命令与 element 命令相似。例如,
如果 Customers 表中有一位客户联系人的姓名是 Mar<ia Andears,则下面的查询不对包含数据进
行实体编码,并将生成无效的 XML 文档。
-- Update a customer record. UPDATE Customers SET ContactName='Mar<ia Anders' WHERE ContactName='Maria Anders' GO
下面的查询返回客户 ID 和联系人姓名信息。
编写生成通用表的查询的过程和对通用表行集进行处理以生成所得到的 XML 文档的过程,与在示例
A 或示例 B 中描述的过程相似。
SELECT 1 as Tag, NULL as Parent, Customers.CustomerID as [Customer!1!CustomerID], Customers.ContactName as [Customer!1!ContactName!xml] FROM Customers ORDER BY [Customer!1!CustomerID] FOR XML EXPLICIT GO -- Set customer record back to the original. UPDATE Customers SET ContactName='Maria Anders' WHERE ContactName='Mar<ia Anders' GO
下面显示部分结果。因为在查询中指定了该命令,所以指定的特性名是包含元素的名称。
<Customer CustomerID="ALFKI"> <ContactName>Mar<ia Anders</ContactName> </Customer> <Customer CustomerID="ANATR"> <ContactName>Ana Trujillo</ContactName> </Customer>
E. 指定隐藏命令
下例说明 hide 命令的使用。当希望查询返回一个特性以便对该查询所返回的通用表中的行进行排序,
但是不希望该特性出现在最终所得到的 XML 文档中时,该命令很有用。
假定希望生成下面的层次结构,在该结构中 <Customer> 元素按 CustomerID 进行排序,并且在
每个 <Customer> 元素中,<Order> 元素按 OrderID 进行排序。注意 OrderID 特性不出现在所得
到的 XML 文档中:
<Customer CustomerID="ALFKI"> <Order OrderDate="1997-08-25T00:00:00" /> <Order OrderDate="1997-10-03T00:00:00" /> <Order OrderDate="1997-10-13T00:00:00" /> </Customer>
在这种情况下,为排序而检索 OrderID,但是在为该特性指定列名时指定 hide 命令。结果,OrderID
特性不显示为所得到的 XML 文档的一部分。
编写生成通用表的查询的过程和对通用表行集进行处理以生成所得到的 XML 文档的过程,与在示例 A
或示例 B 中描述的过程相似。
以下是查询语句:
SELECT 1 as Tag, NULL as Parent, Customers.CustomerID as [Customer!1!CustomerID], NULL as [Order!2!OrderID!hide], NULL as [Order!2!OrderDate] FROM Customers UNION ALL SELECT 2, 1, Customers.CustomerID, Orders.OrderID, Orders.OrderDate FROM Customers, Orders WHERE Customers.CustomerID = Orders.CustomerID ORDER BY [Customer!1!CustomerID], [Order!2!OrderID!hide] FOR XML EXPLICIT
下面是部分结果。OrderID 特性不在所得到的文档中。
<Customer CustomerID="ALFKI"> <Order OrderDate="1997-08-25T00:00:00" /> <Order OrderDate="1997-10-03T00:00:00" /> <Order OrderDate="1997-10-13T00:00:00" /> </Customer> <Customer CustomerID="ANATR"> <Order OrderDate="1996-09-18T00:00:00" /> <Order OrderDate="1997-08-08T00:00:00" /> </Customer>
F. 指定 cdata 命令
如果将该命令设置为 cdata,则不对包含数据进行实体编码,而是将其放入 CDATA 节。cdata 特性
可以是匿名的。
下面的查询将联系人姓名包含在 CDATA 节中。编写生成通用表的查询的过程和对通用表行集进行处理
以生成所得到的 XML 文档的过程,与在示例 A 或示例 B 中描述的过程相似。
SELECT 1 as Tag, NULL as Parent, Customers.CustomerID as [Customer!1!CustomerID], Customers.ContactName as [Customer!1!!cdata] FROM Customers ORDER BY [Customer!1!CustomerID] FOR XML EXPLICIT
下面显示部分结果。包含数据均包在 CDATA 节中,并且不对包含数据进行实体编码(联系人姓名保留
Mar<ia Ande!rs)。
<Customer CustomerID="ALFKI"> <![CDATA[Maria Anders]]> </Customer> <Customer CustomerID="ANATR"> <![CDATA[Ana Trujillo]]> </Customer>
G. 指定 ID 和 IDREF 命令
在 XML 文档中,可将元素特性指定为 ID 类型的特性,然后可使用文档中的 IDREF 特性引用它们,
从而启用文档内的链接(类似于关系数据库中的主键和外键关系)。
下例中的查询返回由 ID 和 IDREF 特性组成的 XML 文档。下例检索客户和订单信息。该查询将返
回下列 XML 文档:
<Customer CustomerID="ALFKI"> <Order CustomerID="ALFKI" OrderDate="1997-08-25T00:00:00"> <OrderID>10643</OrderID> </Order> <Order CustomerID="ALFKI" OrderDate="1997-10-03T00:00:00"> <OrderID>10692</OrderID> </Order> </Customer> ...
假设还希望使 <Customer> 元素的 CustomerID 特性成为 ID 类型并使 <Order> 元素的
CustomerID 特性成为 IDREF 类型。因为一份订单只属于一位客户,所以指定 IDREF。
编写生成通用表的查询的过程和对通用表行集进行处理以生成所得到的 XML 文档的过程,与在示
例 A 或示例 B 中描述的过程相似。该查询只是增加了将命令(Id 和 IDREF)指定为列的一部分。
以下是查询语句:
SELECT 1 as Tag, NULL as Parent, Customers.CustomerID as [Customer!1!CustomerID!id], NULL as [Order!2!OrderID!element], NULL as [Order!2!CustomerID!idref], NULL as [Order!2!OrderDate] FROM Customers UNION ALL SELECT 2, 1, Customers.CustomerID, Orders.OrderID, Orders.CustomerID, Orders.OrderDate FROM Customers, Orders WHERE Customers.CustomerID = Orders.CustomerID ORDER BY [Customer!1!CustomerID!id], [Order!2!OrderID!element] FOR XML EXPLICIT, XMLDATA
在查询中指定的 ID 或 IDREF 命令标记 XML-Data 架构中的元素/特性。在该查询中:
将 ID 命令指定为通用表列名 (Customer!1!CustomerID!id) 的一部分。这使返回的 XML 文档
中 <Customer> 元素的 CustomerID 特性成为 ID 类型的特性。在 XML-Data 架构中,dt:type 值
是 AttributeType 声明中的 ID。
将 IDREF 命令指定为通用表列名 (Order!2!OrderID!idref) 的一部分。此命令使返回的 XML 文
档中 <Order> 元素的 OrderID 特性成为 IDREF 类型的特性。在 XML-Data 架构中,dt:type 值是
AttributeType 声明中的 IDREF。 通过在查询中指定 XMLDATA 选项可获得 XML-Data 架构。注意在查询中指定的 ID 和 IDREF 命令
重写 XML-Data 架构中的数据类型。
下面是部分结果。因为在查询中指定了 XMLDATA 架构选项,所以为结果预先设计了架构。
<Schema name="Schema1" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes"> <ElementType name="Customer" content="mixed" model="open"> <AttributeType name="CustomerID" dt:type="id"/> <attribute type="CustomerID"/> </ElementType> <ElementType name="Order" content="mixed" model="open"> <AttributeType name="CustomerID" dt:type="idref"/> <AttributeType name="OrderDate" dt:type="dateTime"/> <element type="OrderID"/> <attribute type="CustomerID"/> <attribute type="OrderDate"/> </ElementType> <ElementType name="OrderID" content="textOnly" model="closed" dt:type="i4"/> </Schema> <Customer xmlns="x-schema:#Schema1" CustomerID="ALFKI"> <Order CustomerID="ALFKI" OrderDate="1997-08-25T00:00:00"> <OrderID>10643</OrderID> </Order> <Order CustomerID="ALFKI" OrderDate="1997-10-03T00:00:00"> <OrderID>10692</OrderID> </Order> </Customer>
H. 指定 ID 和 IDREFS 特性
可以将元素特性指定为 ID 类型的特性,然后可使用 IDREFS 特性引用它们,从而启用文档内的
链接(与关系数据库中主键、外键的关系相似)。
下例显示如何将 ID、IDREFS 命令指定为查询中列名的一部分以创建 ID 和 IDREFS 类型的
XML 特性。因为 ID 不能是整型值,所以下例中的 ID 值是投影的类型;前缀用于 ID 值。
在 ORDER BY 子句中,将客户姓名指定为正在排序的特性以显示不是 ID 的特性可用于对结果
进行排序。
假设这些表存在于数据库中:
-- Create Customers2 table. CREATE TABLE Customers2 (CustomerID int primary key, CustomerName varchar(50)) GO -- Insert records in Customers2 table. INSERT INTO Customers2 values (1, 'Joe') INSERT INTO Customers2 values (2, 'Bob') INSERT INTO Customers2 values (3, 'Mary') Go -- Create Orders2 table. CREATE TABLE Orders2 (OrderID int primary key, CustomerID int references Customers2) GO -- Insert records in Orders2 table. INSERT INTO Orders2 values (5, 3) INSERT INTO Orders2 values (6, 1) INSERT INTO Orders2 values (9, 1) INSERT INTO Orders2 values (3, 1) INSERT INTO Orders2 values (8, 2) INSERT INTO Orders2 values (7, 2) GO
假设某查询返回具有下列层次结构的 XML 文档:
<Cust CustID="1" CustName="Joe" OrderIDList="O-3 O-6 O-9"> <Order Oid="O-3"/> <Order Oid="O-6"/> <Order Oid="O-9"/> </Cust> <Cust CustID="2" CustName="Bob" OrderIDList="O-7 O-8"> <Order Oid="O-7"/> <Order Oid="O-8"/> </Cust> <Cust CustID="3" CustName="Mary" OrderIDList="O-5"> <Order Oid="O-5"/> </Cust>
<Cust> 元素的 OrderIDList 特性是引用 <Order> 元素的 Oid 特性的多值特性。若要建立此
链接,必须将 Oid 特性声明为 ID 类型,并且必须将 <Cust> 元素的 OrderIDList 特性声明为
IDREFS 类型。因为一个客户可下许多订单,所以使用 IDREFS 类型。
编写生成通用表的查询的过程和对通用表行集进行处理以生成所得到的 XML 文档的过程,与在示
例 A 或示例 B 中描述的过程相似。该查询只是增加了将命令(Id 和 IDREFS)指定为列的一部分。
以下是查询语句:
-- Generate Customer element without IDREFS attribute. SELECT 1 AS tag, NULL AS parent, CustomerID AS "Cust!1!CustID", CustomerName AS "Cust!1!CustName", NULL AS "Cust!1!OrderIDList!idrefs", NULL AS "Order!2!Oid!id" FROM Customers2 UNION ALL -- Now add the IDREFS. Note that Customers2.CustomerName -- is repeated because it is listed in the ORDER BY clause -- (otherwise, NULL would suffice). SELECT 1 AS tag, NULL AS parent, Customers2.CustomerID, Customers2.CustomerName, 'O-'+CAST(Orders2.OrderID as varchar(5)), NULL FROM Customers2 join Orders2 on Customers2.CustomerID = Orders2.CustomerID
UNION ALL -- Now add the subelements (Orders2). -- Customers2.CustomerID is repeated because it is the parent key. -- Customers2.CustomerName is repeated because it is listed -- in the ORDER BY clause. SELECT 2 AS tag, 1 AS parent, Customers2.CustomerID, Customers2.CustomerName, NULL, 'O-'+CAST(Orders2.OrderID as varchar(5)) FROM Customers2 JOIN Orders2 ON Customers2.CustomerID = Orders2.CustomerID
-- Now order by name and by key. No order on the last column -- is required because the key of Orders2 is not a parent. ORDER BY "Cust!1!CustID", "Order!2!Oid!id", "Cust!1!OrderIDList!idrefs" FOR XML EXPLICIT, XMLDATA
在查询中指定的 ID 或 IDREFS 命令标记 XML-Data 架构中的元素/特性。在该查询中:
将 ID 命令指定为通用表列名 (Order!2!Oid!id) 的一部分。这使返回的 XML 文档中 <Order>
元素的 Oid 特性成为 ID 类型的特性。在 XML-Data 架构中,dt:type 值是 AttributeType 声明
中的 ID。
将 IDREF 命令指定为通用表列名 (Cust!1!OrderIDList!idrefs) 的一部分。这使返回的 XML 文
档中 <Cust> 元素的 OrderIDList 特性成为 IDREF 类型的特性。在 XML-Data 架构中,dt:type
值是 AttributeType 声明中的 IDREFS。 通过在查询中指定 XMLDATA 选项可获得 XML-Data 架构。注意在查询中指定的 ID 和 IDREFS
命令重写 XML-Data 架构中的数据类型。
结果如下:
<Schema name="Schema8" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes"> <ElementType name="Cust" content="mixed" model="open"> <AttributeType name="CustID" dt:type="i4"/> <AttributeType name="CustName" dt:type="string"/> <AttributeType name="OrderIDList" dt:type="idrefs"/> <attribute type="CustID"/> <attribute type="CustName"/> <attribute type="OrderIDList"/> </ElementType> <ElementType name="Order" content="mixed" model="open"> <AttributeType name="Oid" dt:type="id"/> <attribute type="Oid"/> </ElementType> </Schema> <Cust xmlns="x-schema:#Schema8" CustID="1" CustName="Joe" OrderIDList="O-3 O-6 O-9"> <Order Oid="O-3"/> <Order Oid="O-6"/> <Order Oid="O-9"/> </Cust> <Cust xmlns="x-schema:#Schema8" CustID="2" CustName="Bob" OrderIDList="O-7 O-8"> <Order Oid="O-7"/> <Order Oid="O-8"/> </Cust> <Cust xmlns="x-schema:#Schema8" CustID="3" CustName="Mary" OrderIDList="O-5"> <Order Oid="O-5"/> </Cust>
I. 指定 xmltext 命令
下例显示如何在使用 EXPLICIT 模式的 SELECT 语句中使用 xmltext 命令解决溢出列中的数据。
请考察 Person 表。该表含有存储 XML 文档未用完部分的 Overflow 列。
CREATE TABLE Person(PersonID varchar(5), PersonName varchar(20), Overflow nvarchar(200)) INSERT INTO Person VALUES ('P1','Joe',N'<SomeTag attr1="data">content</SomeTag>') INSERT INTO Person VALUES ('P2','Joe',N'<SomeTag attr2="data"/>') INSERT INTO Person VALUES ('P3','Joe',N'<SomeTag attr3="data" PersonID="P">content</SomeTag>')
下面的查询从 Person 表中检索列。对于 Overflow 列,没有指定 AttributeName,但是将
directive 设置成 xmltext 作为提供通用表列名的一部分。
SELECT 1 as Tag, NULL as parent, PersonID as [Parent!1!PersonID], PersonName as [Parent!1!PersonName], overflow as [Parent!1!!xmltext] -- No AttributeName; xmltext directive FROM Person FOR XML EXPLICIT
因为没有为 Overflow 列指定 AttributeName 且指定了 xmltext命令,所以在所得到的 XML
文档中将 <overflow> 元素中的特性附加到包含 <Parent> 元素的特性列表中,并且因为 <xmltext>
元素中的 PersonID 特性与在同一元素级上检索的 PersonID 特性发生冲突,所以忽略 <xmltext>
元素中的特性(即使 PersonID 为 NULL)。通常情况下,特性将替代溢出中具有相同名称的特性。
结果如下:
<Parent PersonID="P1" PersonName="Joe" attr1="data"> content</Parent> <Parent PersonID="P2" PersonName="Joe" attr2="data"> </Parent> <Parent PersonID="P3" PersonName="Joe" attr3="data"> content</Parent>
如果溢出数据含有子元素且指定了上述查询,则添加 Overflow 列中的子元素作为所包含的 <Parent>
元素的子元素。
例如,更改 Person 表中的数据以使 Overflow 列现在含有子元素:
TRUNCATE TABLE Person INSERT INTO Person VALUES ('P1','Joe',N'<SomeTag attr1="data">content</SomeTag>') INSERT INTO Person VALUES ('P2','Joe',N'<SomeTag attr2="data"/>') INSERT INTO Person VALUES ('P3','Joe',N'<SomeTag attr3="data" PersonID="P"><name>content</name></SomeTag>')
如果执行上述查询,则添加 <xmltext> 元素中的子元素作为所包含的 <Parent> 元素的子元素。
SELECT 1 as Tag, NULL as parent, PersonID as [Parent!1!PersonID], PersonName as [Parent!1!PersonName], overflow as [Parent!1!!xmltext] -- no AttributeName, xmltext directive FROM Person FOR XML EXPLICIT
结果如下:
<Parent PersonID="P1" PersonName="Joe" attr1="data"> content</Parent> <Parent PersonID="P2" PersonName="Joe" attr2="data"> </Parent> <Parent PersonID="P3" PersonName="Joe" attr3="data"> <name>content</name></Parent>
如果使用 xmltext 命令指定 AttributeName,则添加 <overflow> 元素的特性作为所包含
的 <Parent> 元素的子元素特性。为 AttributeName 指定的名称成为子元素名。
在下面的查询中,与 xmltext命令一起指定 AttributeName (<overflow>)。
SELECT 1 as Tag, NULL as parent, PersonID as [Parent!1!PersonID], PersonName as [Parent!1!PersonName], overflow as [Parent!1!overflow!xmltext] -- overflow is AttributeName -- xmltext is directive FROM Person FOR XML EXPLICIT
结果如下:
<Parent PersonID="P1" PersonName="Joe"> <overflow attr1="data"> content</overflow> </Parent> <Parent PersonID="P2" PersonName="Joe"> <overflow attr2="data"/> </Parent> <Parent PersonID="P3" PersonName="Joe"> <overflow attr3="data" PersonID="P"> <name>content</name></overflow> </Parent>
在下面的查询元素中,为 PersonName 特性指定 directive。这将导致将 PersonName 添加为
所包含的 <Parent> 元素的子元素。<xmltext> 的特性仍附加到所包含的 <Parent> 元素。<overflow>
元素的内容(子元素等)附加到所包含的 <Parent> 元素的其它子元素。
SELECT 1 as Tag, NULL as parent, PersonID as [Parent!1!PersonID], PersonName as [Parent!1!PersonName!element], -- element directive overflow as [Parent!1!!xmltext] FROM Person FOR XML EXPLICIT
结果如下:
<Parent PersonID="P1" attr1="data"> content <PersonName>Joe</PersonName> </Parent> <Parent PersonID="P2" attr2="data"> <PersonName>Joe</PersonName> </Parent> <Parent PersonID="P3" attr3="data"> <name>content</name> <PersonName>Joe</PersonName> </Parent>
如果 xmltext 列数据包含根元素特性,这些特性将不在 XML-Data 架构中显示,并且 MSXML
分析程序不验证所得到的 XML 文档片段的有效性,例如:
SELECT 1 as Tag, 0 as Parent, N'<overflow a="1"/>' as 'overflow!1!!xmltext' FOR XML EXPLICIT, xmldata
结果如下。注意在返回的架构中缺少溢出特性 a。
<Schema name="Schema12" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes"> <ElementType name="overflow" content="mixed" model="open"> </ElementType> </Schema> <overflow xmlns="x-schema:#Schema12" a="1"> </overflow>
J. 获得由客户、订单和订单详细信息组成的 XML 文档
下例中的查询生成通用表行集,前面的主题从概念上对通用表行集进行了讨论。
假设将要生成的层次结构如下:
<Customer cid="C1" name="Janine"> <Order id="O1" date="1/20/1996"> <OrderDetail id="OD1" pid="P1"/> <OrderDetail id="OD2" pid="P2"/> </Order> <Order id="O2" date="3/29/1997"> ... </Customer>
编写生成通用表的查询的过程和对通用表行集进行处理以生成所得到的 XML 文档的过程,与在示例 A
或示例 B 中描述的过程相似。
SELECT 1 as Tag, NULL as Parent, C.CustomerID as [Customer!1!cid], C.ContactName as [Customer!1!name], NULL as [Order!2!id], NULL as [Order!2!date], NULL as [OrderDetail!3!id!id], NULL as [OrderDetail!3!pid!idref] FROM Customers C UNION ALL SELECT 2 as Tag, 1 as Parent, C.CustomerID, NULL, O.OrderID, O.OrderDate, NULL, NULL FROM Customers C, Orders O WHERE C.CustomerID = O.CustomerID UNION ALL SELECT 3 as Tag, 2 as Parent, C.CustomerID, NULL, O.OrderID, NULL, OD.OrderID, OD.ProductID FROM Customers C, Orders O, [Order Details] OD WHERE C.CustomerID = O.CustomerID AND O.OrderID = OD.OrderID ORDER BY [Customer!1!cid], [Order!2!id] FOR XML EXPLICIT
下面是部分结果:
<Customer cid="ALFKI" name="Maria Anders"> <Order id="10643" date="1997-08-25T00:00:00"> <OrderDetail id="10643" pid="28"></OrderDetail> <OrderDetail id="10643" pid="39"></OrderDetail> </Order> <Order id="10692" date="1997-10-03T00:00:00"> <OrderDetail id="10692" pid="63"></OrderDetail> </Order> <Order id="10702" date="1997-10-13T00:00:00"> <OrderDetail id="10702" pid="3"></OrderDetail> <OrderDetail id="10702" pid="76"></OrderDetail> </Order> </Customer> |