Partager via


Générer un schéma XSD en ligne

Dans une clause FOR XML, vous pouvez demander à votre requête de retourner un schéma inline avec les résultats de la requête. Si vous souhaitez un schéma XDR, vous utilisez le mot clé XMLDATA dans la clause FOR XML. Si vous souhaitez un schéma XSD, vous utilisez le mot clé XMLSCHEMA.

Cette rubrique décrit le mot clé XMLSCHEMA et explique la structure du schéma XSD inline résultant. Voici les limitations lorsque vous demandez des schémas inline :

  • Vous pouvez spécifier XMLSCHEMA uniquement en mode RAW et AUTO, et non en mode EXPLICIT.

  • Si une requête FOR XML imbriquée spécifie la directive TYPE, le résultat de la requête est de xml type et ce résultat est traité comme une instance de données XML non typées. Pour plus d’informations, consultez Données XML (SQL Server).

Lorsque vous spécifiez XMLSCHEMA dans une requête FOR XML, vous recevez à la fois un schéma et des données XML, le résultat de la requête. Chaque élément de niveau supérieur des données fait référence au schéma précédent à l’aide d’une déclaration d’espace de noms par défaut qui, à son tour, fait référence à l’espace de noms cible du schéma inline.

Par exemple:

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">  
  <xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />  
  <xsd:element name="Production.ProductModel">  
    <xsd:complexType>  
      <xsd:attribute name="ProductModelID" type="sqltypes:int" use="required" />  
      <xsd:attribute name="Name" use="required">  
        <xsd:simpleType sqltypes:sqlTypeAlias="[AdventureWorks2012].[dbo].[Name]">  
          <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">  
            <xsd:maxLength value="50" />  
          </xsd:restriction>  
        </xsd:simpleType>  
      </xsd:attribute>  
    </xsd:complexType>  
  </xsd:element>  
</xsd:schema>  
<Production.ProductModel xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" ProductModelID="1" Name="Classic Vest" />  

Le résultat inclut le schéma XML et le résultat XML. L’élément <ProductModel> de niveau supérieur dans le résultat fait référence au schéma à l’aide de la déclaration d’espace de noms par défaut, xmlns="urn :schemas-microsoft-com :sql :SqlRowSet1 ».

La partie schéma du résultat peut contenir plusieurs documents de schéma qui décrivent plusieurs espaces de noms. Au minimum, les deux documents de schéma suivants sont retournés :

  • Un document de schéma pour l’espace de noms Sqltypes et pour lequel les types SQL de base sont retournés.

  • Un autre document de schéma qui décrit la forme du résultat de la requête FOR XML.

En outre, si des types de données typés xml sont inclus dans le résultat de la requête, les schémas associés à ces types de données typés xml sont inclus.

L’espace de noms cible du document de schéma qui décrit la forme du résultat FOR XML contient une partie fixe et une partie numérique incrémentée automatiquement. Le format de cet espace de noms est illustré dans la section suivante, où n est un entier positif. Par exemple, dans la requête précédente, urn :schemas-microsoft-com :sql :SqlRowSet1 est l’espace de noms cible.

urn:schemas-microsoft-com:sql:SqlRowSetn  

La modification des espaces de noms cibles dans le résultat qui s’est produit d’une exécution à une autre peut ne pas être souhaitable. Par exemple, si vous interrogez le code XML résultant, la modification de l’espace de noms cible nécessite que vous mettez à jour votre requête. Vous pouvez éventuellement spécifier un espace de noms cible lorsque l’option XMLSCHEMA est ajoutée dans la clause FOR XML. Le code XML obtenu inclut l’espace de noms que vous avez fourni et reste le même, quel que soit le nombre de fois que vous exécutez la requête.

SELECT ProductModelID, Name  
FROM   Production.ProductModel  
WHERE ProductModelID=1  
FOR XML AUTO, XMLSCHEMA ('MyURI')  

Éléments d’entité

Pour discuter des détails de la structure de schéma XSD générée pour le résultat de la requête, l’élément d’entité doit d’abord être décrit

Un élément d’entité dans les données XML retournées par la requête FOR XML est un élément généré à partir d’une table et non d’une colonne. Par exemple, la requête FOR XML suivante retourne les informations de contact de la Person table dans la AdventureWorks2012 base de données.

SELECT BusinessEntityID, FirstName  
FROM Person.Person  
WHERE BusinessEntityID = 1  
FOR XML AUTO, ELEMENTS  

Voici le résultat obtenu :

<Person>

<BusinessEntityID>1</BusinessEntityID>

<FirstName>Ken</FirstName>

</Person>

Dans ce résultat, <Person> est l’élément d’entité. Il peut y avoir plusieurs éléments d’entité dans le résultat XML et chacun d’eux a une déclaration globale dans le schéma XSD inline. Par exemple, la requête suivante récupère les informations d’en-tête de commande et de détail d’une commande spécifique.

