SELECT FOR XML
功能描述
Vastbase在SQL Server兼容模式下,支持SELECT查询的FOR XML子句,即以XML字符串的形式显示查询结果集。
- FOR XML子句可用于顶层查询和子查询。
- 顶层FOR XML子句只能在SELECT语句中使用。
- 在子查询中,FOR XML可用于 INSERT、UPDATE 和 DELETE语句。
- FOR XML可以在赋值语句中使用。
注意事项
该功能仅在数据库兼容模式为SQL Server时支持(即数据库实例初始化时指定DBCOMPATIBILITY='MSSQL')。
Vastbase仅支持本章节中介绍的列的XML映射规则,其余未提及的各映射特性暂不支持。
如果FOR XML查询的列值为空,这意味着在返回结果中这些元素不具有值,详见示例2。
语法格式
SELECT ... FOR XML [ PATH [ ('Element_Name') ] ];
参数说明
PATH
FOR XML可以通过指定关键词来控制XML的生成模式,当前Vastbase仅支持PATH模式,不支持其它模式(AUTO,RAW,EXPLICIT)。
PATH模式是一种简单的匹配方式,它将表中的列或者别名做为 XPATH表达式来进行处理。这些表达式明确了如何将值映射到 XML。每一个XPATH表达式都是一个相对 XPATH,从中可以得到相对于行元素而生成的节点名称与层次结构。
映射规则一节中介绍了如何在各种条件下映射行集中的列,并提供了相关示例。
Element_Name
支持为行元素指定新的名称Element_Name以覆盖默认的<row>,详见支持指定包装元素名称。
映射规则
没有名称的列
任何没有名称的列都将成为内联列。 例如,未指定列别名的计算列或嵌套标量查询将生成不带任何名称的列。 如果该列属于XML类型,则将插入该数据类型实例的内容。 否则,列内容将作为文本节点插入。
SELECT 2 + 2 FOR XML PATH;
默认情况下,对于行集中的每一行,生成的XML中都会包含一个<row>元素。上述语句的返回结果如下:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
------------------------------------------
<row>4</row>
(1 row)
下面这个示例用到了示例1中创建的测试表PRODUCTION,如下语句在FOR XML查询时返回了多个列。
SELECT ProductionID, ProductionName
FROM PRODUCTION WHERE ProductionID=1
FOR XML PATH;
返回结果如下:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
----------------------------------------------------------------------------------
<row><productionid>1</productionid><productionname>cookie</productionname></row>
(1 row)
具有名称的列
下面是一些特定条件,在这些条件下具有名称的行集列将映射(区分大小写)到生成的 XML:
- 不支持列名包含斜杠(/)标记。
- 不支持层级。
- 不支持列名包含特殊字符的列,包括:text(),comment(),node(),data(),
*
。
列名以@符号开头
如果列名称以@符号开头,并且不包含斜杠标记(/),则会创建具有相应列值的元素的属性<row>。
例如,以下查询从PRODUCTION表(表的创建参考示例1)返回一个双列 @Pdt, ProductionName
行集。 在生成的 XML 中,将Pdt
属性添加到相应的 <row> 元素,并用ProductionID为其赋值。
SELECT ProductionID as "@Pdt",ProductionName
FROM PRODUCTION WHERE Price = '25'
FOR XML PATH;
返回结果如下:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
------------------------------------------------------------
<row Pdt="1"><productionname>cookie</productionname></row>
(1 row)
属性必须位于同一级别的任何其他节点类型(例如元素节点和文本节点)之前。 以下查询将返回一个错误:
SELECT ProductionName, ProductionID as "@Pdt"
FROM PRODUCTION WHERE Price = '25'
FOR XML PATH;
列名不以@符号开头
如果列名称不以 at 符号开头 (@) ,不是 XPath 节点测试之一,并且不包含斜杠标记 (/) ,则默认创建作为行元素子元素的 XML 元素 row 。
SELECT 2 + 2 as result for xml PATH;
上述查询指定了列名为result。 因此,会向<row>元素添加<result>子元素,返回结果如下:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
------------------------------------------
<row><result>4</result></row>
(1 row)
支持根元素
通过在ROOT查询中指定FOR XML选项,可以为生成的XML 请求一个顶层元素,如该查询中所示。
如下查询为FOR XML生成的XML指定了根元素(PRODUCTION表的创建参考示例1):
SELECT ProductionID, ProductionName
FROM PRODUCTION WHERE Price = '25'
FOR XML PATH, ROOT('MyRoot');
为ROOT指令指定的参数提供了根元素名称,返回结果如下:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
---------------------------------------------------------------------------------------------------
<MyRoot><row><productionid>1</productionid><productionname>cookie</productionname></row></MyRoot>
(1 row)
支持指定包装元素名称
可以选择指定行元素名称以覆盖默认<row>。 例如,以下查询将返回行
SELECT ProductionID, ProductionName
FROM PRODUCTION WHERE ProductionID=1
FOR XML PATH('result');
返回结果如下,生成的XML包含指定的行元素名称:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
----------------------------------------------------------------------------------------
<result><productionid>1</productionid><productionname>cookie</productionname></result>
(1 row)
如果指定零长度字符串,则不会生成包装元素:
SELECT ProductionID, ProductionName
FROM PRODUCTION WHERE ProductionID=1
FOR XML PATH('');
返回结果如下:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
-----------------------------------------------------------------------
<productionid>1</productionid><productionname>cookie</productionname>
(1 row)
示例
示例1: 创建测试表PRODUCTION并插入数据。
此处仅列出表的创建语句,关于FOR XML示例及分析请参考映射规则小节中的各小标题。
CREATE TABLE PRODUCTION
(ProductionID int PRIMARY KEY NOT NULL, ProductionName varchar(25) NOT NULL, Price money , Description text);
insert into PRODUCTION values(1,'cookie',25,'food');
insert into PRODUCTION values(2,'milk',60,'drink');
1、创建测试表,不插入数据。
create table table_1160902 (col1 int,col2 varchar(10));
2、FOR XML查询的列值为空。
select col1,col2 from table_1160902 for xml path;
返回结果如下:
XML_F52E2B61-18A1-11d1-B105-00805F49916B
------------------------------------------
(1 row)
3、为col1字段插入数值,此时col2字段仍为空。
insert into table_1160902 values (1);
4、执行FOR XML查询。
select col1,col2 from table_1160902 for xml path;
返回结果如下,
XML_F52E2B61-18A1-11d1-B105-00805F49916B
------------------------------------------
<row><col1>1</col1><col2/></row>
(1 row)
示例3: 在子查询中使用FOR XML查询。
1、创建示例1中的测试表PRODUCTION,查看测试表数据。
select * from production;
返回结果如下:
productionid | productionname | price | description
--------------+----------------+--------+-------------
1 | cookie | $25.00 | food
2 | milk | $60.00 | drink
(2 rows)
2、在UPDATE的子查询中使用FOR XML查询:利用子查询找到商品ID(ProductionID)为1的行,将其商品描述(Description)赋值给商品ID(ProductionID)为2的行。在得到子查询的查询结果时将其返回内容转换为XML的形式。
UPDATE PRODUCTION SET Description =(SELECT Description FROM PRODUCTION WHERE ProductionID = '1' FOR XML PATH ) WHERE ProductionID ='2';
3、查看PRODUCTION表的当前数据。
select * from production;
返回结果如下:
productionid | productionname | price | description
--------------+----------------+--------+--------------------------------------------
1 | cookie | $25.00 | food
2 | milk | $60.00 | <row><description>food</description></row>
(2 rows)