使用 FOR XML EXPLICIT,您可以控制查询所返回的 XML 文档的结构。查询必须用特定的方法编写,以在查询结果中指定有关您需要的嵌套的信息。使用 FOR XML EXPLICIT 支持的可选指令,您可以配置各列的处理方式。例如,您可以对以下情况加以控制:让列显示为元素内容还是显示为属性内容,或者,列是否只用于给结果排序,而不会出现在生成的 XML 中。
在 EXPLICIT 模式中,SELECT 语句中的前两列必须分别命名为 Tag 和 Parent。Tag 和 Parent 是元数据列,它们的值用来确定由查询返回的 XML 文档中各元素之间的父子关系(或嵌套)。
Tag 列 这是在 SELECT 列表中指定的第一列。Tag 列存储当前元素的标记值。标记号可以使用的值是 1 到 255。
Parent 列 此列存储当前元素的父项的标记号。如果此列中的值为 NULL,则行就会被放置在 XML 层次的顶层。
例如,假定有这样一个查询,它在没有指定 FOR XML EXPLICIT 时会返回以下结果集。
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> |
除 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 指明在生成结果时忽略此列。这条指令可以用于加入只用来给表排序的列。属性名会被忽略,且不出现在结果中。
element 指明列值作为名称为 AttributeName 的嵌套元素插入,而不是作为属性。
xml 指明列值插入时不进行引用。如果指定了 AttributeName,则值作为使用该名称的元素插入。否则,它在插入时没有包装元素。如果不使用此指令,标记字符就会被转义,除非列是 XML 类型。例如,值 <a/> 将以 <a/> 形式插入。
cdata 指明列值将作为 CDATA 区段插入。AttributeName 会被忽略。
在执行包含 FOR XML EXPLICIT 的查询时,BINARY、LONG BINARY、IMAGE 和 VARBINARY 列中的数据会自动以 base64 编码格式返回。缺省情况下,结果集中的任何 NULL 值都会被忽略。通过更改 for_xml_null_treatment 选项的设置,您可以更改此行为。
假定您要使用 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 DISTINCT 以便将两条 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 DISTINCT 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 DISTINCT SELECT 2, 1, EmployeeID, CustomerID, Region FROM Employees KEY JOIN SalesOrders ORDER BY 3, 1 FOR XML 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 DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT 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 DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT 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 DISTINCT SELECT 2, 1, EmployeeID, NULL, OrderDate, NULL FROM Employees KEY JOIN SalesOrders UNION DISTINCT 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!company!element] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
在此查询所生成的结果中,和符号会被转义,因为该列不属于 XML 类型:
<customer><id>115</id> <company>Sterling & Co.</company> </customer> |
xml 指令表明列值在插入生成的 XML 中时不进行转义。如果用 xml 指令执行与以上查询相同的查询:
SELECT 1 AS tag, NULL AS parent, ID AS [customer!1!id!element], CompanyName AS [customer!1!company!xml] FROM Customers WHERE ID = '115' FOR XML EXPLICIT; |
结果中的和符号将不进行转义:
<customer> <id>115</id> <company>Sterling & Co.</company> </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讨论此页。
|
版权 © 2013, SAP 股份公司或其关联公司. - SAP Sybase SQL Anywhere 16.0 |