Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aplica-se:SQL Server
No XQuery, você pode usar os construtores diretos e computados para construir estruturas XML em uma consulta.
Observação
Não há diferença entre os construtores diretos e computados .
Usar construtores diretos
Ao usar construtores diretos, você especifica a sintaxe semelhante a XML ao construir o XML. Os exemplos a seguir ilustram a construção XML pelos construtores diretos.
Elementos de construção
Usando notações de XML, é possível construir elementos. O exemplo a seguir usa a expressão do construtor de elemento direto e cria um <ProductModel> elemento. O elemento construído tem três elementos filho
Um nó de texto.
Dois nós de
<Summary>elemento e<Features>.O
<Summary>elemento tem um filho de nó de texto cujo valor é"Some description".O
<Features>elemento tem três filhos de nó de elemento,<Weight><Color>e<Warranty>. Cada um desses nós tem um filho de nó de texto e tem os valoresRed,25respectivamente2 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>');
Aqui está o XML resultante:
<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>
Embora seja útil construir elementos de expressões constantes, como mostrado neste exemplo, o verdadeiro poder desse recurso de linguagem do XQuery é a capacidade de construir XML capaz de extrair dinamicamente dados de um banco de dados. Você pode usar chaves para especificar expressões de consulta. No XML resultante, a expressão é substituída por seu valor. Por exemplo, a consulta a seguir constrói um elemento com um <NewRoot> elemento filho (<e>). O valor do elemento <e> é computado especificando uma expressão de caminho dentro de chaves ("{ ... }").
DECLARE @x AS XML;
SET @x = '<root>5</root>';
SELECT @x.query('<NewRoot><e> { /root } </e></NewRoot>');
As chaves agem como tokens de troca de contexto e alternam a consulta da construção XML para avaliação de consulta. Nesse caso, a expressão de caminho XQuery dentro das chaves, /root, é avaliada e os resultados são substituídos por ela.
Eis o resultado:
<NewRoot>
<e>
<root>5</root>
</e>
</NewRoot>
A consulta a seguir é semelhante à anterior. No entanto, a expressão nas chaves especifica a data() função para recuperar o valor atômico do <root> elemento e a atribui ao elemento construído. <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;
Eis o resultado:
<NewRoot>
<e>5</e>
</NewRoot>
Para usar as chaves como parte do texto em vez de tokens de troca de contexto, é possível não utilizá-las como "\} \} " ou "\{\{", como mostrado neste exemplo:
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;
Eis o resultado:
<NewRoot> Hello, I can use { and } as part of my text</NewRoot>
A consulta a seguir é outro exemplo de construção de elementos com o uso do construtor de elemento direto. Além disso, o valor do <FirstLocation> elemento é obtido executando a expressão nas chaves. A expressão de consulta retorna as etapas de fabricação no primeiro local de centro de trabalho da coluna Instructions da tabela 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;
Eis o resultado:
<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>
Conteúdo do elemento na construção de XML
O exemplo a seguir ilustra o comportamento das expressões na construção do conteúdo de elemento com o uso do construtor de elemento direto. No exemplo a seguir, o construtor de elemento direto especifica uma expressão. Para essa expressão, um nó de texto é criado no XML resultante.
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>');
A sequência de valor atômico resultante da avaliação de expressão é adicionada ao nó de texto com um espaço adicionado entre os valores atômicos adjacentes, como mostrado no resultado. O elemento construído tem um filho. Ele é um nó de texto que contém o valor mostrado no resultado.
<result>This is step 1 This is step 2 This is step 3</result>
Em vez de uma expressão, se você especificar três expressões separadas que geram três nós de texto, os nós de texto adjacentes serão mesclados em um único nó de texto, por meio de concatenação, no XML resultante.
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>');
O nó de elemento construído tem um filho. Ele é um nó de texto que contém o valor mostrado no resultado.
<result>This is step 1This is step 2This is step 3</result>
Atributos de construção
Ao construir elementos usando o construtor de elemento direto, você também pode especificar atributos do elemento usando a sintaxe semelhante a XML, conforme mostrado neste exemplo:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>');
Aqui está o XML resultante:
<ProductModel ProductModelID="111">
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>
O elemento <ProductModel> construído tem um atributo ProductModelID e estes nós filho:
Um nó de texto,
This is product model catalog description.Um nó de elemento.
<Summary>Esse nó tem um filho de nó de texto,Some description.
Ao construir um atributo, você pode especificar seu valor com uma expressão em chaves. Nesse caso, o resultado da expressão é retornado como o valor de atributo.
No exemplo a seguir, a data() função não é estritamente necessária. Como você está atribuindo o valor da expressão a um atributo, data() é aplicado implicitamente para recuperar o valor digitado da expressão especificada.
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;
Eis o resultado:
<NewRoot attr="5" />
A seguir, um outro exemplo no qual são especificadas expressões para a construção de atributo LocationID e SetupHrs. Essas expressões são avaliadas com base no XML na coluna Instruction. O valor digitado da expressão é atribuído aos atributos.
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;
Este é o resultado parcial:
<FirstLocation LocationID="10" SetupHours="0.5" >
<AWMI:step ...
</AWMI:step>
...
</FirstLocation>
Limitações de implementação
Estas são as limitações:
Não há suporte para expressões de atributo múltiplas ou mistas (cadeia de caracteres e expressão XQuery). Por exemplo, como mostrado na consulta a seguir, você constrói um XML em que
Itemé uma constante e o valor5é obtido avaliando uma expressão de consulta:<a attr="Item 5" />A consulta a seguir retorna um erro, pois você está misturando cadeia de caracteres constante com uma expressão ({/x}) e isso não tem suporte:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="Item {/x}"/>');Nesse caso, você tem as seguintes opções:
Forme o valor de atributo pela concatenação de dois valores atômicos. Esses valores atômicos são serializados no valor de atributo com um espaço entre os valores atômicos:
SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Eis o resultado:
<a attr="Item 5" />Use a função concat para concatenar os dois argumentos de cadeia de caracteres no valor do atributo resultante:
SELECT @x.query('<a attr="{concat(''Item'', /x[1])}"/>');Nesse caso, não há espaço adicionado entre os dois valores de cadeia de caracteres. Se quiser um espaço entre os dois valores, insira-o explicitamente.
Eis o resultado:
<a attr="Item5" />
Não há suporte para várias expressões como um valor de atributo. Por exemplo, a consulta a seguir retorna um erro:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{/x}{/x}"/>');Não há suporte para sequências heterogêneas. Qualquer tentativa de atribuir uma sequência heterogênea como um valor de atributo retorna um erro, conforme mostrado no exemplo a seguir. Neste exemplo, uma sequência heterogênea, uma cadeia de caracteres "Item" e um elemento
<x>, é especificada como o valor do atributo:DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{''Item'', /x }" />');Se você aplicar a
data()função, a consulta funcionará porque ela recuperará o valor atômico da expressão,/xque é concatenada com a cadeia de caracteres. Apresentamos a seguir uma sequência de valores atômicos:SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Eis o resultado:
<a attr="Item 5" />A ordem de nó do atributo é aplicada durante a serialização e não durante a verificação de tipo estático. Por exemplo, a consulta a seguir falha, pois tenta adicionar um atributo depois de um nó sem-atributo.
SELECT CONVERT (XML, '').query(' element x { attribute att { "pass" }, element y { "Element text" }, attribute att2 { "fail" } } '); GOA consulta anterior retorna o seguinte erro:
XML well-formedness check: Attribute cannot appear outside of element declaration. Rewrite your XQuery so it returns well-formed XML.
Adicionar namespaces
Ao construir XML usando os construtores diretos, o elemento construído e os nomes de atributo podem ser qualificados com o uso de um prefixo de namespace. É possível associar o prefixo ao namespace das seguintes formas:
- Usando um atributo de declaração de namespace.
- Usando a
WITH XMLNAMESPACEScláusula. - No prólogo do XQuery.
Usar um atributo de declaração de namespace para adicionar namespaces
O exemplo a seguir usa um atributo de declaração de namespace na construção do elemento <a> para declarar um namespace padrão. A construção do elemento <b> filho desfaz a declaração do namespace padrão declarado no elemento pai.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<a xmlns="a">
<b xmlns=""/>
</a>');
Eis o resultado:
<a xmlns="a">
<b xmlns="" />
</a>
É possível atribuir um prefixo ao namespace. O prefixo é especificado na construção do elemento <a>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b/>
</x:a>');
Eis o resultado:
<x:a xmlns:x="a">
<b />
</x:a>
Você pode cancelar a declaração de um namespace padrão na construção XML, mas não é possível cancelar a declaração de um prefixo de namespace. A consulta a seguir retorna um erro, pois você não pode cancelar a declaração de um prefixo conforme especificado na construção do elemento <b>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b xmlns:x=""/>
</x:a>');
O namespace recentemente construído está disponível para uso na consulta. Por exemplo, a consulta a seguir declara um namespace na construção do elemento <FirstLocation>e especifica o prefixo nas expressões para os valores de atributo LocationID e 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;
A criação de um novo prefixo de namespace dessa forma substitui qualquer declaração de namespace preexistante para esse prefixo. Por exemplo, a declaração de namespace, AWMI="https://someURI"no prolog de consulta, é substituída pela declaração de namespace no <FirstLocation> elemento.
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;
Usar uma caixa de diálogo para adicionar namespaces
Este exemplo ilustra como podem ser adicionados namespaces ao XML construído. Um namespace padrão é declarado no prólogo de consulta.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
declare default element namespace "a";
<a><b xmlns=""/></a>');
Na construção do elemento <b>, o atributo de declaração de namespace é especificado com uma cadeia de caracteres vazia como seu valor. Isso desfaz a declaração do namespace padrão declarado no pai.
Eis o resultado:
<a xmlns="a">
<b xmlns="" />
</a>
Construção XML e manipulação de espaço em branco
O conteúdo de elemento na construção XML pode incluir caracteres de espaço em branco. Esses caracteres são tratados das seguintes formas:
Os caracteres de espaço em branco nos URIs do namespace são tratados como o tipo
anyURIXSD. Especificamente, é assim que eles são tratados:- Qualquer caractere com espaço em branco no início e término é eliminado.
- Os valores de caractere com espaço em branco são reduzidos para um único espaço.
Os caracteres de avanço de linha no conteúdo de atributo são substituídos por espaços. Todos os outros caracteres com espaço em branco permanecem inalterados.
O espaço em branco nos elementos é preservado.
O exemplo a seguir ilustra o tratamento de espaço em branco na construção 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;
Eis o resultado:
-- result
<test attr="<test attr=" my test attr value "><a>
This is a
test
</a></test>
"><a>
This is a
test
</a></test>
Outros construtores XML diretos
Os construtores para instruções de processamento e comentários XML usam a mesma sintaxe que a sintaxe de construção XML correspondente. Construtores computados para nós de texto também são compatíveis, mas são usados XML DML principalmente para construir nós de texto.
Observação
Para obter um exemplo de como usar um construtor de nó de texto explícito, consulte o exemplo específico na inserção (DML XML).
Na consulta a seguir, o XML construído inclui um elemento, dois atributos, um comentário e uma instrução de processamento. Uma vírgula é usada antes do <FirstLocation>, porque uma sequência está sendo construída.
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;
Este é o resultado parcial:
<?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>
Usar construtores computados
Nesse caso, especifique as palavras-chave que identificam o tipo de nó que você deseja construir. São suportadas apenas as seguintes palavras-chave:
- elemento
- atributo
- enviar SMS
Para elemento e nós de atributo, essas palavras-chave são seguidas pelo nome de nó e também pela expressão, entre chaves, que gera o conteúdo para esse nó. No exemplo a seguir, você está construindo este XML:
<root>
<ProductModel PID="5">Some text <summary>Some Summary</summary></ProductModel>
</root>
Esta é a consulta que usa construtores computados que geram o XML:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('element root
{
element ProductModel
{
attribute PID { 5 },
text{"Some text "},
element summary { "Some Summary" }
}
} ');
A expressão que gera o conteúdo de nó pode especificar uma expressão de consulta.
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 }
}
} ');
Os construtores de elemento e atributo computados, conforme definido na especificação XQuery, permitem que você compute os nomes do nó. Quando você estiver usando construtores diretos no SQL Server, os nomes de nó, como elemento e atributo, devem ser especificados como literais constantes. Portanto, não há diferença nos construtores diretos e construtores computados para elementos e atributos.
No exemplo a seguir, o conteúdo dos nós construídos é obtido das instruções de fabricação XML armazenadas na coluna Instruções do tipo de dados xml na tabela 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;
Este é o resultado parcial:
<FirstLocation LocationID="10">
<AllTheSteps>
<AWMI:step> ... </AWMI:step>
<AWMI:step> ... </AWMI:step>
...
</AllTheSteps>
</FirstLocation>
Outras limitações de implementação
Construtores de atributo computados não podem ser usados para declarar um novo namespace. Além disso, não há suporte para os seguintes construtores computados no SQL Server:
- Construtores de nó de documento computados
- Construtores de instrução de processamento computados
- Construtores de comentário computados