Compartir a través de


value() (método del tipo de datos xml)

Realiza una consulta XQuery en datos XML y devuelve un valor de tipo SQL. Este método devuelve un valor escalar.

Normalmente, este método se utiliza para extraer un valor de una instancia XML almacenada en una columna, parámetro o variable de tipo xml. De esta manera, se pueden especificar consultas SELECT que combinen o comparen datos XML con datos de columnas que no son XML.

Sintaxis

value (XQuery, SQLType)

Argumentos

  • XQuery
    Es la expresión XQuery, un literal de cadena, que recupera los datos de la instancia XML. La expresión XQuery debe devolver un valor como máximo. En caso contrario, se devuelve un error.

  • SQLType
    Es el tipo SQL preferido, un literal de cadena, que se devuelve. El tipo de valor devuelto de este método coincide con el parámetro SQLType. SQLType no puede ser un tipo de datos xml, un tipo definido por el usuario de Common Language Runtime (CLR), image, text, ntext o un tipo de datos sql_variant. SQLType puede ser un tipo de datos definido por el usuario SQL.

El método value() utiliza el operador CONVERT de Transact-SQL de manera implícita e intenta convertir el resultado de la expresión XQuery, la representación de cadena serializada, del tipo XSD al tipo SQL correspondiente especificado por la conversión Transact-SQL. Para obtener más información acerca de las reglas de conversión de tipos de CONVERT, vea CAST y CONVERT (Transact-SQL).

[!NOTA]

Por motivos de rendimiento, en lugar de utilizar el método value() en un predicado para la comparación con un valor relacional, utilice exist() con sql:column(). Esto se muestra en el ejemplo D a continuación.

Ejemplos

A. Utilizar el método value() con una variable de tipo xml

En el ejemplo siguiente, una instancia XML está almacenada en una variable de tipo xml. El método value() recupera el valor del atributo ProductID en el XML. Después, el valor se asigna a una variable int.

DECLARE @myDoc xml
DECLARE @ProdID int
SET @myDoc = '<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features>
  <Warranty>1 year parts and labor</Warranty>
  <Maintenance>3 year parts and labor extended maintenance is available</Maintenance>
</Features>
</ProductDescription>
</Root>'

SET @ProdID =  @myDoc.value('(/Root/ProductDescription/@ProductID)[1]', 'int' )
SELECT @ProdID

Como resultado se devuelve el valor 1.

Aunque hay un solo atributo ProductID en la instancia XML, las reglas de los tipos estáticos requieren que se especifique explícitamente que la expresión de ruta de acceso devuelva un singleton. Por tanto, se especifica [1] al final de la expresión de ruta de acceso. Para obtener más información acerca de los tipos estáticos, vea XQuery y el establecimiento de tipos estáticos.

B. Utilizar el método value() para recuperar un valor de una columna de tipo xml

La siguiente consulta se especifica sobre una columna de tipo xml (CatalogDescription) de la base de datos AdventureWorks. La consulta recupera los valores del atributo ProductModelID de cada instancia XML almacenada en la columna.

SELECT CatalogDescription.value('           
    declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";           
       (/PD:ProductDescription/@ProductModelID)[1]', 'int') AS Result           
FROM Production.ProductModel           
WHERE CatalogDescription IS NOT NULL           
ORDER BY Result desc           

Observe lo siguiente en la consulta anterior:

  • Se utiliza la palabra clave namespace para definir un prefijo de espacio de nombres.

  • Según los requisitos de los tipos estáticos, se agrega [1] al final de la expresión de ruta de acceso del método value() para indicar explícitamente que la expresión de ruta de acceso devuelva un singleton.

Éste es el resultado parcial:

-----------
35         
34         
...

C. Utilizar los métodos value() y exist() para recuperar valores de una columna de tipo xml

En el siguiente ejemplo se muestra el uso del método value() y el método exist() del tipo de datos xml. El método value() se utiliza para recuperar los valores del atributo ProductModelID del XML. El método exist() de la cláusula WHERE se utiliza para filtrar las filas de la tabla.

La consulta recupera los identificadores de modelo de producto de las instancias XML que incluyen información de garantía (el elemento <Warranty>) entre sus características. La condición de la cláusula WHERE utiliza el método exist() para recuperar únicamente las filas que cumplan esta condición.

SELECT CatalogDescription.value('
     declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
           (/PD:ProductDescription/@ProductModelID)[1] ', 'int') as Result
FROM  Production.ProductModel
WHERE CatalogDescription.exist('
     declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
     declare namespace wm="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain";

     /PD:ProductDescription/PD:Features/wm:Warranty ') = 1

Observe lo siguiente en la consulta anterior:

  • La columna CatalogDescription es una columna XML con tipo. Esto significa que tiene asociada una colección de esquemas. En el prólogo de las consultas XQuery, se utiliza la declaración del espacio de nombres para definir el prefijo que se utilizará posteriormente en el cuerpo de la consulta.

  • Si el método exist() devuelve 1 (True), significa que la instancia XML incluye el elemento secundario <Warranty> entre sus características.

  • Después, el método value() de la cláusula SELECT recupera los valores del atributo ProductModelID como enteros.

Éste es el resultado parcial:

Result     
-----------
19         
23         
...

D. Utilizar el método exist() en lugar del método value()

Por motivos de rendimiento, en lugar de utilizar el método value() de un predicado para compararlo con un valor relacional, utilice exist() con sql:column(). Por ejemplo:

CREATE TABLE T (c1 int, c2 varchar(10), c3 xml)
GO

SELECT c1, c2, c3 
FROM T
WHERE c3.value( '/root[1]/@a', 'integer') = c1
GO

Esto se puede escribir de la forma siguiente:

SELECT c1, c2, c3 
FROM T
WHERE c3.exist( '/root[@a=sql:column("c1")]') = 1
GO