Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In una clausola FOR XML è possibile richiedere che la query restituisca uno schema inline oltre ai risultati della query. Per ottenere uno schema XDR, utilizzare la parola chiave XMLDATA nella clausola FOR XML. Per ottenere uno schema XSD, utilizzare invece la parola chiave XMLSCHEMA.
In questo argomento viene descritta la parola chiave XMLSCHEMA e viene illustrata la struttura dello schema XSD inline risultante. Di seguito sono riportate le limitazioni quando si richiedono schemi inline:
È possibile specificare la parola chiave XMLSCHEMA unicamente nelle modalità RAW e AUTO e non nella modalità EXPLICIT.
Se una query FOR XML nidificata specifica la direttiva TYPE, il risultato della query è di
xmltipo e questo risultato viene considerato come un'istanza di dati XML non tipizzati. Per altre informazioni, vedere Dati XML (SQL Server).
Se si specifica la parola chiave XMLSCHEMA in una query FOR XML, si otterrà sia uno schema che i dati XML, ovvero il risultato della query. Ogni elemento di livello principale dei dati fa riferimento allo schema precedente tramite una dichiarazione dello spazio dei nomi predefinito che, a sua volta, fa riferimento allo spazio dei nomi di destinazione dello schema inline.
Per esempio:
<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" />
Il risultato include lo schema XML e il risultato XML. L'elemento <ProductModel> di primo livello nel risultato fa riferimento allo schema usando la dichiarazione dello spazio dei nomi predefinita, xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" .
La parte del risultato relativa allo schema può contenere diversi documenti di schema che descrivono più namespace. Verranno restituiti almeno i due documenti di schema seguenti:
Un documento di schema per lo spazio dei nomi Sqltypes e per il quale vengono restituiti i tipi SQL di base.
Un altro documento di schema che descrive la forma del risultato della query FOR XML.
Inoltre, se nel risultato della query sono inclusi tipi di dati xml, vengono inclusi gli schemi associati a tali tipi di dati tipizzati xml.
Lo spazio dei nomi di destinazione del documento di schema che descrive la forma del risultato della query FOR XML contiene una parte fissa e una parte numerica che viene incrementata automaticamente. Di seguito è illustrato il formato di questo spazio dei nomi, dove n è un numero intero positivo. Ad esempio, nella query precedente urn:schemas-microsoft-com:sql:SqlRowSet1 rappresenta lo spazio dei nomi di destinazione.
urn:schemas-microsoft-com:sql:SqlRowSetn
La modifica degli spazi dei nomi di destinazione nel risultato tra un'esecuzione e l'altra potrebbe non essere auspicabile. Ad esempio, se si esegue una query sul codice XML risultante, la modifica nel namespace di destinazione richiederà di aggiornare la query. Se nella clausola FOR XML viene aggiunta l'opzione XMLSCHEMA, è possibile specificare facoltativamente uno spazio dei nomi di destinazione. Il codice XML risultante includerà lo spazio dei nomi specificato e rimarrà invariato, indipendentemente dal numero di esecuzioni della query.
SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID=1
FOR XML AUTO, XMLSCHEMA ('MyURI')
Elementi entità
Prima di fornire informazioni dettagliate sulla struttura dello schema XSD generato per il risultato della query, è necessario descrivere l'elemento entità.
Un elemento entità nel codice XML restituito dalla query FOR XML è un elemento generato da una tabella e non da una colonna. La query FOR XML seguente, ad esempio, restituisce informazioni relative ai contatti presenti nella tabella Person del database AdventureWorks2012 .
SELECT BusinessEntityID, FirstName
FROM Person.Person
WHERE BusinessEntityID = 1
FOR XML AUTO, ELEMENTS
Risultato:
<Person>
<BusinessEntityID>1</BusinessEntityID>
<FirstName>Ken</FirstName>
</Person>
In questo risultato, <Person> è l'elemento dell'entità. Nel risultato XML possono essere presenti più elementi entità, per ognuno dei quali è disponibile una dichiarazione globale nello schema XSD inline. Ad esempio, la query seguente recupera l'intestazione e i dettagli relativi a un ordine di vendita specifico.
SELECT SalesOrderHeader.SalesOrderID, ProductID, OrderQty
FROM Sales.SalesOrderHeader, Sales.SalesOrderDetail
WHERE SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
AND SalesOrderHeader.SalesOrderID=5001
FOR XML AUTO, ELEMENTS, XMLSCHEMA
Nella query è specificata la direttiva ELEMENTS e pertanto il codice XML risultante è incentrato sugli elementi. Nella query è inoltre specificata la direttiva XMLSCHEMA e pertanto viene restituito uno schema XSD inline. Risultato:
<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>
Nota quanto segue dalla query precedente:
Nel risultato <
SalesOrderHeader> e <SalesOrderDetail> sono elementi di entità. Per questo motivo, vengono dichiarati a livello globale nello schema. Ovvero, la dichiarazione viene visualizzata al livello superiore all'interno dell'elemento <Schema> .Gli <>
SalesOrderIDelementi ,ProductID<> e <OrderQty> non sono elementi di entità, perché eseguono il mapping alle colonne. I dati di colonna vengono restituiti come elementi nel codice XML e ciò è dovuto alla direttiva ELEMENTS. Questi vengono mappati a elementi locali del tipo complesso dell'elemento entità. Si noti che se la direttiva ELEMENTS non è specificata, iSalesOrderIDvalori eProductIDOrderQtyvengono mappati agli attributi locali del tipo complesso dell'elemento di entità corrispondente.
Conflitti tra nomi di attributo
La discussione seguente è basata sulle tabelle CustOrder e CustOrderDetail. Per testare gli esempi seguenti, creare le tabelle e inserire dati di esempio personalizzati:
CREATE TABLE CustOrder (OrderID int primary key, CustomerID int)
GO
CREATE TABLE CustOrderDetail (OrderID int, ProductID int, Qty int)
GO
Nelle query FOR XML a volte viene utilizzato lo stesso nome per indicare proprietà o attributi diversi. Ad esempio, la query in modalità RAW incentrata sugli attributi seguente crea due attributi con lo stesso nome, OrderID e viene quindi generato un errore.
SELECT CustOrder.OrderID,
CustOrderDetail.ProductID,
CustOrderDetail.OrderID
FROM dbo.CustOrder, dbo.CustOrderDetail
WHERE CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA
Tuttavia, poiché è accettabile avere due elementi con lo stesso nome, è possibile eliminare il problema aggiungendo la direttiva ELEMENTS:
SELECT CustOrder.OrderID,
CustOrderDetail.ProductID,
CustOrderDetail.OrderID
from dbo.CustOrder, dbo.CustOrderDetail
where CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA, ELEMENTS
Di seguito è riportato il risultato. Si noti che nello schema XSD inline, l'elemento OrderID è definito due volte. Per una dichiarazione minOccurs è impostato su 0 e corrisponde all'elemento OrderID della tabella CustOrderDetail e la seconda dichiarazione esegue il mapping alla colonna chiave primaria OrderID della tabella CustOrder , nella quale minOccurs è 1 per impostazione predefinita.
<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>
Conflitti tra nomi di elemento
Nelle query FOR XML è possibile utilizzare lo stesso nome per indicare due sottoelementi. Ad esempio, la query seguente recupera i valori ListPrice e DealerPrice dei prodotti, ma specifica lo stesso alias per le due colonne, ovvero Price. Nel set di righe risultante saranno pertanto presenti due colonne con lo stesso nome.
Caso 1: Entrambi i sottoelementi sono colonne non chiave dello stesso tipo e possono essere NULL
Nella query seguente, entrambi i sottoelementi sono colonne non chiave dello stesso tipo e possono essere 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
Di seguito è riportato il codice XML generato, nel quale è visualizzata solo una frazione dello schema XSD inline:
...
<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>
Nota quanto segue nello schema XSD:
ListPrice e DealerPrice sono dello stesso tipo,
moneyed entrambi possono essere NULL nella tabella. Pertanto, poiché potrebbero non essere restituiti nel codice XML risultante, è presente un <Price> solo elemento figlio nella dichiarazione di tipo complesso dell'elemento <row> con minOccurs=0 e maxOccurs=2.Nel risultato, poiché il
DealerPricevalore è NULL nella tabella, viene restituito soloListPricecome <Price> elemento . Se si aggiunge ilXSINILparametro alla direttiva ELEMENTS, si riceveranno entrambi gli elementi con ilxsi:nilvalore impostato su TRUE per l'elemento<Price> che corrisponde a DealerPrice. Riceverai anche due <Price> elementi figlio nella definizione di tipo complesso <row> nello schema XSD inline con l'attributonillableimpostato a TRUE per entrambi. Di seguito è riportato un frammento che rappresenta un risultato parziale:
...
<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>
Caso 2: Una colonna chiave e una colonna non chiave dello stesso tipo
La query seguente illustra una colonna chiave e una colonna non chiave dello stesso tipo.
CREATE TABLE T (Col1 int primary key, Col2 int, Col3 nvarchar(20))
go
INSERT INTO T VALUES (1, 1, 'test')
go
La query seguente alla tabella T specifica lo stesso alias per Col1 e Col2, dove Col1 è una chiave primaria e non può essere Null e Col2 può essere Null. In questo modo vengono generati due elementi figli dell'elemento <row>.
SELECT Col1 as Col, Col2 as Col, Col3
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA
Di seguito è riportato il risultato. nel quale è visualizzato solo un frammento dello schema XSD inline.
...
<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>
Si noti che nello schema XSD inline che l'elemento <Col> corrispondente a Col2 ha minOccurs impostato su 0.
Caso 3: Entrambi gli elementi sono di tipo diverso e le colonne corrispondenti possono essere NULL
La query seguente viene eseguita sulla tabella di esempio illustrata nel caso 2:
SELECT Col1, Col2 as Col, Col3 as Col
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA
Nella query seguente, a Col2 e Col3 sono assegnati gli stessi alias. In questo modo vengono generati due elementi di pari livello con lo stesso nome e che sono entrambi elementi figlio dell'elemento <raw> nel risultato. Entrambe le colonne sono di tipo diverso e possono essere NULL. Di seguito è riportato il risultato. nel quale è visualizzato solo uno schema XSD inline parziale.
...
<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>
Nota quanto segue nello schema XSD:
Poiché sia Col2 che Col3 possono essere NULL, la <
Col> dichiarazione di elemento specifica i minOccurs come 0 e maxOccurs come 2.Poiché entrambi gli <
Col> elementi sono di pari livello, è presente una dichiarazione di elemento nello schema. Inoltre, dato che entrambi gli elementi sono anche di tipo diverso, benché di tipo semplice, il tipo dell'elemento nello schema èxsd:anySimpleType. Nel risultato, ogni tipo di istanza è identificato dall'attributoxsi:type.Nel risultato, ogni istanza dell'elemento <>
Colfa riferimento al tipo di istanza usando l'attributoxsi:type.