Compartilhar via


Tipos de dados XPath (SQLXML 4.0)

Aplica-se a: Banco de Dados SQL do Azure do SQL Server

O Microsoft SQL Server, XPath e XML Schema (XSD) têm tipos de dados muito diferentes. Por exemplo, o XPath não tem tipos de dados inteiros ou de data, mas o SQL Server e o XSD têm muitos. O XSD usa precisão de nanossegundos para valores de tempo e o SQL Server usa no máximo precisão de 1/300 de segundo. Consequentemente, o mapeamento de um tipo de dados para outro nem sempre é possível. Para obter mais informações sobre como mapear tipos de dados do SQL Server para tipos de dados XSD, consulte Coerções de tipo de dados e a anotação sql:datatype (SQLXML 4.0).

O XPath tem três tipos de dados: string, number e boolean. O tipo de dados numérico é sempre um ponto flutuante de precisão dupla IEEE 754. O tipo de dados float(53) do SQL Serveré o mais próximo do número XPath. No entanto, float(53) não é exatamente IEEE 754. Por exemplo, nem NaN (não é um número) nem infinidade é usado. Tentar converter uma cadeia de caracteres não numérica em número e tentar dividir por zero resulta em um erro.

Conversões do XPath

Quando você usa uma consulta do XPath como OrderDetail[@UnitPrice > "10.0"], conversões de tipos de dados implícitas e explícitas podem alterar sutilmente o significado da consulta. Por isso, é importante entender como são implementados os tipos de dados XPath. A especificação da linguagem XPath, XML Path Language (XPath) versão 1.0 W3C Proposed Recommendation 8 October 1999, pode ser encontrada no site do W3C em http://www.w3.org/TR/1999/PR-xpath-19991008.html.

Os operadores de XPath são divididos em quatro categorias:

  • Operadores boolianos (e, ou)

  • Operadores relacionais (<, >, <=, >=)

  • Operadores de igualdade (=, !=)

  • Operadores aritméticos (+, -, *, div, mod)

Cada categoria de operador converte os respectivos operandos de forma diferente. Os operadores de XPath convertem implicitamente seus operandos se necessário. Os operadores aritméticos convertem seus operandos em número e resultam em um valor numérico. Os operadores booleanos convertem seus operandos em booleanos e resultam em um valor booliano. Os operadores relacionais e operadores de igualdade resultam em um valor booliano. Entretanto, eles têm diferentes regras de conversão dependendo dos tipos de dados originais dos respectivos operandos, conforme mostra esta tabela.

Operando Operador relacional Operador de igualdade
Ambos os operandos são conjuntos de nós. TRUE se e somente se houver um nó em um conjunto e um nó no segundo conjunto, de modo que a comparação de seus valores de cadeia de caracteres seja TRUE. Idem.
Um é um conjunto de nós, o outro uma string. TRUE se e somente se houver um nó no conjunto de nós de modo que, quando convertido em número, a comparação dele com a cadeia de caracteres convertida em número seja VERDADEIRO. TRUE se e somente se houver um nó no conjunto de nós de modo que, quando convertido em string, a comparação dele com a string seja TRUE.
Um é um conjunto de nós, o outro um número. VERDADEIRO se e somente se houver um nó no conjunto de nós de modo que, quando convertido em número, a comparação dele com o número seja VERDADEIRO. Idem.
Um é um conjunto de nós, o outro um booleano. TRUE se e somente se houver um nó no conjunto de nós de modo que, quando convertido em booleano e depois em número, a comparação dele com o booleano convertido em número seja VERDADEIRO. TRUE se e somente se houver um nó no conjunto de nós de modo que, quando convertido em booleano, a comparação dele com o booleano seja TRUE.
Nenhum é um conjunto de nós. Converta os dois operandos em número e compare. Converta ambos os operandos em um tipo comum e compare. Converta em booleano se um for booleano, número se qualquer um for número; caso contrário, converta em string.

Observação

Como os operadores relacionais XPath sempre convertem seus operandos em número, as comparações de cadeia de caracteres não são possíveis. Para incluir comparações de data, o SQL Server 2000 oferece esta variação para a especificação XPath: Quando um operador relacional compara uma cadeia de caracteres com uma cadeia de caracteres, um conjunto de nós com uma cadeia de caracteres ou um conjunto de nós com valor de cadeia de caracteres com um conjunto de nós com valor de cadeia de caracteres, uma comparação de cadeia de caracteres (não uma comparação de número ) é executada.

