Microsoft SQL Server
FOR XML PATH
Поиск…
замечания
Существует также несколько других режимов FOR XML
:
-
FOR XML RAW
- Создает один элемент<row>
каждой строки. -
FOR XML AUTO
- попытка эвристического автогенерации иерархии. -
FOR XML EXPLICIT
- обеспечивает больший контроль над формой XML, но является более громоздким, чемFOR XML PATH
.
Hello World XML
SELECT 'Hello World' FOR XML PATH('example')
<example>Hello World</example>
Указание пространств имен
WITH XMLNAMESPACES (
DEFAULT 'http://www.w3.org/2000/svg',
'http://www.w3.org/1999/xlink' AS xlink
)
SELECT
'example.jpg' AS 'image/@xlink:href',
'50px' AS 'image/@width',
'50px' AS 'image/@height'
FOR XML PATH('svg')
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
<image xlink:href="firefox.jpg" width="50px" height="50px"/>
</svg>
Определение структуры с использованием выражений XPath
SELECT
'XPath example' AS 'head/title',
'This example demonstrates ' AS 'body/p',
'https://www.w3.org/TR/xpath/' AS 'body/p/a/@href',
'XPath expressions' AS 'body/p/a'
FOR XML PATH('html')
<html>
<head>
<title>XPath example</title>
</head>
<body>
<p>This example demonstrates <a href="https://www.w3.org/TR/xpath/">XPath expressions</a></p>
</body>
</html>
В FOR XML PATH
столбцы без имени становятся текстовыми узлами. NULL
или ''
поэтому становятся пустыми текстовыми узлами. Примечание. Вы можете преобразовать именованный столбец в неназванный, используя AS *
DECLARE @tempTable TABLE (Ref INT, Des NVARCHAR(100), Qty INT)
INSERT INTO @tempTable VALUES (100001, 'Normal', 1), (100002, 'Foobar', 1), (100003, 'Hello World', 2)
SELECT ROW_NUMBER() OVER (ORDER BY Ref) AS '@NUM',
'REF' AS 'FLD/@NAME', REF AS 'FLD', '',
'DES' AS 'FLD/@NAME', DES AS 'FLD', '',
'QTY' AS 'FLD/@NAME', QTY AS 'FLD'
FROM @tempTable
FOR XML PATH('LIN'), ROOT('row')
<row>
<LIN NUM="1">
<FLD NAME="REF">100001</FLD>
<FLD NAME="DES">Normal</FLD>
<FLD NAME="QTY">1</FLD>
</LIN>
<LIN NUM="2">
<FLD NAME="REF">100002</FLD>
<FLD NAME="DES">Foobar</FLD>
<FLD NAME="QTY">1</FLD>
</LIN>
<LIN NUM="3">
<FLD NAME="REF">100003</FLD>
<FLD NAME="DES">Hello World</FLD>
<FLD NAME="QTY">2</FLD>
</LIN>
</row>
Использование (пустых) текстовых узлов помогает отделить предыдущий выходной узел от следующего, так что SQL Server знает, как запустить новый элемент для следующего столбца. В противном случае он запутывается, когда атрибут уже существует в том, что он считает «текущим» элементом.
Например, без пустых строк между элементом и атрибутом в SELECT
SQL Server дает ошибку:
Столбец с атрибутом «FLD / @ NAME» не должен появляться после не-атрибут-центричного брата в иерархии XML в FOR XML PATH.
Также обратите внимание, что этот пример также обернул XML в корневой элемент с именем row
, указанный ROOT('row')
Использование FOR XML PATH для конкатенации значений
FOR XML PATH
можно использовать для конкатенации значений в строку. Следующий пример объединяет значения в строку CSV
:
DECLARE @DataSource TABLE
(
[rowID] TINYINT
,[FirstName] NVARCHAR(32)
);
INSERT INTO @DataSource ([rowID], [FirstName])
VALUES (1, 'Alex')
,(2, 'Peter')
,(3, 'Alexsandyr')
,(4, 'George');
SELECT STUFF
(
(
SELECT ',' + [FirstName]
FROM @DataSource
ORDER BY [rowID] DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
Несколько важных замечаний:
- предложение
ORDER BY
может использоваться для упорядочения значений в предпочтительном порядке - если в качестве разделителя конкатенации используется более длинное значение, необходимо также изменить параметр функции
STUFF
;
SELECT STUFF
(
(
SELECT '---' + [FirstName]
FROM @DataSource
ORDER BY [rowID] DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,3 -- the "3" could also be represented as: LEN('---') for clarity
,''
);
- поскольку используются опция
TYPE
и.value
, конкатенация работает сNVARCHAR(MAX)