SELECT  SalesOrderHeader.SalesOrderID, ProductID, OrderQty  
FROM    Sales.SalesOrderHeader, Sales.SalesOrderDetail  
WHERE   SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID  
AND     SalesOrderHeader.SalesOrderID=5001  
FOR XML AUTO, ELEMENTS, XMLSCHEMA  

Étant donné que la requête spécifie la directive ELEMENTS, le code XML résultant est centré sur les éléments. La requête spécifie également la directive XMLSCHEMA. Par conséquent, un schéma XSD inline est retourné. Voici le résultat obtenu :

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">

<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />

<xsd:element name="Sales.SalesOrderHeader">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="SalesOrderID" type="sqltypes:int" />

<xsd:element ref="schema:Sales.SalesOrderDetail" minOccurs="0" maxOccurs="unbounded" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

<xsd:element name="Sales.SalesOrderDetail">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="ProductID" type="sqltypes:int" />

<xsd:element name="OrderQty" type="sqltypes:smallint" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>

Notez les points suivants dans la requête précédente :

  • Dans le résultat, <SalesOrderHeader> et <SalesOrderDetail> sont des éléments d’entité. En raison de cela, ils sont déclarés globalement dans le schéma. Autrement dit, la déclaration apparaît au niveau supérieur à l’intérieur de l’élément <Schema> .

  • Les <SalesOrderID>, <ProductID> et <OrderQty> ne sont pas des éléments d’entité, car ils sont mappés aux colonnes. Les données de colonne sont retournées en tant qu’éléments dans le code XML, en raison de la directive ELEMENTS. Ces éléments correspondent aux éléments locaux du type complexe de l’élément d’entité. Notez que si la directive ELEMENTS n’est pas spécifiée, les valeurs SalesOrderID, ProductID et OrderQty sont mappées aux attributs locaux du type complexe de l’élément d’entité correspondant.

Conflits de noms d’attributs

La discussion suivante est basée sur les tableaux CustOrder et CustOrderDetail. Pour tester les exemples suivants, créez ces tables et ajoutez vos propres exemples de données :

CREATE TABLE CustOrder (OrderID int primary key, CustomerID int)  
GO  
CREATE TABLE CustOrderDetail (OrderID int, ProductID int, Qty int)  
GO  

Dans FOR XML, le même nom est parfois utilisé pour indiquer différentes propriétés, attributs. Par exemple, la requête en mode RAW centré sur les attributs suivant génère deux attributs portant le même nom, OrderID. Cela génère une erreur.

SELECT CustOrder.OrderID,   
       CustOrderDetail.ProductID,   
       CustOrderDetail.OrderID  
FROM   dbo.CustOrder, dbo.CustOrderDetail  
WHERE  CustOrder.OrderID = CustOrderDetail.OrderID  
FOR XML RAW, XMLSCHEMA  

Toutefois, étant donné qu’il est acceptable d’avoir deux éléments portant le même nom, vous pouvez éliminer le problème en ajoutant la directive ELEMENTS :

SELECT CustOrder.OrderID,  
       CustOrderDetail.ProductID,   
       CustOrderDetail.OrderID  
from   dbo.CustOrder, dbo.CustOrderDetail  
where  CustOrder.OrderID = CustOrderDetail.OrderID  
FOR XML RAW, XMLSCHEMA, ELEMENTS  

Voici le résultat. Notez que dans le schéma XSD inline, l’élément OrderID est défini deux fois. L'une des déclarations a minOccurs défini à 0, correspondant à l'ID de commande à partir de la table CustOrderDetail, et la deuxième est mappée à la colonne clé primaire de l'ID de commande de la table CustOrder, où minOccurs est 1 par défaut.

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">

<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="https://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />

<xsd:element name="row">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="OrderID" type="sqltypes:int" />

<xsd:element name="ProductID" type="sqltypes:int" minOccurs="0" />

<xsd:element name="OrderID" type="sqltypes:int" minOccurs="0" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>

Conflits de noms d’élément

Dans FOR XML, le même nom peut être utilisé pour indiquer deux sous-éléments. Par exemple, la requête suivante récupère les valeurs ListPrice et DealerPrice des produits, mais la requête spécifie le même alias, Price, pour ces deux colonnes. Par conséquent, l’ensemble de lignes résultant aura deux colonnes portant le même nom.

Cas 1 : les deux sous-éléments sont des colonnes non clés du même type et peuvent être NULL

Dans la requête suivante, les deux sous-éléments sont des colonnes non clés du même type et peuvent être NULL.

DROP TABLE T  
go  
CREATE TABLE T (ProductID int primary key, ListPrice money, DealerPrice money)  
go  
INSERT INTO T values (1, 1.25, null)  
go  
  
SELECT ProductID, ListPrice Price, DealerPrice Price  
FROM   T  
for    XML RAW, ELEMENTS, XMLSCHEMA  

Il s’agit du code XML correspondant généré. Seule une fraction du XSD inline est affichée :

...

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">

<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />

<xsd:element name="row">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="ProductID" type="sqltypes:int" />

<xsd:element name="Price" type="sqltypes:money" minOccurs="0" maxOccurs="2" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>

<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">

<ProductID>1</ProductID>

