Regras de conversão de tipos em XQuery

O diagrama de especificações de funções e operadores do W3C XQuery 1.0 e do XPath 2.0 mostra os tipos de dados internos. Isso inclui os tipos derivados e primitivos internos.

Hierarquia de tipo XQuery 1.0

Este tópico descreve as regras de conversão de tipos aplicadas à conversão de um tipo em outro usando um dos seguintes métodos:

  • Conversão explícita que você faz usando cast as ou as funções de construtor de tipo (por exemplo, xs:integer("5")).

  • Conversão implícita que ocorre durante a promoção de tipos

Conversão explícita

A tabela a seguir descreve a conversão de tipos permitida entre os tipos primitivos internos.

Descreve as regras de conversão para Xquery.

  • Um tipo primitivo interno pode ser convertido em outro tipo primitivo interno, com base nas regras na tabela.

  • Um tipo primitivo pode ser convertido em qualquer tipo derivado desse tipo primitivo. Por exemplo, você pode converter de xs:decimal em xs:integer, ou de xs:decimal em xs:long.

  • Um tipo derivado pode ser convertido em qualquer tipo que seja seu ancestral na hierarquia de tipo, todo o caminho até o seu tipo base primitivo interno. Por exemplo, você pode converter de xs:token em xs:normalizedString ou em xs:string.

  • Um tipo derivado poderá ser convertido em um tipo primitivo se seu ancestral primitivo puder ser convertido no tipo de destino. Por exemplo, você pode converter xs:integer, um tipo derivado, em um xs:string, um tipo primitivo, pois xs:decimal, o ancestral primitivo do xs:integer, pode ser convertido em xs:string.

  • Um tipo derivado pode ser convertido em outro tipo derivado se o ancestral primitivo do tipo de origem puder ser convertido no ancestral primitivo do tipo de destino. Por exemplo, você pode converter de xs:integer em xs:token, pois é possível converter de xs:decimal em xs:string.

  • As regras de conversão de tipos definidos pelo usuário em tipos internos são as mesmas para os tipos internos. Por exemplo, você pode definir um tipo derivado myInteger do tipo xs:integer. Em seguida, myInteger pode ser convertido em xs:token, pois xs:decimal pode ser convertido em xs:string.

Não há suporte para os seguintes tipos de conversão:

  • Não é permitida a conversão em ou de tipos de lista. Isso inclui tipos de lista definidos pelo usuário e tipos de lista internos, como xs:IDREFS, xs:ENTITIES e xs:NMTOKENS.

  • Não há suporte para conversão em ou de xs:QName.

  • Não há suporte para xs:NOTATION e para os subtipos completamente ordenados de duração, xdt:yearMonthDuration e xdt:dayTimeDuration. Conseqüentemente, não há suporte para conversão em ou desses tipos.

Os exemplos a seguir ilustram a conversão de tipo explícito.

Exemplo A

O exemplo a seguir consulta uma variável de tipo xml. A consulta retorna uma seqüência de um valor de tipo simples digitada como xs:string.

declare @x xml
set @x = '<e>1</e><e>2</e>'
select @x.query('/e[1] cast as xs:string?')
go

Exemplo B

O exemplo a seguir consulta uma variável xml digitada. O exemplo cria primeiro uma coleção de esquemas XML. Em seguida, utiliza a coleção de esquemas XML para criar uma variável xml digitada. O esquema fornece as informações de digitação para a instância XML atribuída à variável. São, então, especificadas consultas na variável.

create xml schema collection myCollection as N'
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="root">
            <xs:complexType>
                  <xs:sequence>
                        <xs:element name="A" type="xs:string"/>
                        <xs:element name="B" type="xs:string"/>
                        <xs:element name="C" type="xs:string"/>
                  </xs:sequence>
            </xs:complexType>
      </xs:element>
</xs:schema>'
go

A consulta a seguir retorna um erro estático, pois você não sabe quantos elementos <root> de nível superior estão na instância de documento.

declare @x xml(myCollection)
set @x = '<root><A>1</A><B>2</B><C>3</C></root>
          <root><A>4</A><B>5</B><C>6</baz></C>'
select @x.query('/root/A cast as xs:string?')
go

Ao especificar um elemento <root> singleton na expressão, a consulta tem êxito. A consulta retorna uma seqüência de um valor de tipo simples digitada como xs:string.

declare @x xml(myCollection)
set @x = '<root><A>1</A><B>2</B><C>3</C></root>
              <root><A>4</A><B>5</B><C>6</C></root>'
select @x.query('/root[1]/A cast as xs:string?')
go

No exemplo a seguir, a variável de tipo xml inclui uma palavra-chave de documento que especifica a coleção de esquemas XML. Isso indica que a instância XML deve ser um documento que tenha um único elemento de nível superior. Se você criar dois elementos <root> na instância XML, será retornado um erro.

declare @x xml(document myCollection)
set @x = '<root><A>1</A><B>2</B><C>3</C></root>
              <root><A>4</A><B>5</B><C>6</C></root>'
go

Você pode alterar a instância para incluir apenas um elemento de nível superior. Dessa forma, a consulta funcionará. Novamente, a consulta retorna uma seqüência de um valor de tipo simples digitado como xs:string.

declare @x xml(document myCollection)
set @x = '<root><A>1</A><B>2</B><C>3</C></root>'
select @x.query('/root/A cast as xs:string?')
go

Conversão implícita

A conversão implícita só é permitida para tipos numéricos e tipos atômicos não digitados. Por exemplo, a função min() a seguir retorna o mínimo dos dois valores:

