`
NistCK
  • 浏览: 38763 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

MSSQL 使用 EXPLICIT 模式

阅读更多

    在 EXPLICIT 模式中,查询书写器控制由执行查询所返回的 XML 文档的形式。必须以特定的方

式编写查询,将有关预期嵌套的附加信息显式指定为查询的一部分。可用 directive 在列级指定附

加的配置。当指定EXPLICIT 模式时,必须负责确保生成的 XML 符合语法规则并且有效(对于

XML-DATA 架构)。

 

1、处理 EXPLICIT 模式查询和通用表
    EXPLICIT 模式将查询执行所得到的行集转换为 XML 文档。为使 EXPLICIT 模式生成 XML 文

档,行集必须具有特定的格式。这需要以某种方式编写 SELECT 查询以生成具有特定格式的行集(

称为通用表),可对该行集进行处理以生成请求的 XML 文档。

 

    EXPLICIT 模式首先要求查询生成两个元数据列:

    (1) 在 SELECT 子句中指定的第一列必须是命名 (Tag) 标记号。Tag 列存储当前元素的标记

              号。Tag 是整型数据类型。

    (2) 指定的第二列必须是父元素的命名 (Parent) 标记号。Parent 列存储父元素的标记号。


     这些列用于确定 XML 树中的父子层次结构。这些信息随后用于生成预期的 XML 树。如果存储在

Parent 列中的父标记值是 0 或 NULL,则将行放置在 XML 层次结构的顶层。

     通用表的其余部分充分描述所得到的 XML 文档。行集(通用表)中的数据垂直分区成组。每组

成为结果中的一个 XML 元素。

     FOR XML EXPLICIT 模式要求 SELECT 查询以某种方式指定通用表中的列名。它要求

SELECT 查询将元素名与标记号相关联,并提供通用表列名中的特性名(默认情况下是特性名)。此

外,若要得到与父实例相关联的正确子实例,需要对行集排序,使子实例紧跟在它的父实例后。简言

之,通用表的列名、Tag 和 Parent 元列中的值以及通用表格式的数据所提供的信息都用于生成所期

望的 EXPLICIT 模式的 XML 文档。

 

     SELECT 查询还必须指定通用表中的列名。通用表中的列名使用 XML 类属标识符和特性名进行编

码。通用表列名中的元素名、特性名和其它转换信息的编码被指定为:

       ElementName!TagNumber!AttributeName!Directive

 

参数
ElementName

     是所得到的元素类属标识符(例如,如果将 Customers 指定为 ElementName,则

     <Customers> 是元素标记)。

TagNumber

     是元素的标记号。借助于通用表中的两个元数据列(Tag 和 Parent),TagNumber

     用于表示 XML 树中的 XML元素嵌套。每个 TagNumber 都准确对应于一个 ElementName。

AttributeName

     是 XML 特性的名称(如果没有指定 Directive)或包含的元素名(如果 Directive 是

      xml、cdata 或 element)。
     如果指定 Directive,则 AttributeName 可以为空。这种情况下,列中包含的值直接

     由具有指定 ElementName 的元素所包含。

Directive

     是可选命令。如果没有指定 Directive,则必须指定 AttributeName。如果没有指定

     AttributeName 且没有指定 Directive(如 Customer!1),则表示元素命令(如

     Customer!1!!element)且包含数据。

     Directive 有两种用途。该选项用于分别使用关键字 ID、IDREF 和 IDREFS 对 ID、

     IDREF 和 IDREFS 进行编码。还用于表示如何使用关键字 hide、element、xml、xmltext

     和 cdata 将字符串数据映射到 XML。大多数情况下允许在这些组中组合指令,但是不能

     在组本身中进行组合。

ID
     可将元素特性指定为 ID 类型的特性。然后可以使用 IDREF 和 IDREFS 特性引用它们,

     以启用文档内的链接。但是,如果没有请求 XMLDATA,则此关键字无效。

IDREF
     指定为 IDREF 的特性可用于引用 ID 类型的特性,以启用文档内的链接。但是,如果没有

     请求 XMLDATA,则此关键字无效。

IDREFS
     指定为 IDREFS 的特性可用于引用 ID 类型的特性,以启用文档内的链接。但是,如果没

     有请求 XMLDATA,则此关键字无效。

hide
     不显示特性。这对于按照不出现在结果中的特性对结果进行排序可能很有用。

element
     不生成特性。而是生成具有指定名称的包含元素(如果没有指定特性名则直接生成包含元素)。

     包含数据被编码为实体(例如,字符 < 变成 &lt;)。该关键字可以与 ID、IDREF 或

     IDREFS 组合。

xml
     除了不进行实体编码外,该命令与元素命令相同(例如,字符 < 仍是 <)。除了 hide 外,

     该命令不能与任何其它命令一起使用。

xmltext
     列内容应包在单个标记内,以便与文档的其它部分集成。在提取 OPENXML 存储在列中的

     溢出(未用完的)XML 数据时该命令很有用。有关更多信息,请参见使用 OPENXML 编写

     XML。 如果指定了 AttributeName,则标记名由指定名称替换;
     否则通过将内容放在容器的起始处而不进行实体编码,将特性追加到包含元素的当前特性列表。

     含有该命令的列必须是文本类型(varchar、nvarchar、char、nchar、text、ntext)。

     该命令只能与 hide 一起使用。在提取存储在列中的溢出数据时该命令很有用。

     如果内容不是有效的 XML,则该行为不明确。


cdata
     通过用 CDATA 节环绕数据来包含数据。不对内容进行实体编码。原始数据类型必须是文本

     类型(varchar、nvarchar、text、ntext)。该命令只能与 hide 一起使用。当使用该命

     令时,不应指定 AttributeName。 


 

2、示例

 

示例 A 和 B 详细说明了编写使用 EXPLICIT 模式的查询的过程。该过程适用于后面的其它示例。

 

A. 检索客户和订单信息
下例检索客户和订单信息。假定希望生成下面的层次结构:

<Customer CustomerID="ALFKI">

<Order OrderID=10643>
     <Order OrderID=10692>

       ...

</Customer>
<Customer CustomerID="ANATR" >

<Order OrderID=10308 >
     <Order OrderID=10625 >

       ...

</Customer>

 

    生成所得到的 XML 树的查询生成通用表,该表包含两个元数据列:Tag 和 Parent。因此,在

指定查询时 SELECT 子句必须指定这两列。这两列中的值用于生成 XML 层次结构。

    <Customer> 元素位于顶层。在下面的示例中,指派给此元素的 Tag 值为 1(该值可以是任

何数字,但是有唯一的数字与每个元素名相关联)。因为 <Customer> 是顶层元素,所以其

Parent 标记值为 NULL。

    <Order> 元素是 <Customer> 元素的子元素。因此,<Order> 元素的 Parent 标记值为 1

(将 <Customer> 标识为其父元素)。指派给 <Order> 元素的 Tag 值为 2。

 

    可使用两个 SELECT 语句编写查询并使用 UNION ALL 组合这两个语句的结果:

    在第一个 SELECT 语句中,获取所有 <Customer> 元素及其特性值。在含有多个 SELECT

语句的查询中,只使用在第一个查询中指定的列名(通用表列名)。忽略在第二个 SELECT 语句中

指定的列名。因此,指定 XML 元素和特性名的通用表的列名包含在下面的查询中:


SELECT 1                    as Tag,
         NULL                 as Parent,
         Customers.CustomerID as [Customer!1!CustomerID],
         NULL                 as [Order!2!OrderID]
FROM Customers

 

    在第二个查询中检索所有 <Order> 元素及其特性值:

 
SELECT 2,
         1,
         Customers.CustomerID,
         Orders.OrderID
FROM Customers, Orders
WHERE Customers.CustomerID = Orders.CustomerID

 

     使用 UNION ALL 组合此查询中的两个 SELECT 语句。


     以只进方式对通用表行集(包含所有数据和元数据)逐行扫描,以生成所得到的 XML 树。为了

输出正确的 XML 文档层次结构,指定通用表中的行顺序也很重要。为此可在查询中使用 ORDER BY

子句。


    下面是最终查询:


SELECT 1                    as Tag,
         NULL                 as Parent,
         Customers.CustomerID as [Customer!1!CustomerID],
         NULL                 as [Order!2!OrderID]
FROM Customers

UNION ALL
SELECT 2,
         1,
         Customers.CustomerID,
         Orders.OrderID
FROM Customers, Orders
WHERE Customers.CustomerID = Orders.CustomerID
ORDER BY [Customer!1!CustomerID], [Order!2!OrderID]
FOR XML EXPLICIT

 

     所得到的通用表是有四列的表。为了举例说明,只显示几行。

 

Tag      Parent       Customer!1!CustomerID         Order!2!OrderID
1          NULL         ALFKI                                       NULL
2         1                ALFKI                                       10643
2         1                ALFKI                                       10692
2         1                ALFKI                                       10702
2         1                ALFKI                                       11011
2         1                ALFKI                                        ...
1         NULL          ANATR                                       NULL
2         1                ANATR                                      10308
2         1                ANATR                                      10625
2         1                ANATR                                      ...

 


     下面描述处理通用表中的行以生成所得到的 XML 树:

      第一行标识 Tag 值 1。标识所有含有 Tag 值 1 的列。只有一列含有 Tag 值 1:

Customer!1!CustomerID。此列名由元素名 (Customer)、标记号 (1) 和特性名 (CustomerID)

组成。因此,创建 <Customer> 元素并向其添加特性 CustomerID。然后将该列值指派为该特性值。


      第二行有 Tag 值 2。因此,标识所有含有 Tag 值 2 的列。只有一列含有 Tag 值 2:

Order!2!OrderID。此列名由元素名 (Order)、标记号 (2) 和特性名 (OrderID) 组成。该行也将

<Customer> 标识为其父元素(Parent 值为 1)。结果,创建 <Order> 元素作为 <Customer>

元素的子元素并向其添加特性 OrderID。然后将该列值指派为该特性值。


     以相同的方式处理后面含有 Tag 值 2 的所有行。


     标识含有 Tag 值 1 的某行。标识含有 Tag 值 1 的 Customer!1!CustomerID 列。该列标识

没有父元素(Parent 为 NULL)的 <Customer> 元素。因而,关闭前面的 <Order> 标记和

<Customer> 标记。打开新的 <Customer> 标记并重复此过程。
     因为没有在查询中指定 Directive,所以特性名是 XML 特性的名称。下面是部分结果集:

 

<Customer CustomerID="ALFKI">
  <Order OrderID="10643" />
  <Order OrderID="10692" />
  <Order OrderID="10702" />
  <Order OrderID="11011" />
</Customer>
<Customer CustomerID="ANATR">
  <Order OrderID="10308" />
  <Order OrderID="10625" />
</Customer>

 

 

B. 指定元素命令


     下例检索客户和订单信息。假定希望生成下面的层次结构:(注意 <OrderID> 是 <Order> 的子元素

而不是特性):

 

<Customer CustomerID="ALFKI">
   <Order OrderDate="1997-08-25T00:00:00">
      <OrderID>10643</OrderID>
   </Order>
   <Order OrderDate="1997-10-03T00:00:00">
      <OrderID>10692</OrderID>
   </Order>
    ...
</Customer>

 

     <Customer> 元素位于顶层。在下例中,为 <Customer> 指派 Tag 值 1。因为 <Customer> 为顶

层元素,所以其Parent 标记值为 NULL。

     <Order> 元素是 <Customer> 元素的子元素。因此,<Order> 元素的 Parent 标记值为 1(将

<Customer> 标识为其父元素),并为其指派 Tag 值 2。

     <Order> 元素具有作为包含元素(不是特性)的 <OrderID>。因此,在检索该值时,必须指定 element

命令。可使用两个 SELECT 语句编写查询,并使用 UNION ALL 组合这两个语句的结果:

     在第一个 SELECT 语句中,获取所有 <Customer> 元素及其特性值。在含有多个 SELECT 语句的查

询中,只使用在第一个查询中指定的列名(通用表列名)。忽略在第二个 SELECT 语句中指定的列名。因此,

指定 XML 元素和特性名的通用表的列名包含在下面的查询中:


SELECT 1                    as Tag,
         NULL                 as Parent,
         Customers.CustomerID as [Customer!1!CustomerID],
         NULL                 as [Order!2!OrderID!element],
         NULL                 as [Order!2!OrderDate]
FROM Customers

 

    在第二个查询中检索所有 <Order> 元素及其特性值。因为需要使用 ORDER BY 子句对含有子元素的父

元素进行分组,所以该查询选择 Customers.CustomerID。


SELECT 2, 1,
         Customers.CustomerID,
         Orders.OrderID,
         Orders.OrderDate
FROM Customers, Orders
WHERE Customers.CustomerID = Orders.CustomerID

 

     使用 UNION ALL 组合此查询中的两个 SELECT 语句。


     使用 ORDER BY 子句指定所生成的通用表行集中的行顺序。


     下面是最终查询:


SELECT 1                    as Tag,
         NULL                 as Parent,
         Customers.CustomerID as [Customer!1!CustomerID],
         NULL                 as [Order!2!OrderID!element],
         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!element]
FOR XML EXPLICIT

 

     所得到的通用表是有五列的表。为了举例说明,只显示几行。


Tag  Parent    Customer!1!CustomerID      Order!2!OrderID!element      Order!2!OrderDate
1      NULL      ALFKI                                    NULL                                       NULL
2     1             ALFKI                                    10692                                    1997-10-03T00:00:00
2     1             ALFKI                                    10702                                    1997-10-13T00:00:00
2     1             ALFKI                                    10835                                    1998-01-15T00:00:00
...    ...            ...                                          ...                                           ...
1     NULL       ANATR                                   10308                                    1996-09-18T00:00:00
1     NULL       ANATR                                   ...                                            ...


      下面描述对行集中的行进行处理以生成所得到的 XML 树:

       第一行标识 Tag 值 1。因此,标识所有含有 Tag 值 1 的列。只有一列含有 Tag 值 1:

Customer!1!CustomerID列。此列名由元素名 (Customer)、标记号 (1) 和特性名 (CustomerID)

组成。因此,创建 <Customer> 元素并向其添加特性 CustomerID。然后将该列值指派为该特性值。


       第二行含有 Tag 值 2。标识含有 Tag 值 2 的所有列。有两列含有 tag号 2:

Order!2!OrderID!element 和 Order!2!OrderDate。 列名 Order!2!OrderDate 由元素名

 (Order)、标记号 (2) 和特性名 (OrderDate) 组成。该行将 <Customer>标识为其父元素(Parent

值为 1)。因此,创建 <Order> 元素作为 <Customer> 元素的子元素并向其添加特性 OrderID。将

该列值指派为该特性值。列名 Order!2!OrderID!element 由命令 (element) 组成。因此,生成一个

包含元素 (<OrderID>)。将该列值指派为该元素值。


       以相同的方式处理后面含有 Tag 值 2 的所有行。


       标识含有 Tag 值 1 的某行。标识含有 Tag 值 1 的 Customer!1!CustomerID 列。该列标识

没有父元素(Parent 为 NULL)的 <Customer> 元素。因而,关闭前面的 <Order> 标记和

<Customer> 标记。打开新的 <Customer> 标记并重复此过程。

 

       说明:  在此查询中,如果更改列名 (Order!2!OrderID!element) 以便不指定特性名

(Order!2!!element),则该查询直接生成包含元素。

 

C. 指定 element 命令和实体编码


      如果将 directive 设置为 element,则对包含数据进行实体编码。例如,如果在 Customers 表中

有一位客户联系人的姓名是 Mar<ia Anders,则下面的查询将对所包含的数据进行编码:

 

--Update 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!element]
FROM Customers
ORDER BY [Customer!1!CustomerID]
FOR XML EXPLICIT
GO
-- set the value back to original
UPDATE Customers
SET ContactName='Maria Anders'
WHERE ContactName='Mar<ia Anders'
GO

 

      下面显示部分结果。因为在查询中指定了 element 命令,所以指定的特性名是包含元素的名称。也

对 ContactName 进行实体编码(将 ContactName 中的 < 字符返回为 &lt;)

 

<Customer CustomerID="ALFKI">
  <ContactName>Mar&lt;ia Anders</ContactName>
</Customer>
<Customer CustomerID="ANATR">
  <ContactName>Ana Trujillo</ContactName>
</Customer>

 

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>

 

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    mysql集群主从安装总结

    mysqld --initialize --user=mysql --datadir=/usr/local/mysql/data/data3306 --explicit_defaults_for_timestamp ``` 这条命令的作用是: - `--initialize`: 初始化MySQL数据目录。 - `--user=mysql`: 指定运行...

    mysql5.7.19安装包64位rpm格式

    使用rpm安装方式安装mysql,安装的路径如下:(系统自动配置好了,不需要手动配置) a 数据库目录 /var/lib/mysql/ b 配置文件 /usr/share/mysql(mysql.server命令及配置文件) c 相关命令 /usr/bin(mysqladmin ...

    mysql-5.7.17-winx64的安装、配置和初始化

    - 这些警告信息不影响MySQL的正常使用,但如果希望消除这些警告,可以在`my.ini`中加入`explicit_defaults_for_timestamp=true`配置项。 - **其他警告**:“'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_...

    mysql5.7.21安装

    - 使用 `mysql -u root -p` 命令登录 MySQL。由于安装时使用了 `--initialize-insecure` 参数,初始密码为空。 - 如果无法登录,重启 MySQL 服务后再次尝试。 - **修改密码**: - 使用以下命令修改 root 用户的...

    MySQL部署手册1

    使用`mysqld_safe`命令以守护进程模式启动MySQL服务,然后通过`&`符号使其在后台运行。 9. **设置权限**: 为了管理方便,需要将安装目录的所有权改为`root`用户,而数据目录仍归`mysql`用户所有。 10. **配置...

    mysql数据库my.cnf配置文件

    #MySQL的查询缓冲大小(从4.0.1开始,MySQL提供了查询缓冲机制)使用查询缓冲,MySQL将SELECT语句和查询结果存放在缓冲区中, # 今后对于同样的SELECT语句(区分大小写),将直接从缓冲区中读取结果。根据MySQL用户...

    MySQL的M-S部署手册1

    2. **解压安装包**:使用`tar`命令解压缩下载的MySQL安装文件,例如`tar xvf mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz`,并将其移动到指定目录,如`/opt/deploy/data/`。 3. **配置MySQL**:修改MySQL的配置...

    mysql参数配置

    12. **explicit_defaults_for_timestamp=1** - 明确设置TIMESTAMP类型的默认值。 13. **lower_case_table_names=1** - 表名是否区分大小写(1表示小写)。 14. **max_allowed_packet=32M** - 最大允许的数据包...

    小记一次mysql主从配置解决方案

    - 添加`explicit_defaults_for_timestamp=true`,确保在MySQL 5.6及以上版本中兼容旧版本的从库。 - 重启MySQL服务,使配置生效。 2. **获取主库状态信息**: - 使用`SHOW MASTER STATUS;`命令,记录当前的二...

    mysql配置文件详细[归类].pdf

    10. **explicit_defaults_for_timestamp**: 设置为1表示使用严格的timestamp行为,不依赖于全局变量。 11. **join_buffer_size**: 用于联合查询操作的缓冲区大小,调整它可以影响联接查询的性能。 12. **tmp_table...

    mysql 5.7.19 winx64免安装版配置教程

    除此之外,还需要设置数据库服务器的端口(port=3306)、字符集(character-set-server=utf8)、文件系统的字符集(character-set-filesystem=utf8)、SQL模式(sql_mode)以及是否为时间戳启用显式默认值(explicit_...

    MySQL 5.6 中 TIMESTAMP 的变化分析

    系统开始发出关于隐式默认值的警告,提示用户使用`explicit_defaults_for_timestamp`选项。开启这个选项后,TIMESTAMP的行为变为: 1. 若TIMESTAMP列没有声明NOT NULL,它允许NULL值。这意味着你可以明确设置该列为...

    mysql5.7.18解压版启动mysql服务

    - **sql-mode**:设定MySQL服务器的模式,STRICT_TRANS_TABLES选项使得严格模式,NO_AUTO_CREATE_USER防止自动创建用户,NO_ENGINE_SUBSTITUTION禁止替换存储引擎。 通过以上步骤,你可以成功启动MySQL 5.7.18解压...

    解压版MYSQL安装及遇到的错误及解决方法

    - [mysqld]:配置服务器端参数,如安装目录(basedir)、数据目录(datadir)、服务器端口(port)、字符集(character_set_server)、SQL模式(sql_mode)、查询缓存(explicit_defaults_for_timestamp)以及是否...

    MySQL 5.6 中 TIMESTAMP有那些变化

    3. 使用 `explicit_defaults_for_timestamp` 选项以确保明确的默认值设置,避免未来版本的不兼容性。 4. 在严格的 SQL 模式下运行数据库,以确保数据完整性。 总之,MySQL 5.6 对 TIMESTAMP 的改动旨在提高数据库的...

    MySQL 5.6 & 5.7最优配置文件模板(my.ini)

    - `autocommit`: 默认的事务处理模式,设置为0表示关闭自动提交。 - `character_set_server`: 设置服务器的默认字符集,这里为utf8mb4,支持全Unicode字符。 - `max_connections`: 允许的最大并发连接数,防止...

Global site tag (gtag.js) - Google Analytics