我FOR XML
在 SQL Server 2008 中闲逛,看看它是否更适合构建 Web 服务响应,而不是依赖 Hibernate 和 HQL 来映射 DTO(或从平面结果集中手动映射它们)。
我创建了一个虚构的例子,其中人们可能有孩子和一组电话号码。
我面临的情况是SELECT name FROM personCte
会产生不需要的包装<name>
元素,从而导致<name><name first="test" last="test"/></name>
.
我可以通过执行以下操作来摆脱额外的包装元素,但我想知道是否有更合适的方法?
SELECT (select name)
FROM personCte
该解决方案的一个问题是它不能在 CTE 中使用,因为必须命名所有 CTE 列。
我还想知道是否有比执行子查询更好的方法将多个属性展开为单个元素(例如将名字和姓氏转换为名称)?
这是我正在使用的示例代码:
DECLARE @Person TABLE (
id int NOT NULL PRIMARY KEY IDENTITY(1, 1),
firstName nvarchar(50) NOT NULL,
lastName nvarchar(50) NOT NULL,
parentId int NULL
);
DECLARE @PersonPhoneNumber TABLE (
personId int NOT NULL,
number char(12) NOT NULL
);
INSERT INTO @Person (firstName, lastName, parentId)
VALUES
('Person', 'A', NULL),
('Person', 'B', 1),
('Person', 'C', 2);
INSERT INTO @PersonPhoneNumber
VALUES
(1, '888-888-8888'),
(1, '999-999-9999'),
(3, '333-333-3333');
;WITH personCte AS (
SELECT
id,
(
SELECT firstName AS [@first], lastName AS [@last]
FROM @Person
WHERE id = person.id
FOR XML PATH('name'), TYPE
) AS name,
(
SELECT number
FROM @PersonPhoneNumber
WHERE personId = person.id
FOR XML PATH(''), TYPE
) AS phoneNumbers,
parentId
FROM @Person person
)
SELECT
id,
(SELECT name), /* Used to avoid unwanted wrapping name element */
phoneNumbers,
parentId,
(
SELECT id, (SELECT name), phoneNumbers, parentId
FROM personCte person
WHERE parentId = p.id
FOR XML AUTO, TYPE
) AS children
FROM personCte p
FOR XML AUTO, ROOT('persons'), TYPE
正确产生:
<persons>
<person id="1">
<name first="Person" last="A" />
<phoneNumbers>
<number>888-888-8888</number>
<number>999-999-9999</number>
</phoneNumbers>
<children>
<person id="2" parentId="1">
<name first="Person" last="B" />
</person>
</children>
</person>
<person id="2" parentId="1">
<name first="Person" last="B" />
<children>
<person id="3" parentId="2">
<name first="Person" last="C" />
<phoneNumbers>
<number>333-333-3333</number>
</phoneNumbers>
</person>
</children>
</person>
<person id="3" parentId="2">
<name first="Person" last="C" />
<phoneNumbers>
<number>333-333-3333</number>
</phoneNumbers>
</person>
</persons>