Compartir a través de


Expresiones de secuencias (XQuery)

SQL Server admite los operadores XQuery que se utilizan para generar, filtrar y combinar una secuencia de elementos. Un elemento puede ser un valor atómico o un nodo.

Generar secuencias

El operador de comas se puede utilizar para generar una secuencia que concatene los elementos en una única secuencia.

Una secuencia puede contener valores duplicados. Las secuencias anidadas (una secuencia dentro de otra) se contraen. Por ejemplo, la secuencia (1, 2, (3, 4, (5))) pasa a ser (1, 2, 3, 4, 5). A continuación, se ofrecen ejemplos de cómo se generan secuencias.

Ejemplo A

La consulta siguiente devuelve una secuencia de cinco valores atómicos:

declare @x xml
set @x=''
select @x.query('(1,2,3,4,5)')
go
-- result 1 2 3 4 5

La consulta siguiente devuelve una secuencia de dos nodos:

-- sequence of 2 nodes
declare @x xml
set @x=''
select @x.query('(<a/>, <b/>)')
go
-- result
<a />
<b />

La consulta siguiente devuelve un error, porque se pretende generar una secuencia de valores atómicos y nodos. Esta es una secuencia heterogénea y no se admite.

declare @x xml
set @x=''
select @x.query('(1, 2, <a/>, <b/>)')
go

Ejemplo B

La consulta siguiente genera una secuencia de valores atómicos mediante la combinación de cuatro secuencias de distinta longitud en una única secuencia.

declare @x xml
set @x=''
select @x.query('(1,2),10,(),(4, 5, 6)')
go
-- result = 1 2 10 4 5 6

La secuencia se puede ordenar mediante FLOWR y ORDER BY:

declare @x xml
set @x=''
select @x.query('for $i in ((1,2),10,(),(4, 5, 6))
                  order by $i
                  return $i')
go

Para contar los elementos de la secuencia se puede utilizar la función fn:count().

declare @x xml
set @x=''
select @x.query('count( (1,2,3,(),4) )')
go
-- result = 4

Ejemplo C

La consulta siguiente se especifica para la columna de tipo xml AdditionalContactInfo de la tabla Contact. Esta columna almacena información de contacto adicional, como uno o más números de teléfono adicionales, números de buscapersonas y direcciones. <telephoneNumber>, <pager> y otros nodos pueden aparecer en cualquier lugar del documento. La consulta genera una secuencia que contiene todos los elementos secundarios de <telephoneNumber> del nodo de contexto, seguidos de los elementos secundarios de <pager>. Observe el uso del operador de comas de la secuencia en la expresión devuelta, ($a//act:telephoneNumber, $a//act:pager).

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes' AS act,
 'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo' AS aci)

SELECT AdditionalContactInfo.query('
   for $a in /aci:AdditionalContactInfo 
   return ($a//act:telephoneNumber, $a//act:pager)
') As Result
FROM Person.Contact
WHERE ContactID=3

El resultado es el siguiente:

<act:telephoneNumber xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
  <act:number>333-333-3333</act:number>
</act:telephoneNumber>
<act:telephoneNumber xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
  <act:number>333-333-3334</act:number>
</act:telephoneNumber>
<act:pager xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
  <act:number>999-555-1244</act:number>
  <act:SpecialInstructions>
Page only in case of emergencies.
</act:SpecialInstructions>
</act:pager>

Filtrar secuencias

Es posible filtrar la secuencia devuelta por una expresión si se agrega un predicado a la expresión. Para obtener más información, consulte Expresiones de ruta de acceso (XQuery). Por ejemplo, la consulta siguiente devuelve una secuencia de tres nodos de elemento <a>:

declare @x xml
set @x = '<root>
<a attrA="1">111</a>
<a></a>
<a></a>
</root>'
SELECT @x.query('/root/a')

El resultado es el siguiente:

<a attrA="1">111</a>
<a />
<a />

Para recuperar solo los elementos <a> que tengan el atributo attrA, se puede especificar un filtro en el predicado. La secuencia resultante tendrá un único elemento <a>.

declare @x xml
set @x = '<root>
<a attrA="1">111</a>
<a></a>
<a></a>
</root>'
SELECT @x.query('/root/a[@attrA]')

El resultado es el siguiente:

<a attrA="1">111</a>

Para obtener más información sobre cómo especificar predicados en una expresión de ruta de acceso, vea Especificar predicados en un paso de expresión de ruta de acceso.

En el ejemplo siguiente se genera una expresión de secuencia de subárboles y, después, se aplica un filtro al flujo.

declare @x xml
set @x = '
<a>
  <c>C under a</c>
</a>
<b>  
   <c>C under b</c>
</b>
<c>top level c</c>
<d></d>
'

La expresión de (/a, /b) genera una secuencia con los subárboles /a y /b, y, en la secuencia resultante, la expresión filtra el elemento <c>.

SELECT @x.query('
  (/a, /b)/c
')

El resultado es el siguiente:

<c>C under a</c>
<c>C under b</c>

En el ejemplo siguiente se aplica un filtro de predicado. La expresión busca los elementos <a> y <b> que contienen el elemento <c>.

declare @x xml
set @x = '
<a>
  <c>C under a</c>
</a>
<b>  
   <c>C under b</c>
</b>

<c>top level c</c>
<d></d>
'
SELECT @x.query('
  (/a, /b)[c]
')

El resultado es el siguiente:

<a>
  <c>C under a</c>
</a>
<b>
  <c>C under b</c>
</b>

Limitaciones de la implementación

Estas son las limitaciones:

  • No se admiten las expresiones de rango XQuery.

  • Las secuencias deben ser homogéneas. Concretamente, todos los elementos de una secuencia deben ser nodos o valores atómicos. Esto se comprueba de manera estática.

  • No se admite la combinación de secuencias de nodos por medio del operador UNION, INTERSECT o EXCEPT.

Vea también

Conceptos

Expresiones XQuery