在数据库操作中,有时需要将查询结果以XML格式返回。传统的方法是使用存储过程,通过游标逐条处理记录,然后拼接字符串来生成XML。但这种方法效率低下,且代码复杂。幸运的是,SQL提供了一种更简洁高效的方法:FOR XML子句。本文将详细介绍如何使用FOR XML子句的RAW模式来生成XML数据。
要理解本文内容,需要具备基本的SQLJOIN知识。
本文将使用以下数据库结构。可以复制粘贴以下代码来创建数据库,或者创建自己的数据库并调整查询。
CREATE DATABASE FOR_XML_TUTORIAL;
USE [FOR_XML_TUTORIAL];
CREATE TABLE [CUSTOMER] (
CUSTOMER_ID INT PRIMARY KEY NOT NULL,
FIRST_NAME VARCHAR(25) NOT NULL,
LAST_NAME VARCHAR(25) NOT NULL,
POSTAL_CODE VARCHAR(2) NOT NULL
);
CREATE TABLE [ORDER] (
ORDER_ID INT PRIMARY KEY NOT NULL,
CUSTOMER_ID INT NOT NULL REFERENCES CUSTOMER(CUSTOMER_ID),
TOTAL_ITEMS INT NOT NULL,
TOTAL_AMOUNT NUMERIC(18, 2) NOT NULL
);
INSERT INTO CUSTOMER VALUES (1, 'John', 'Michaels', 'TX');
INSERT INTO CUSTOMER VALUES (2, 'Shawn', 'Cena', 'MA');
INSERT INTO CUSTOMER VALUES (3, 'Dwayne', 'Austin', 'TX');
INSERT INTO CUSTOMER VALUES (4, 'Steve', 'Johnson', 'FL');
INSERT INTO [ORDER] VALUES (1, 1, 5, 32.50);
INSERT INTO [ORDER] VALUES (2, 1, 2, 21.36);
INSERT INTO [ORDER] VALUES (3, 2, 7, 59.00);
INSERT INTO [ORDER] VALUES (4, 3, 2, 18.24);
INSERT INTO [ORDER] VALUES (5, 4, 3, 30.00);
INSERT INTO [ORDER] VALUES (6, 4, 6, 66.00);
使用FOR XML子句时,必须指定一个模式,以返回相应的XML数据。以下是可用模式的列表:
将使用以下查询来返回客户信息和订单信息。
SELECT C.FIRST_NAME, C.LAST_NAME, C.POSTAL_CODE, O.ORDER_ID, O.TOTAL_ITEMS, O.TOTAL_AMOUNT
FROM [CUSTOMER] C
INNER JOIN [ORDER] O ON C.CUSTOMER_ID = O.CUSTOMER_ID
要返回RAW模式的XML数据,只需在上述查询中添加FOR XML RAW。
SELECT C.FIRST_NAME, C.LAST_NAME, C.POSTAL_CODE, O.ORDER_ID, O.TOTAL_ITEMS, O.TOTAL_AMOUNT
FROM [CUSTOMER] C
INNER JOIN [ORDER] O ON C.CUSTOMER_ID = O.CUSTOMER_ID
FOR XML RAW
上述查询返回的XML数据如下:
可以看到,查询返回的每条记录都被转换为一个名为"row"的XML元素,列名转换为属性名,属性值设置为查询返回的值。
要更改元素名称,可以在RAW关键字后添加所需的元素名称:
SELECT C.FIRST_NAME, C.LAST_NAME, C.POSTAL_CODE, O.ORDER_ID, O.TOTAL_ITEMS, O.TOTAL_AMOUNT
FROM [CUSTOMER] C
INNER JOIN [ORDER] O ON C.CUSTOMER_ID = O.CUSTOMER_ID
FOR XML RAW('Customer')
上述查询返回的XML数据中,每个元素的名称从"row"更改为"Customer"。
要更改属性名称,只需为列提供别名:
SELECT C.FIRST_NAME AS 'FirstName', C.LAST_NAME AS 'LastName', C.POSTAL_CODE AS 'PostalCode',
O.ORDER_ID AS 'OrderId', O.TOTAL_ITEMS AS 'Items', O.TOTAL_AMOUNT AS 'Amount'
FROM [CUSTOMER] C
INNER JOIN [ORDER] O ON C.CUSTOMER_ID = O.CUSTOMER_ID
FOR XML RAW('Customer')
上述查询返回的数据中,属性名称已更改为新的别名。
要将每个元素嵌套在一个根元素中,可以在查询中添加ROOT关键字:
SELECT C.FIRST_NAME AS 'FirstName', C.LAST_NAME AS 'LastName', C.POSTAL_CODE AS 'PostalCode',
O.ORDER_ID AS 'OrderId', O.TOTAL_ITEMS AS 'Items', O.TOTAL_AMOUNT AS 'Amount'
FROM [CUSTOMER] C
INNER JOIN [ORDER] O ON C.CUSTOMER_ID = O.CUSTOMER_ID
FOR XML RAW('Customer'), ROOT
返回的数据现在被嵌套在一个名为"root"的父元素中。
要更改根元素的名称,可以在ROOT关键字后添加所需的名称:
SELECT C.FIRST_NAME AS 'FirstName', C.LAST_NAME AS 'LastName', C.POSTAL_CODE AS 'PostalCode',
O.ORDER_ID AS 'OrderId', O.TOTAL_ITEMS AS 'Items', O.TOTAL_AMOUNT AS 'Amount'
FROM [CUSTOMER] C
INNER JOIN [ORDER] O ON C.CUSTOMER_ID = O.CUSTOMER_ID
FOR XML RAW('Customer'), ROOT('Customers')
上述查询返回的数据中,根元素的名称已更改为"Customers"。
到目前为止,执行的所有查询都返回了将每列转换为属性的XML数据格式。要更改此格式,并将每列映射到自己的元素,可以在查询中添加ELEMENTS关键字:
SELECT C.FIRST_NAME AS 'FirstName', C.LAST_NAME AS 'LastName', C.POSTAL_CODE AS 'PostalCode',
O.ORDER_ID AS 'OrderId', O.TOTAL_ITEMS AS 'Items', O.TOTAL_AMOUNT AS 'Amount'
FROM [CUSTOMER] C
INNER JOIN [ORDER] O ON C.CUSTOMER_ID = O.CUSTOMER_ID
FOR XML RAW('Customer'), ROOT('Customers'), ELEMENTS
现在,每条记录的属性被转换为一个元素,其名称设置为别名,值设置为查询返回的值。