min(xs:integer("1"), xs:double("1.1"))

Nesse exemplo, os dois valores passados na função min() XQuery são de tipos diferentes. Portanto, a conversão implícita é executada onde o tipo inteiro é promovido para duplo e os dois valores duplos são comparados.

A promoção de tipo como descrita nesse exemplo segue estas regras:

  • Um tipo numérico derivado interno pode ser promovido a seu tipo básico. Por exemplo, um inteiro pode ser promovido a decimal.

  • Um decimal pode ser promovido a flutuante e um flutuante pode ser promovido a duplo.

Como a conversão implícita só é permitida para tipos numéricos, o seguinte não é permitido:

  • Conversão implícita para tipos de cadeia de caracteres. Por exemplo, se dois tipos de cadeia de caracteres forem esperados e você passar uma cadeia de caracteres e um token, nenhuma conversão implícita ocorrerá e um erro será retornado.

  • Conversão implícita de tipos numéricos em tipos de cadeia de caracteres. Por exemplo, se você passar um valor do tipo inteiro em uma função que está esperando um parâmetro de tipo de cadeia de caracteres, nenhuma conversão implícita ocorrerá e um erro será retornado.

Convertendo valores

Ao converter de um tipo a outro, os valores reais são transformados do espaço de valor do tipo de origem no espaço de valor do tipo de destino. Por exemplo, a conversão de um xs:decimal em um xs:double transformará o valor decimal em um valor duplo.

A seguir são apresentadas algumas das regras de transformação.

Convertendo um valor de um tipo de cadeia de caracteres ou untypedAtomic

O valor que está sendo convertido em um tipo de cadeia de caracteres ou untypedAtomic é transformado da mesma maneira que a validação do valor com base nas regras do tipo de destino. Isso inclui as regras de processamento de espaço em branco e padrão eventual. Por exemplo, o apresentado a seguir terá êxito e gerará um valor duplo, 1.1e0:

xs:double("1.1")

Na conversão em tipos binários, como xs:base64Binary ou xs:hexBinary, de um tipo de cadeia de caracteres ou untypedAtomic, os valores de entrada precisam ser codificados como base64 ou hex, respectivamente.

Convertendo um valor em um tipo de cadeia de caracteres ou untypedAtomic

A conversão em um tipo de cadeia de caracteres ou untypedAtomic transforma o valor em sua representação léxica canônica do XQuery. Especificamente, isso pode significar que um valor que pode ter obedecido a um padrão específico ou outra restrição durante a entrada não será representado de acordo com essa restrição. Para informar isso aos usuários, o SQL Server sinaliza os tipos em que a restrição de tipo pode ser um problema apresentando um aviso quando esses tipos são carregados na coleção de esquemas.

Ao converter um valor do tipo xs:float ou xs:double, ou qualquer um de seus subtipos, em um tipo de cadeia de caracteres ou untypedAtomic, o valor será representado em notação científica. Isso só é realizado quando o valor absoluto do valor é inferior a 1.0E-6, ou superior ou igual a 1.0E6. Isso significa que 0 é serializado em notação científica para 0.0E0.

Por exemplo, xs:string(1.11e1) retornará o valor da cadeia de caracteres "11.1", enquanto xs:string(-0.00000000002e0) retornará o valor da cadeia de caracteres, "-2.0E-11".

Na conversão de tipos binários, como xs:base64Binary ou xs:hexBinary, em um tipo de cadeia de caracteres ou untypedAtomic, os valores binários serão representados em sua forma codificada base64 ou hex, respectivamente.

Convertendo um valor em um tipo numérico

Na conversão de um valor de um tipo numérico em um valor de outro tipo numérico, o valor é mapeado de um espaço de valor para outro sem passar pela serialização da cadeia de caracteres. Se o valor não atender à restrição de um tipo de destino, as seguintes regras serão aplicadas:

  • Se o valor de origem já for numérico e o tipo de destino for xs:float ou um subtipo que permita valores -INF ou INF e a conversão do valor numérico de origem resultar em um estouro, o valor será mapeado para INF se o valor for positivo ou -INF se o valor for negativo. Se o tipo de destino não permitir INF ou -INF e ocorrer um estouro, haverá falha na conversão e o resultado nessa versão do SQL Server será a seqüência vazia.

  • Se o valor de origem já for numérico e o tipo de destino for um tipo numérico, que inclui 0, -0e0 ou 0e0 em seu intervalo de valores aceito, e a conversão do valor numérico de destino resultar em um estouro, o valor será mapeado das seguintes formas:

    • O valor será mapeado para 0 para um tipo de destino decimal.

    • O valor será mapeado para -0e0 quando o valor for um estouro negativo.

    • O valor será mapeado para 0e0 quando o valor for um estouro negativo positivo para um tipo de destino flutuante ou duplo.

    Se o tipo de destino não incluir zero em seu espaço de valor, haverá falha na conversão e o resultado será a seqüência vazia.

    Observe que essa conversão de um valor em um tipo binário de ponto flutuante, como xs:float, xs:double ou qualquer um dos subtipos, poderá perder precisão.

Limitações de implementação

Estas são as limitações:

  • Não há suporte para o valor do ponto flutuante NaN.

  • Os valores conversíveis são restritos pelas restrições de implementação de tipos designadas. Por exemplo, você não pode converter uma cadeia de caracteres de dados com um ano negativo em xs:date. Tal conversão resultará em uma seqüência vazia se o valor for fornecido em tempo de execução (em vez de gerar um erro de tempo de execução).

Consulte também

Conceitos