使用 FOR XML EXPLICIT,您可以控制查询所返回的 XML 文档的结构。查询必须用特定的方法编写,以在查询结果中指定有关您需要的嵌套的信息。使用 FOR XML EXPLICIT 支持的可选指令,您可以配置各列的处理方式。例如,您可以对以下情况加以控制:让列显示为元素内容还是显示为属性内容,或者,列是否只用于给结果排序,而不会出现在生成的 XML 中。
有关如何使用 FOR XML EXPLICIT 编写查询的示例,请参见编写 EXPLICIT 模式的查询。
在 EXPLICIT 模式中,SELECT 语句中的前两列必须分别命名为 Tag 和 Parent。Tag 和 Parent 是元数据列,它们的值用来确定由查询返回的 XML 文档中各元素之间的父子关系(或嵌套)。
Tag 列 这是在选择列表中指定的第一列。Tag 列存储当前元素的标记值。标记号可以使用的值是 1 到 255。
Parent 列 此列存储当前元素的父项的标记号。如果此列中的值为 NULL,则行就会被放置在 XML 层次的顶层。
例如,假定有这样一个查询,它在没有指定 FOR XML EXPLICIT 时会返回以下结果集。(将会在下一节向查询添加数据列中介绍 GivenName!1 和 ID!2 数据列的用途。)
Tag | Parent | GivenName!1 | ID!2 |
---|---|---|---|
1 | NULL | 'Beth' | NULL |
2 | NULL | NULL | '102' |
在本示例中,Tag 列中的值是结果集中各元素的标记号。两行的 Parent 列都包含 NULL 值。这意味着两个元素都会在层次的顶层生成,当查询包括 FOR XML EXPLICIT 子句时,将给出以下结果:
<GivenName>Beth</GivenName> <ID>102</ID> |
但是,如果第二行的 Parent 列的值是 1,结果将如下所示:
<GivenName>Beth <ID>102</ID> </GivenName> |
有关如何使用 FOR XML EXPLICIT 编写查询的示例,请参见编写 EXPLICIT 模式的查询。
除 Tag 列和 Parent 列之外,查询还必须包含一个或多个数据列。这些数据列的名称控制着在标记过程中解释列的方式。每个列名都拆分为由惊叹号 (!) 分隔的字段。可以为数据列指定以下字段:
ElementName!TagNumber!AttributeName!Directive
ElementName 元素的名称。对于给定的行,会从标记号匹配的第一列的 ElementName 字段中提取为该行生成的元素的名称。如果有多个 TagNumber 相同的列,对于后面的 TagNumber相同的列,会忽略 ElementName。在上面的示例中,第一行会生成一个名为 <GivenName> 的元素。
TagNumber 元素的标记号。对于有给定标记值的行,所有在其 TagNumber 字段中具有相同值的列都会向与该行相对应的元素提供内容。
AttributeName 指定列值是 ElementName 元素的属性。例如,如果数据列具有名称 productID!1!Color,那么 Color 就会显示为 <productID> 元素的一个属性。
Directive 使用此可选字段,您可以进一步控制 XML 文档的格式。您可以为 Directive 指定以下任意一个值:
hide 指明在生成结果时忽略此列。这条指令可以用于加入只用来给表排序的列。属性名会被忽略,且不出现在结果中。
有关使用 hide 指令的示例,请参见使用 hide 指令。
元素 指明列值作为名称为 AttributeName 的嵌套元素插入,而不是作为属性。
有关使用 element 指令的示例,请参见使用 element 指令。
xml 指明列值插入时不进行引用。如果指定了 AttributeName,则值作为使用该名称的元素插入。否则,它在插入时没有包装元素。如果不使用此指令,标记字符就会被转义,除非列是 XML 类型。例如,值 <a/> 将以 <a/> 形式插入。
有关使用 xml 指令的示例,请参见使用 xml 指令。
cdata 指明列值将作为 CDATA 区段插入。AttributeName 会被忽略。
有关使用 cdata 指令的示例,请参见使用 cdata 指令。
在执行包含 FOR XML EXPLICIT 的查询时,BINARY、LONG BINARY、IMAGE 和 VARBINARY 列中的数据会自动以 base64 编码格式返回。缺省情况下,结果集中的任何 NULL 值都会被忽略。通过更改 for_xml_null_treatment 选项的设置,您可以更改此行为。
有关 for_xml_null_treatment 选项的详细信息,请参见for_xml_null_treatment 选项和FOR XML 和 NULL 值。
假定您要使用 FOR XML EXPLICIT 编写一个生成以下 XML 文档的查询:
<employee EmployeeID='129'> <customer CustomerID='107' Region='Eastern'/> <customer CustomerID='119' Region='Western'/> <customer CustomerID='131' Region='Eastern'/> </employee> <employee EmployeeID='195'> <customer CustomerID='109' Region='Eastern'/> <customer CustomerID='121' Region='Central'/> </employee> |
实现方法是:编写一条按指定的准确顺序返回以下结果集的 SELECT 语句,然后将 FOR XML EXPLICIT 附加到该查询。
Tag | Parent | employee!1!EmployeeID | customer!2!CustomerID | customer!2!Region |
---|---|---|---|---|
1 | NULL | 129 | NULL | NULL |
2 | 1 | 129 | 107 | Eastern |
2 | 1 | 129 | 119 | Western |
2 | 1 | 129 | 131 | Central |
1 | NULL | 195 | NULL | NULL |
2 | 1 | 195 | 109 | Eastern |
2 | 1 | 195 | 121 | Central |
在编写查询时,对于某指定行,只有部分列会成为所生成的 XML 文档的组成部分。仅当 TagNumber 字段(列名中的第二个字段)中的值与 Tag 列中的值匹配时,XML 文档中才会加入一列。
在该示例中,第三列用于在其 Tag 列中有值 1 的两个行。在第四和第五列中,值用于在其 Tag 列中有值 2 的行。从列名中的第一个字段中提取元素名。在本例中,会创建 <employee> 元素和 <customer> 元素。
属性名来自列名中的第三个字段,所以,EmployeeID 属性是为 <employee> 元素创建的,而 CustomerID 属性和 Region 属性是为 <customer> 元素生成的。
以下步骤介绍了如何使用 SQL Anywhere 示例数据库构建一个 FOR XML EXPLICIT 查询,让该查询生成一个与本节开始时出现的 XML 文档类似的 XML 文档。
编写 SELECT 语句以生成顶层元素。
在本示例中,查询中的第一个 SELECT 语句会生成 <employee> 元素。查询中的前两个值必须是 Tag 和 Parent 列值。<employee> 元素位于层次的顶层,所以会给它分配一个 Tag 值 1 以及一个 Parent 值 NULL。
如果您要编写一个使用 UNION 的 EXPLICIT 模式查询,则只有在第一条 SELECT 语句中指定的列名才会被使用。要用作元素名或属性名的列名必须在第一条 SELECT 语句中指定,因为在后续 SELECT 语句中指定的列名会被忽略。
要为上面的表生成 <employee> 元素,您的第一条 SELECT 语句应如下所示:
SELECT 1 AS tag, NULL AS parent, EmployeeID AS [employee!1!EmployeeID], NULL AS [customer!2!CustomerID], NULL AS [customer!2!Region] FROM Employees; |
编写 SELECT 语句来生成子元素。
第二个查询会生成 <customer> 元素。由于这是一个 EXPLICIT 模式查询,所以在所有 SELECT 语句中指定的前两个值都必须是 Tag 值和 Parent 值。<customer> 元素会得到标记号 2,而由于它是 <employee> 元素的子项,因此具有 Parent 值 1。第一条 SELECT 语句已经指出 EmployeeID、CustomerID 和 Region 都是属性。
SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders |
给查询添加 UNION ALL 以便将两条 SELECT 语句合并到一起:
SELECT 1 AS tag, NULL AS parent, EmployeeID AS [employee!1!EmployeeID], NULL AS [customer!2!CustomerID], NULL AS [customer!2!Region] FROM Employees UNION ALL SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders |
添加 ORDER BY 子句以指定结果中的行的顺序。行的顺序即在最终生成的文档中使用的顺序。
SELECT 1 AS tag, NULL AS parent, EmployeeID AS [employee!1!EmployeeID], NULL AS [customer!2!CustomerID], NULL AS [customer!2!Region] FROM Employees UNION ALL SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders ORDER BY 3, 1 FOR XML EXPLICIT; |
有关 EXPLICIT 模式的语法的信息,请参见参数。
以下示例查询会检索有关雇员所下订单的信息。在本示例中,有以下三种类型的元素:<employee>、<order> 和 <department>。<employee> 元素具有 ID 属性和 name 属性,<order> 元素具有 date 属性,<department> 元素具有 name 属性。
SELECT 1 tag, NULL parent, EmployeeID [employee!1!ID], GivenName [employee!1!name], NULL [order!2!date], NULL [department!3!name] FROM Employees UNION ALL SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION ALL SELECT 3, 1, EmployeeID, NULL, NULL, DepartmentName FROM Employees e JOIN Departments d ON e.DepartmentID=d.DepartmentID ORDER BY 3, 1 FOR XML EXPLICIT; |
您将从此查询得到以下结果:
<employee ID="102" name="Fran"> <department name="R & D"/> </employee> <employee ID="105" name="Matthew"> <department name="R & D"/> </employee> <employee ID="129" name="Philip"> <order date="2000-07-24"/> <order date="2000-07-13"/> <order date="2000-06-24"/> <order date="2000-06-08"/> ... <department name="Sales"/> </employee> <employee ID="148" name="Julie"> <department name="Finance"/> </employee> ... |
如果您想生成子元素而不是属性,可以向查询中添加 element 指令,如下所示:
SELECT 1 tag, NULL parent, EmployeeID [employee!1!id!element], GivenName [employee!1!name!element], NULL [order!2!date!element], NULL [department!3!name!element] FROM Employees UNION ALL SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION ALL SELECT 3, 1, EmployeeID, NULL, NULL, DepartmentName FROM Employees e JOIN Departments d ON e.DepartmentID=d.DepartmentID ORDER BY 3, 1 FOR XML EXPLICIT; |
您将从此查询得到以下结果:
<employee> <id>102</id> <name>Fran</name> <department> <name>R & D</name> </department> </employee> <employee> <id>105</id> <name>Matthew</name> <department> <name>R & D</name> </department> </employee> <employee> <id>129</id> <name>Philip</name> <order> <date>2000-07-24</date> </order> <order> <date>2000-07-13</date> </order> <order> <date>2000-06-24</date> </order> ... <department> <name>Sales</name> </department> </employee> ... |
在以下查询中,雇员 ID 用于为结果排序,但结果中不会出现雇员 ID,因为指定了 hide 指令:
SELECT 1 tag, NULL parent, EmployeeID [employee!1!id!hide], GivenName [employee!1!name], NULL [order!2!date], NULL [department!3!name] FROM Employees UNION ALL SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION ALL SELECT 3, 1, EmployeeID, NULL, NULL, DepartmentName FROM Employees e JOIN Departments d ON e.DepartmentID=d.DepartmentID ORDER BY 3, 1 FOR XML EXPLICIT; |
此查询会返回以下结果:
<employee name="Fran"> <department name="R & D"/> </employee> <employee name="Matthew"> <department name="R & D"/> </employee> <employee name="Philip"> <order date="2000-04-21"/> <order date="2001-07-23"/> <order date="2000-12-30"/> <order date="2000-12-20"/> ... <department name="Sales"/> </employee> <employee name="Julie"> <department name="Finance"/> </employee> ... |
缺省情况下,当 FOR XML EXPLICIT 查询的结果包含的字符不是有效 XML 字符时,无效字符会被转义,除非该列属于 XML 类型。有关信息,请参见对非法的 XML 名称编码。
例如,以下查询会生成包含和符号 (&) 的 XML:
SELECT 1 AS tag, NULL AS parent, ID AS [customer!1!ID!element], CompanyName AS [customer!1!CompanyName] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
在此查询所生成的结果中,和符号会被转义,因为该列不属于 XML 类型:
<Customers CompanyName="Sterling & Co."> <ID>115</ID> </Customers> |
xml 指令表明列值在插入生成的 XML 中时不进行引用。如果用 xml 指令执行与以上查询相同的查询:
SELECT 1 AS tag, NULL AS parent, ID AS [customer!1!ID!element], CompanyName AS [customer!1!CompanyName!xml] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
结果中的和符号将不进行引用:
<customer> <ID>115</ID> <CompanyName>Sterling & Co.</CompanyName> </customer> |
请注意,此 XML 不是一个结构完好的 XML,因为它含有和符号,而该符号在 XML 中是一个特殊字符。在查询生成 XML 之后,由您负责确保该 XML 结构完好且有效:SQL Anywhere 并不检查所生成的 XML 是否结构完好和有效。
当您指定 xml 指令时,AttributeName 字段会被忽略,并且会生成元素而不是属性。
以下查询使用 cdata 指令在 CDATA 区段中返回客户名称:
SELECT 1 AS tag, NULL AS parent, ID AS [product!1!ID], Description AS [product!1!!cdata] FROM Products FOR XML EXPLICIT; |
此查询生成的结果将在 CDATA 区段中列出对每种产品的说明。CDATA 区段中包含的数据不进行引用:
<product ID="300"> <![CDATA[Tank Top]]> </product> <product ID="301"> <![CDATA[V-neck]]> </product> <product ID="302"> <![CDATA[Crew Neck]]> </product> <product ID="400"> <![CDATA[Cotton Cap]]> </product> ... |
![]() |
使用DocCommentXchange 讨论此页。
|
版权 © 2010, iAnywhere Solutions, Inc. - SQL Anywhere 12.0.0 |