Conversões de conjuntos de nós

As conversões de conjuntos de nós nem sempre são intuitivas. Um conjunto de nós é convertido em uma cadeia de caracteres usando o valor da cadeia de caracteres apenas do primeiro nó do conjunto. Um conjunto de nós é convertido em número convertendo-o em cadeia de caracteres e, em seguida, convertendo cadeia de caracteres em número. Um conjunto de nós é convertido em booleano testando sua existência.

Observação

O SQL Server não executa a seleção posicional em conjuntos de nós: por exemplo, a consulta Customer[3] XPath significa o terceiro cliente; esse tipo de seleção posicional não tem suporte no SQL Server. Portanto, as conversões de conjunto de nós para cadeia de caracteres ou conjunto de nós para número , conforme descrito pela especificação XPath, não são implementadas. O SQL Server usa a semântica "qualquer" sempre que a especificação XPath especifica a semântica "primeira". Por exemplo, com base na especificação XPath do W3C, a consulta Order[OrderDetail/@UnitPrice > 10.0] XPath seleciona os pedidos com o primeiro OrderDetail que tem um UnitPrice maior que 10,0. No SQL Server, essa consulta XPath seleciona esses pedidos com qualquer OrderDetail que tenha um UnitPrice maior que 10.0.

A conversão para booleano gera um teste de existência; portanto, a consulta Products[@Discontinued=true()] XPath é equivalente à expressão SQL "Products.Discontinued is not null", não à expressão SQL "Products.Discontinued = 1". Para tornar a consulta equivalente à última expressão SQL, primeiro converta o conjunto de nós em um tipo não booliano , como number. Por exemplo, Products[number(@Discontinued) = true()].

Como a maioria dos operadores é definida como TRUE se é TRUE para qualquer um ou para um dos nós do conjunto, essas operações sempre avaliam como FALSE se o conjunto está vazio. Assim, se A está vazio, tanto A = B quanto A != B são FALSE, e not(A=B) e not(A!=B) são TRUE.

Normalmente, um atributo ou elemento que mapeia para uma coluna existe se o valor dessa coluna no banco de dados não for nulo. Os elementos que fazem o mapeamento para linhas existirão se qualquer um dos filhos existir.

Observação

Os elementos anotados com is-constant sempre existem. Consequentemente, os predicados XPath não podem ser usados em elementos is-constant .

Quando um conjunto de nós é convertido em cadeia de caracteres ou número, seu tipo XDR (se houver) é inspecionado no esquema anotado e esse tipo é usado para determinar a conversão necessária.

Mapeando tipos de dados XDR para tipos de dados XPath

O tipo de dados XPath de um nó é derivado do tipo de dados XDR no esquema, conforme mostrado na tabela a seguir (o nó EmployeeID é usado para fins ilustrativos).

Tipo de dados XDR Equivalente

tipos de dados XPath
Conversão do SQL Server usada
Nonebin.base64bin.hex N/D Nenhuma_do_funcionário
boolean boolean CONVERT(bit, EmployeeID)
number, int, float,i1, i2, i4, i8,r4, r8ui1, ui2, ui4, ui8 número CONVERT(float(53), EmployeeID)
id, idref, idrefsentity, entities, enumerationnotation, nmtoken, nmtokens, chardate, Timedate, Time.tz, string, uri, uuid string CONVERT(nvarchar(4000), EmployeeID, 126)
fixed14.4 N/D (não há nenhum tipo de dados no XPath equivalente ao tipo de dados XDR fixed14.4) CONVERT(money, EmployeeID)
date string LEFT(CONVERT(nvarchar(4000), EmployeeID, 126), 10)
time

time.tz
string SUBSTRING(CONVERT(nvarchar(4000), EmployeeID, 126), 1 + CHARINDEX(N'T', CONVERT(nvarchar(4000), EmployeeID, 126)), 24)

As conversões de data e hora são projetadas para funcionar se o valor for armazenado no banco de dados usando o tipo de dados datetime do SQL Serverou uma cadeia de caracteres. Observe que o tipo de dados datetime do SQL Servernão usa fuso horário e tem uma precisão menor do que o tipo de dados de hora XML. Para incluir o tipo de dados de fuso horário ou precisão adicional, armazene os dados no SQL Server usando um tipo de cadeia de caracteres .

