Generera ett infogat XSD-schema
gäller för:SQL Server
Azure SQL Database
I en FOR XML-sats kan du begära att frågan returnerar ett infogat schema tillsammans med frågeresultaten. Om du vill ha ett XDR-schema använder du nyckelordet XMLDATA i FOR XML-satsen. Om du vill ha ett XSD-schema använder du nyckelordet XMLSCHEMA.
Den här artikeln beskriver nyckelordet XMLSCHEMA och förklarar strukturen för det resulterande infogade XSD-schemat. Följande är begränsningarna när du begär infogade scheman:
Du kan endast ange XMLSCHEMA i RAW- och AUTO-läge, inte i EXPLICIT läge.
Om en kapslad FOR XML-fråga anger TYPE-direktivet är frågeresultatet av xml- typ och det här resultatet behandlas som en instans av otypade XML-data. Mer information finns i XML-data (SQL Server).
När du anger XMLSCHEMA i en FOR XML-fråga får du både ett schema och XML-data, frågeresultatet. Varje element på den översta nivån i data refererar till det tidigare schemat med hjälp av en standarddeklaration för namnområdet som i sin tur refererar till målnamnområdet för det infogade schemat.
Till exempel:
<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="[AdventureWorks2022].[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" />
Resultatet innehåller XML-schema och XML-resultatet. Det <ProductModel>
elementet på den översta nivån i resultatet refererar till schemat med hjälp av standarddeklarationen för namnområdet, xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" .
Schemadelen av resultatet kan innehålla flera schemadokument som beskriver flera namnområden. Minst returneras följande två schemadokument:
Ett schemadokument för Sqltypes namnrymd och för vilket de grundläggande SQL-typerna returneras.
Ett annat schemadokument som beskriver formen på FOR XML-frågeresultatet.
Om några specificerade XML- datatyper ingår i frågeresultatet inkluderas även de scheman som är associerade med dessa specificerade XML- datatyper.
Målnamnområdet för schemadokumentet som beskriver formen på FOR XML-resultatet innehåller en fast del och en numerisk del som ökar automatiskt. Formatet för det här namnområdet visas i följande där n är ett positivt heltal. I den föregående frågan är till exempel urn:schemas-microsoft-com:sql:SqlRowSet1 målnamnområdet.
urn:schemas-microsoft-com:sql:SqlRowSetn
Det kanske inte är önskvärt att ändra målnamnrymderna i resultatet från en körning till en annan. Om du till exempel frågar den resulterande XML-koden kräver ändringen i målnamnområdet att du uppdaterar frågan. Du kan också ange ett målnamnområde när XMLSCHEMA-alternativet läggs till i FOR XML-satsen. Den resulterande XML-koden innehåller det namnområde som du angav och förblir detsamma, oavsett hur många gånger du kör frågan.
SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID=1
FOR XML AUTO, XMLSCHEMA ('MyURI');
Entitetselement
För att kunna diskutera information om XSD-schemastrukturen som genererats för frågeresultatet måste entitetselementet först beskrivas
Ett entitetselement i XML-data som returneras av FOR XML-frågan är ett element som genereras från en tabell och inte från en kolumn. Följande FOR XML-fråga returnerar till exempel kontaktinformation från tabellen Person
i AdventureWorks2022
-databasen.
SELECT BusinessEntityID, FirstName
FROM Person.Person
WHERE BusinessEntityID = 1
FOR XML AUTO, ELEMENTS;
Det här är resultatet:
<Person>
<BusinessEntityID>1</BusinessEntityID>
<FirstName>Ken</FirstName>
</Person>
I det här resultatet är <Person>
entitetselementet. Det kan finnas flera entitetselement i XML-resultatet och var och en av dessa har en global deklaration i det infogade XSD-schemat. Följande fråga hämtar till exempel försäljningsorderhuvudet och information om en viss order.
SELECT SalesOrderHeader.SalesOrderID, ProductID, OrderQty
FROM Sales.SalesOrderHeader, Sales.SalesOrderDetail
WHERE SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
AND SalesOrderHeader.SalesOrderID=5001
FOR XML AUTO, ELEMENTS, XMLSCHEMA;
Eftersom frågan anger ELEMENTS-direktivet är den resulterande XML-koden elementcentrerad. Frågan anger även XMLSCHEMA-direktivet. Därför returneras ett infogat XSD-schema. Det här är resultatet:
<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>
Observera följande från föregående fråga:
I resultatet är
<SalesOrderHeader>
och<SalesOrderDetail>
entitetselement. Därför deklareras de globalt i schemat. Deklarationen visas alltså på den översta nivån i elementet<Schema>
.<SalesOrderID>
,<ProductID>
och<OrderQty>
är inte entitetselement eftersom de mappas till kolumner. Kolumndata returneras som element i XML-koden på grund av ELEMENT-direktivet. Dessa mappas till lokala element av entitetselementets komplexa typ. Om elementdirektivet inte anges mappas värdenaSalesOrderID
,ProductID
ochOrderQty
till lokala attribut av motsvarande entitetselements komplexa typ.
Attributnamnskonflikter
Följande diskussion baseras på tabellerna CustOrder
och CustOrderDetail
. Om du vill testa följande exempel skapar du dessa tabeller och lägger till dina egna exempeldata:
CREATE TABLE CustOrder (OrderID int primary key, CustomerID int);
GO
CREATE TABLE CustOrderDetail (OrderID int, ProductID int, Qty int);
GO
I FOR XML används samma namn ibland för att ange olika egenskaper, attribut. Följande attributcentrerade RAW-lägesfråga genererar till exempel två attribut som har samma namn, OrderID. Detta genererar ett fel.
SELECT CustOrder.OrderID,
CustOrderDetail.ProductID,
CustOrderDetail.OrderID
FROM dbo.CustOrder, dbo.CustOrderDetail
WHERE CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA;
Men eftersom det är acceptabelt att ha två element som har samma namn kan du eliminera problemet genom att lägga till ELEMENTS-direktivet:
SELECT CustOrder.OrderID,
CustOrderDetail.ProductID,
CustOrderDetail.OrderID
from dbo.CustOrder, dbo.CustOrderDetail
where CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA, ELEMENTS;
Det här är resultatet. Observera att orderID-elementet definieras två gånger i det infogade XSD-schemat. En av deklarationerna har minOccurs inställt på 0, motsvarande OrderID i tabellen CustOrderDetail, och den andra mappas till primärnyckelkolumnen OrderID i tabellen CustOrder
där minOccurs är inställt till 1 som standard.
<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>
Elementnamnskonflikter
I FOR XML kan samma namn användas för att ange två underelement. Följande fråga hämtar till exempel ListPrice- och DealerPrice-värden för produkter, men frågan anger samma alias, Price, för dessa två kolumner. Därför har den resulterande raduppsättningen två kolumner med samma namn.
Fall 1: Båda underelementen är icke-nyckelkolumner av samma typ och kan vara NULL
I följande fråga är båda underelementen icke-nyckelkolumner av samma typ och kan vara 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;
Det här är motsvarande XML som genereras. Endast en bråkdel av den inbäddade XSD:en visas.
...
<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>
Observera följande i det infogade XSD-schemat:
Både ListPrice och DealerPrice är av samma typ,
money
och båda kan vara NULL i tabellen. Eftersom de kanske inte returneras i den resulterande XML-koden finns det därför bara ett<Price>
underordnat element i den komplexa typdeklarationen för det<row>
element som harminOccurs=0
ochmaxOccurs=2
.Eftersom värdet för
DealerPrice
är NULL i tabellen returneras endastListPrice
som ett<Price>
element. Om du lägger till parameternXSINIL
i ELEMENTS-direktivet får du båda elementen som har värdetxsi:nil
inställt på TRUE för det<Price>
element som motsvarar DealerPrice. Du får också två<Price>
underordnade element i den<row>
komplexa typdefinitionen i det infogade XSD-schemat med attributetnillable
inställt på TRUE för båda. Det här fragmentet är ett partiellt resultat:
...
<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>
Fall 2: En nyckel och en icke-nyckelkolumn av samma typ
Följande fråga illustrerar en nyckel och en icke-nyckelkolumn av samma typ.
CREATE TABLE T (Col1 int primary key, Col2 int, Col3 nvarchar(20));
GO
INSERT INTO T VALUES (1, 1, 'test');
GO
Följande fråga mot tabell T- anger samma alias för Col1 och Col2, där Col1 är en primärnyckel och inte kan vara null och Col2 kan vara null. Detta genererar två syskonelement som är underordnade elementet <row>
.
SELECT Col1 as Col, Col2 as Col, Col3
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA
Det här är resultatet. Endast ett fragment av det infogade XSD-schemat visas.
...
<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>
Observera i det infogade XSD-schemat att elementet <Col>
som motsvarar Col2 har minOccurs inställt på 0.
Fall 3: Båda elementen av olika typer och motsvarande kolumner kan vara NULL
Följande fråga anges mot exempeltabellen som visas i fall 2:
SELECT Col1, Col2 as Col, Col3 as Col
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA;
I följande fråga får Col2 och Col3 samma alias. Detta genererar två syskonelement som har samma namn och som båda är underordnade till <raw>
-elementet i resultatet. Båda dessa kolumner är av olika typer och båda kan vara NULL. Det här är resultatet. Endast delvis infogat XSD-schema visas.
...
<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>
Observera följande i det infogade XSD-schemat:
Eftersom både Col2 och Col3 kan vara NULL anger
<Col>
-elementdeklarationen minOccurs som 0 och maxOccurs som 2.Eftersom båda de
<Col>
elementen är syskon finns det en elementdeklaration i schemat. Eftersom båda elementen också är av olika typer, men båda är enkla typer, är typen av element i schematxsd:anySimpleType
. I resultatet identifieras varje instanstyp av attributetxsi:type
.I resultatet refererar varje instans av
<Col>
-elementet till dess instanstyp med hjälp av attributetxsi:type
.