Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Область применения:SQL Server
В XQuery можно использовать прямые и вычисляемые конструкторы для создания структур XML в запросе.
Примечание.
Нет разницы между прямыми и вычисляемых конструкторами.
Использование прямых конструкторов
При использовании конструкторов direct в построении XML указывается синтаксис, подобный XML. В следующих примерах иллюстрируется построение XML с помощью конструкторов direct.
Элементы конструктора
В используемой нотации XML можно создавать элементы. В следующем примере используется выражение конструктора прямых элементов и создается <ProductModel> элемент. Созданный элемент содержит три дочерних элемента.
Текстовый узел.
Два узла
<Summary>элемента и<Features>.Элемент
<Summary>имеет один дочерний текстовый узел, значение которого равно"Some description".Элемент
<Features>содержит три дочерних элемента,<Color><Weight>и<Warranty>. Каждый из этих узлов имеет один дочерний текстовый узел и имеет значенияRed,25соответственно2 years parts and labor.
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
<Features>
<Color>Red</Color>
<Weight>25</Weight>
<Warranty>2 years parts and labor</Warranty>
</Features></ProductModel>');
Ниже приведен результирующий XML-код:
<ProductModel ProductModelID="111">
This is product model catalog description.
<Summary>Some description</Summary>
<Features>
<Color>Red</Color>
<Weight>25</Weight>
<Warranty>2 years parts and labor</Warranty>
</Features>
</ProductModel>
Хотя показанное в данном примере построение элементов из неизменных выражений полезно само по себе, настоящая мощь этой функции языка XQuery раскрывается при построении XML-документов с динамическим извлечением данных из базы данных. Для указания выражений запроса можно использовать фигурные скобки. В результирующем XML-документе выражение заменяется своим значением. Например, следующий запрос создает <NewRoot> элемент с одним дочерним элементом (<e>). Значение элемента <e> вычисляется путем указания выражения пути внутри фигурных скобков ("{... }").
DECLARE @x AS XML;
SET @x = '<root>5</root>';
SELECT @x.query('<NewRoot><e> { /root } </e></NewRoot>');
Фигурные скобки выступают в качестве токенов переключения контекста и переключают запрос с построения XML на оценку запроса. В данном случае производится оценка выражения пути XQuery внутри фигурных скобок, /root, и вместо выражения подставляются результаты.
Ниже приведен результат:
<NewRoot>
<e>
<root>5</root>
</e>
</NewRoot>
Следующий запрос похож на предыдущий. Однако выражение в фигурных скобках указывает data() функцию для получения атомарного значения <root> элемента и назначает его созданному элементу <e>.
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('
<NewRoot>
<e> { data(/root) } </e>
</NewRoot>'));
SELECT @y;
Ниже приведен результат:
<NewRoot>
<e>5</e>
</NewRoot>
Если в качестве части текста желательно использовать фигурные скобки вместо токенов переключения контекста, то последние можно изолировать с помощью фигурных скобок «}}» или «{{», как показано в следующем примере:
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('
<NewRoot> Hello, I can use {{ and }} as part of my text</NewRoot>'));
SELECT @y;
Ниже приведен результат:
<NewRoot> Hello, I can use { and } as part of my text</NewRoot>
Следующий запрос — еще один пример построения элементов с помощью прямого конструктора элементов. Кроме того, значение <FirstLocation> элемента получается путем выполнения выражения в фигурных скобках. Выражение запроса возвращает шаги изготовления к первому цеху из столбца Instructions таблицы Production.ProductModel.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<FirstLocation>
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Ниже приведен результат:
<FirstLocation>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Insert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
</AWMI:step>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Attach <AWMI:tool>Trim Jig TJ-26</AWMI:tool> to the upper and lower right corners of the aluminum sheet.
</AWMI:step>
...
</FirstLocation>
Содержимое элемента в xml-построении
В следующем примере показано использование выражений при построении содержимого элемента с помощью прямого конструктора элементов. В этом примере прямой конструктор элементов указывает одно выражение. Для этого выражения в результирующем XML-документе создается один текстовый узел.
DECLARE @x AS XML;
SET @x = '
<root>
<step>This is step 1</step>
<step>This is step 2</step>
<step>This is step 3</step>
</root>';
SELECT @x.query('
<result>
{ for $i in /root[1]/step
return string($i)
}
</result>');
Последовательность элементарного значения, рассчитанная при оценке выражения, добавляется в текстовый узел с пробелом между соседними элементарными значениями, как это показано в результате. Построенный элемент содержит один дочерний элемент. Это текстовый узел, который хранит значение, показанное в результате.
<result>This is step 1 This is step 2 This is step 3</result>
Если вместо одного выражения задать три отдельных выражения, формирующих три текстовых узла, в результирующем XML-документе происходит объединение соседних текстовых узлов в один узел методом сцепления.
DECLARE @x AS XML;
SET @x = '
<root>
<step>This is step 1</step>
<step>This is step 2</step>
<step>This is step 3</step>
</root>';
SELECT @x.query('
<result>
{ string(/root[1]/step[1]) }
{ string(/root[1]/step[2]) }
{ string(/root[1]/step[3]) }
</result>');
Построенный узел элементов содержит один дочерний элемент. Это текстовый узел, который хранит значение, показанное в результате.
<result>This is step 1This is step 2This is step 3</result>
Конструктор атрибутов
При создании элементов с помощью конструктора прямых элементов можно также указать атрибуты элемента с помощью синтаксиса, аналогичного XML, как показано в этом примере:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>');
Ниже приведен результирующий XML-код:
<ProductModel ProductModelID="111">
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>
Созданный элемент <ProductModel> имеет атрибут ProductModelID и следующие дочерние узлы:
Текстовый узел
This is product model catalog description.Узел элемента,
<Summary>. Этот узел содержит один дочерний текстовый узел,Some description.
При создании атрибута можно указать его значение с выражением в фигурных скобках. В этом случае результат выражения возвращается в качестве значения атрибута.
В следующем примере data() функция не является строго обязательной. Так как вы назначаете значение выражения атрибуту, data() неявно применяется для получения типизированного значения указанного выражения.
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('<NewRoot attr="{ data(/root) }" ></NewRoot>'));
SELECT @y;
Ниже приведен результат:
<NewRoot attr="5" />
Ниже приведен еще один пример, в котором указаны выражения для построения атрибутов LocationID и SetupHrs. Оценка этих выражений производится по XML-документу, содержащемуся в столбце Instruction. Типизированное значение выражения присваивается атрибутам.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<FirstLocation
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Ниже приведен частичный результат:
<FirstLocation LocationID="10" SetupHours="0.5" >
<AWMI:step ...
</AWMI:step>
...
</FirstLocation>
Ограничения реализации
Существуют следующие ограничения:
Несколько или смешанных (строковых и XQuery выражений) не поддерживаются. Например, как показано в следующем запросе, создается XML-документ, в котором
Itemявляется константой, а значение5получено при оценке выражения запроса:<a attr="Item 5" />Следующий запрос возвращает ошибку, так как вы смешиваете константную строку с выражением ({/x}), и это не поддерживается:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="Item {/x}"/>');В этом случае имеются варианты, перечисленные ниже.
Сформировать значение атрибута путем объединения двух элементарных значений. Эти элементарные значения включены последовательно в значение атрибута с пробелом между элементарными значениями:
SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Ниже приведен результат:
<a attr="Item 5" />Используйте функцию сцепления для объединения двух строковых аргументов в итоговое значение атрибута:
SELECT @x.query('<a attr="{concat(''Item'', /x[1])}"/>');В этом случае между двумя строковыми значениями пробел не добавляется. Если требуется добавить пробелы между двумя значениями, необходимо задать их явно.
Ниже приведен результат:
<a attr="Item5" />
Несколько выражений в качестве значения атрибута не поддерживаются. Например, следующий запрос возвращает ошибку:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{/x}{/x}"/>');Разнородные последовательности не поддерживаются. Любая попытка назначить разнородную последовательность в качестве значения атрибута возвращает ошибку, как показано в следующем примере. В этом примере разнородная последовательность, строка "Item" и элемент
<x>указываются в качестве значения атрибута:DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{''Item'', /x }" />');При применении
data()функции запрос работает, так как он получает атомарное значение выражения,/xкоторое объединяется со строкой. Ниже приведена последовательность элементарных значений:SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Ниже приведен результат:
<a attr="Item 5" />Узел атрибутов принудительно упорядочивается во время сериализации, а не при статической проверке типов. Например, следующий запрос завершится ошибкой, потому что запрос пытается добавить атрибут после узла без атрибутов.
SELECT CONVERT (XML, '').query(' element x { attribute att { "pass" }, element y { "Element text" }, attribute att2 { "fail" } } '); GOПредыдущий запрос возвращает следующую ошибку:
XML well-formedness check: Attribute cannot appear outside of element declaration. Rewrite your XQuery so it returns well-formed XML.
Добавление пространств имен
При построении XML-документа с помощью прямых конструкторов имена создаваемого элемента и атрибута можно определить с помощью префикса пространства имен. Префикс можно связать с пространством имен следующими способами:
- с помощью атрибута объявления пространства имен;
- Используя
WITH XMLNAMESPACESпредложение. - в прологе запроса на языке XQuery.
Добавление пространств имен с помощью атрибута объявления пространства имен
В следующем примере используется атрибут объявления пространства имен в построении элемента <a> для объявления пространства имен по умолчанию. Построение дочернего элемента <b> отменяет объявление пространства имен по умолчанию, объявленного в родительском элементе.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<a xmlns="a">
<b xmlns=""/>
</a>');
Ниже приведен результат:
<a xmlns="a">
<b xmlns="" />
</a>
Пространству имен можно назначить префикс. Префикс указывается в построении элемента <a>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b/>
</x:a>');
Ниже приведен результат:
<x:a xmlns:x="a">
<b />
</x:a>
Вы можете отменить объявление пространства имен по умолчанию в конструкции XML, но не можете отменить объявление префикса пространства имен. Следующий запрос возвращает ошибку, так как вы не можете отменить объявление префикса, как указано в построении элемента <b>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b xmlns:x=""/>
</x:a>');
Новое построенное пространство имен доступно для использования внутри запроса. Например, следующий запрос объявляет пространство имен при создании элемента <FirstLocation>и задает префикс в выражениях для значений атрибута LocationID и SetupHrs.
SELECT Instructions.query('
<FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Создание префикса пространства имен таким образом переопределяет любое предварительное объявление пространства имен для этого префикса. Например, объявление пространства имен в AWMI="https://someURI"прологе запроса переопределяется объявлением пространства имен в элементе <FirstLocation> .
SELECT Instructions.query('
declare namespace AWMI="https://someURI";
<FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Добавление пространств имен с помощью пролога
В следующем примере показан порядок добавления пространств имен в построенный XML-документ. Пространство имен по умолчанию объявляется в прологе запроса.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
declare default element namespace "a";
<a><b xmlns=""/></a>');
В построении элемента <b>атрибут объявления пространства имен указывается пустой строкой в качестве значения. Это отменяет объявление пространства имен, произведенное по умолчанию в родительском элементе.
Ниже приведен результат:
<a xmlns="a">
<b xmlns="" />
</a>
Обработка xml-конструкций и пробелов
Содержимое элемента в конструкции XML может содержать пробелы. Эти символы обрабатываются следующим образом.
Символы пробелов в URI пространства имен рассматриваются как XSD-тип
anyURI. В частности, это то, как они обрабатываются:- Все начальные и конечные пробелы удаляются.
- Внутренние последовательности пробельных символов заменяются одиночными пробелами.
Символы перехода на новую строку внутри содержимого атрибутов заменяются пробелами. Все остальные пробелы остаются неизменными.
Пробелы внутри элементов не изменяются.
В следующем примере показана обработка пробельных символов в конструкции XML:
-- line feed is replaced by space.
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('
declare namespace myNS=" https://
abc/
xyz
";
<test attr=" my
test attr
value " >
<a>
This is a
test
</a>
</test>
') AS XML_Result;
Ниже приведен результат:
-- result
<test attr="<test attr=" my test attr value "><a>
This is a
test
</a></test>
"><a>
This is a
test
</a></test>
Другие прямые конструкторы XML
Конструкторы для обработки инструкций и комментариев XML используют тот же синтаксис, что и соответствующий синтаксис конструкции XML. Вычисляемые конструкторы для текстовых узлов также поддерживаются, но в основном используются для XML DML создания текстовых узлов.
Примечание.
Пример использования явного конструктора текстового узла см. в конкретном примере вставки (XML DML).
В следующем запросе созданный XML-документ содержит элемент, два атрибута, комментарий и инструкцию по обработке. Перед созданием последовательности используется <FirstLocation>запятая.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<?myProcessingInstr abc="value" ?>,
<FirstLocation
WorkCtrID = "{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
<!-- some comment -->
<?myPI some processing instructions ?>
{ (/AWMI:root/AWMI:Location[1]/AWMI:step) }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Ниже приведен частичный результат:
<?myProcessingInstr abc="value" ?>
<FirstLocation WorkCtrID="10" SetupHrs="0.5">
<!-- some comment -->
<?myPI some processing instructions ?>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">I
nsert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
</AWMI:step>
...
</FirstLocation>
Использование вычисляемых конструкторов
В данном случае указываются ключевые слова, которые идентифицируют тип узла, подлежащий построению. Поддерживается использование только следующих ключевых слов:
- элемент
- атрибут
- text
В узлах элементов и атрибутов эти ключевые слова используются перед именем узла и перед заключенным в фигурные скобки выражением, которое формирует содержимое этого узла. В следующем примере вы создаете этот XML-код:
<root>
<ProductModel PID="5">Some text <summary>Some Summary</summary></ProductModel>
</root>
Ниже приведен запрос, использующий вычисляемые конструкторы, создающие XML:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('element root
{
element ProductModel
{
attribute PID { 5 },
text{"Some text "},
element summary { "Some Summary" }
}
} ');
Выражение запроса может быть задано выражением, формирующим содержимое узла.
DECLARE @x AS XML;
SET @x = '<a attr="5"><b>some summary</b></a>';
SELECT @x.query('element root
{
element ProductModel
{
attribute PID { /a/@attr },
text{"Some text "},
element summary { /a/b }
}
} ');
Вычисляемые элементы и конструкторы атрибутов, как определено в спецификации XQuery, позволяют вычислить имена узлов. При использовании прямых конструкторов в SQL Server имена узлов, такие как элемент и атрибут, должны быть указаны в виде константных литералов. Поэтому нет разницы в прямых конструкторах и вычисляемых конструкторах для элементов и атрибутов.
В следующем примере содержимое созданных узлов получено из XML-инструкций по производству, хранящихся в столбце "Инструкции" типа данных XML в таблице ProductModel.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
element FirstLocation
{
attribute LocationID { (/AWMI:root/AWMI:Location[1]/@LocationID)[1] },
element AllTheSteps { /AWMI:root/AWMI:Location[1]/AWMI:step }
}
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Ниже приведен частичный результат:
<FirstLocation LocationID="10">
<AllTheSteps>
<AWMI:step> ... </AWMI:step>
<AWMI:step> ... </AWMI:step>
...
</AllTheSteps>
</FirstLocation>
Другие ограничения реализации
Конструкторы вычисляемых атрибутов нельзя использовать для объявления нового пространства имен. Кроме того, следующие вычисляемых конструкторы не поддерживаются в SQL Server:
- вычисляемые конструкторы узлов документов;
- вычисляемые конструкторы инструкций обработки;
- вычисляемые конструкторы комментариев.