<Price>1.2500</Price>

</row>

Notez les éléments suivants dans le schéma XSD inline :

  • ListPrice et DealerPrice sont du même type, moneyet les deux peuvent être NULL dans la table. Par conséquent, étant donné qu’ils ne peuvent pas être retournés dans le code XML résultant, il n’existe qu’un seul élément enfant dans la déclaration de type complexe de l’élémentrow><qui a minOccurs=0 et maxOccurs=2.<Price>

  • Dans le résultat, étant donné que la valeur DealerPrice est NULL dans la table, seul ListPrice est retourné en tant qu’élément <Price>. Si vous ajoutez le XSINIL paramètre à la directive ELEMENTS, vous recevrez les deux éléments dont la xsi:nil valeur est définie sur TRUE pour l’élément<Price> qui correspond à DealerPrice. Vous recevrez également deux <Price> éléments enfants dans la <row> définition de type complexe dans le schéma XSD inline avec l’attribut nillable défini sur TRUE pour les deux. Ce fragment est un résultat partiel :

...

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">

<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />

<xsd:element name="row">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="ProductID" type="sqltypes:int" nillable="1" />

<xsd:element name="Price" type="sqltypes:money" nillable="1" />

<xsd:element name="Price" type="sqltypes:money" nillable="1" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>

<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<ProductID>1</ProductID>

<Price>1.2500</Price>

<Price xsi:nil="true" />

</row>

Cas 2 : Une clé et une colonne non clé du même type

La requête suivante illustre une clé et une colonne non clé du même type.

CREATE TABLE T (Col1 int primary key, Col2 int, Col3 nvarchar(20))  
go  
INSERT INTO T VALUES (1, 1, 'test')  
go   

La requête suivante sur la table T spécifie le même alias pour Col1 et Col2, où Col1 est une clé primaire et ne peut pas être null, et Col2 peut être null. Cela génère deux éléments frères qui sont des enfants de l’élément <row> .

SELECT Col1 as Col, Col2 as Col, Col3  
FROM T  
FOR XML RAW, ELEMENTS, XMLSCHEMA  

Voici le résultat. Seul un fragment du schéma XSD inline est affiché.

...

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">

<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />

<xsd:element name="row">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="Col" type="sqltypes:int" />

<xsd:element name="Col" type="sqltypes:int" minOccurs="0" />

<xsd:element name="Col3" minOccurs="0">

<xsd:simpleType>

<xsd:restriction base="sqltypes:nvarchar"

sqltypes:localeId="1033"

sqltypes:sqlCompareOptions="IgnoreCase

IgnoreKanaType IgnoreWidth"

sqltypes:sqlSortId="52">

<xsd:maxLength value="20" />

</xsd:restriction>

</xsd:simpleType>

</xsd:element>

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>

<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">

<Col>1</Col>

<Col>1</Col>

<Col3>test</Col3>

</row>

Notez dans le schéma XSD inline que l’élément <Col> correspondant au Col2 a minOccurs défini sur 0.

Cas 3 : les deux éléments de différents types et colonnes correspondantes peuvent être NULL

La requête suivante est spécifiée par rapport à l’exemple de table indiqué dans le cas 2 :

SELECT Col1, Col2 as Col, Col3 as Col  
FROM T  
FOR XML RAW, ELEMENTS, XMLSCHEMA  

Dans la requête suivante, Col2 et Col3 reçoivent les mêmes alias. Cela génère deux éléments frères qui ont le même nom et qui sont les deux enfants de l’élément <raw> dans le résultat. Ces deux colonnes sont de types différents et peuvent être NULL. Voici le résultat. Seul un schéma XSD inline partiel est affiché.

...

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="https://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">

<xsd:import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes" />

<xsd:simpleType name="Col1">

<xsd:restriction base="sqltypes:int" />

</xsd:simpleType>

<xsd:simpleType name="Col2">

<xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033"

sqltypes:sqlCompareOptions="IgnoreCase

IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">

<xsd:maxLength value="20" />

</xsd:restriction>

</xsd:simpleType>

<xsd:element name="row">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="Col1" type="sqltypes:int" />

<xsd:element name="Col" minOccurs="0" maxOccurs="2" type="xsd:anySimpleType" />

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>

<row xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">

<Col1>1</Col1>

<Col xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:type="Col1">1</Col>

<Col xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:type="Col2">test</Col>

</row>

Notez les éléments suivants dans le schéma XSD inline :

  • Étant donné que Col2 et Col3 peuvent être NULL, la <Col> déclaration d’élément spécifie le minOccurs comme 0 et maxOccurs comme 2.

  • Étant donné que les <Col> deux éléments sont frères, il existe une déclaration d’élément dans le schéma. En outre, étant donné que les deux éléments sont également de types différents, bien que les deux soient des types simples, le type de l’élément dans le schéma est xsd:anySimpleType. Dans le résultat, chaque type d’instance est identifié par l’attribut xsi:type .

  • Dans le résultat, chaque instance de l’élément <>Colfait référence à son type d’instance à l’aide de l’attributxsi:type.