Quando um nó é convertido do tipo de dados XDR no tipo de dados XPath, às vezes é necessária conversão adicional (de um tipo de dados XPath para outro tipo de dados XPath). Por exemplo, considere esta consulta do XPath:

(@m + 3) = 4  

Se @m for do tipo de dados XDR fixed14.4 , a conversão do tipo de dados XDR para o tipo de dados XPath será realizada usando:

CONVERT(money, m)  

Nessa conversão, o nó m é convertido de fixed14.4 para money. Porém, a adição do valor de 3 exige conversão adicional:

CONVERT(float(CONVERT(money, m))  

A expressão do XPath é avaliada como:

CONVERT(float(CONVERT(money, m)) + CONVERT(float(53), 3) = CONVERT(float(53), 3)  

Conforme mostra a tabela a seguir, essa é a mesma conversão aplicada para outras expressões do XPath (como literais ou expressões compostas).

X é a incógnita X é string X é o número X é booleano
cadeia de caracteres(X) CONVERT (nvarchar(4000), X, 126) - CONVERT (nvarchar(4000), X, 126) CASE WHEN X THEN N'true' ELSE N'false' END
número(X) CONVERT (float(53), X) CONVERT (float(53), X) - CASE WHEN X THEN 1 ELSE 0 END
booleano(X) - LEN(X) > 0 X != 0 -

Exemplos

R. Converter um tipo de dados em uma consulta do XPath

Na consulta XPath a seguir especificada em relação a um esquema XSD anotado, a consulta seleciona todos os nós Employee com o valor do atributo EmployeeID de E-1, em que "E-" é o prefixo especificado usando a anotação sql:id-prefix .

Employee[@EmployeeID="E-1"]

O predicado na consulta é equivalente à expressão SQL:

N'E-' + CONVERT(nvarchar(4000), Employees.EmployeeID, 126) = N'E-1'

Como EmployeeID é um dos valores de tipo de dados id (idref, idrefs, nmtoken, nmtokens e assim por diante) no esquema XSD, EmployeeID é convertido no tipo de dados XPath de cadeia de caracteres usando as regras de conversão descritas anteriormente.

CONVERT(nvarchar(4000), Employees.EmployeeID, 126)

O prefixo "E -" é adicionado à cadeia de caracteres, e o resultado é comparado com N'E-1'.

B. Executar várias conversões de tipo de dados em uma consulta do XPath

Considere esta consulta do XPath especificada com base em um esquema XSD anotado: OrderDetail[@UnitPrice * @OrderQty > 98]

Essa consulta XPath retorna todos os <elementos OrderDetail> que satisfazem o predicado @UnitPrice * @OrderQty > 98. Se o UnitPrice for anotado com um tipo de dados fixed14.4 no esquema anotado, esse predicado será equivalente à expressão SQL:

CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice)) * CONVERT(float(53), OrderDetail.OrderQty) > CONVERT(float(53), 98)

Ao converter os valores na consulta do XPath, ocorre a primeira conversão do tipo de dados XDR no tipo de dados XPath. Como o tipo de dados XSD de UnitPrice é fixed14.4, conforme descrito na tabela anterior, essa é a primeira conversão usada:

CONVERT(money, OrderDetail.UnitPrice))   

Como os operadores aritméticos convertem seus operandos para o tipo de dados XPath numérico, a segunda conversão (de um tipo de dados XPath para outro tipo de dados XPath) é aplicada na qual o valor é convertido em float(53) (float(53) está próximo ao tipo de dados numérico XPath):

CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice))   

Supondo que o atributo OrderQty não tenha nenhum tipo de dados XSD, OrderQty é convertido em um tipo de dados XPath numérico em uma única conversão:

CONVERT(float(53), OrderDetail.OrderQty)  

Da mesma forma, o valor 98 é convertido para o tipo de dados XPath numérico :

CONVERT(float(53), 98)  

Observação

Se o tipo de dados XSD usado no esquema for incompatível com o tipo de dados subjacente do SQL Server no banco de dados ou se uma conversão de tipo de dados XPath impossível for executada, o SQL Server poderá retornar um erro. Por exemplo, se o atributo EmployeeID for anotado com a anotação id-prefix , o XPath Employee[@EmployeeID=1] gerará um erro, pois EmployeeID tem a anotação id-prefix e não pode ser convertido em número.