Fonction sql:column() (XQuery)

Comme décrit dans la rubrique Liaison de données relationnelles dans des données XML, vous pouvez utiliser la fonction sql:column() en combinaison avec des méthodes de type de données XML pour exposer une valeur relationnelle dans XQuery.

Par exemple, la méthode query() (type de données XML) permet de préciser une requête portant sur une instance XML stockée dans une variable ou une colonne de type xml. Il se peut également que vous vouliez que votre requête utilise des valeurs provenant d'une autre colonne non XML, afin de regrouper des données relationnelles et des données XML. Pour ce faire, vous pouvez utiliser la fonction sql:column().

La valeur SQL est alors mappée à sa valeur XQuery correspondante et son type à son type de base XQuery équivalent au type SQL.

Syntaxe

sql:column("columnName")

Notes

Il est à noter qu'une référence à une colonne spécifiée dans la fonction sql:column() d'une requête XQuery fait référence à une colonne de la ligne en cours de traitement.

Dans SQL Server, vous pouvez uniquement faire référence à une instance xml dans le contexte de l'expression source d'une instruction d'insertion XML-DML ; sinon, vous ne pouvez pas faire référence à des colonnes de type xml ou de type CLR défini par l'utilisateur.

La fonction sql:column() n'est pas prise en charge dans les opérations JOIN. Vous pouvez utiliser l'opération APPLY à la place.

Exemples

A. Utilisation de sql:column() pour récupérer une valeur relationnelle dans du code XML

Concernant la construction XML, l'exemple suivant illustre la méthode à suivre pour récupérer des valeurs dans une colonne relationnelle non XML afin de lier les données XML et les données relationnelles.

La requête construit du code XML se présentant sous la forme suivante :

<Product ProductID="771" ProductName="Mountain-100 Silver, 38" ProductPrice="3399.99" ProductModelID="19" 
  ProductModelName="Mountain 100" />

Il est à noter les points suivants dans le code XML ainsi construit :

  • La valeur des attributs ProductID, ProductName et ProductPrice s'obtiennent à partir de la table Product.

  • La valeur de l'attribut ProductModelID est récupérée à partir de la table ProductModel.

  • Pour rendre la requête plus intéressante, la valeur de l'attribut ProductModelName est obtenue à partir de la colonne CatalogDescription de type xml. Comme les informations du catalogue de modèles de produits XML ne sont pas stockées pour tous les modèles de produits, l'instruction if ne permet de récupérer la valeur que si elle existe.

    SELECT P.ProductID, CatalogDescription.query('
    declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
           <Product 
               ProductID=       "{ sql:column("P.ProductID") }"
               ProductName=     "{ sql:column("P.Name") }"
               ProductPrice=    "{ sql:column("P.ListPrice") }"
               ProductModelID= "{ sql:column("PM.ProductModelID") }" >
               { if (not(empty(/pd:ProductDescription))) then
                 attribute ProductModelName { /pd:ProductDescription[1]/@ProductModelName }
                else 
                   ()
    }
            </Product>
    ') as Result
    FROM Production.ProductModel PM, Production.Product P
    WHERE PM.ProductModelID = P.ProductModelID
    AND   CatalogDescription is not NULL
    ORDER By PM.ProductModelID
    

Vous remarquerez les points suivants relatifs à la requête précédente :

  • Les valeurs étant issues de deux tables différentes, la clause FROM doit mentionner ces deux tables. La condition stipulée dans la clause WHERE filtre le résultat et ne récupère ainsi que les produits dont les modèles disposent d'une description mentionnée dans le catalogue.

  • Le mot clé namespace mentionné dans le prologue de la requête XQuery définit le préfixe d'espace de noms (à savoir « pd ») utilisé dans le corps de la requête. Il reste à noter que les alias de table, à savoir « P » et « PM », sont définis dans la clause FROM de la requête même.

  • La fonction sql:column() sert à transférer des valeurs non XML aux données XML.

Voici le résultat partiel :

ProductID               Result
-----------------------------------------------------------------
771         <Product ProductID="771"                   ProductName="Mountain-100 Silver, 38" 
                  ProductPrice="3399.99" ProductModelID="19" 
                  ProductModelName="Mountain 100" />
...

La requête suivante construit du code XML contenant des informations spécifiques à chaque produit. Ces informations comprennent les colonnes ProductID (correspondant à l'identificateur du produit), ProductName (le nom du produit), ProductPrice (son prix) et le cas échéant, ProductModelName (le nom de son modèle) pour les produits appartenant à un modèle donné ; dans le cas présenté ci-dessous, ProductModelID = 19. Les données XML sont ensuite affectées à la variable @x de type xml.

declare @x xml
SELECT @x = CatalogDescription.query('
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
       <Product 
           ProductID=       "{ sql:column("P.ProductID") }"
           ProductName=     "{ sql:column("P.Name") }"
           ProductPrice=    "{ sql:column("P.ListPrice") }"
           ProductModelID= "{ sql:column("PM.ProductModelID") }" >
           { if (not(empty(/pd:ProductDescription))) then
             attribute ProductModelName { /pd:ProductDescription[1]/@ProductModelName }
            else 
               ()
}
        </Product>
') 
FROM Production.ProductModel PM, Production.Product P
WHERE PM.ProductModelID = P.ProductModelID
And P.ProductModelID = 19
select @x