Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Область применения: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:
- вычисляемые конструкторы узлов документов;
- вычисляемые конструкторы инструкций обработки;
- вычисляемые конструкторы комментариев.