Gerar um esquema XSD em linha
Aplica-se a:SQL Server
Banco de Dados SQL do Azure
Em uma cláusula FOR XML, você pode solicitar que sua consulta retorne um esquema embutido juntamente com os resultados da consulta. Se desejar um esquema XDR, use a palavra-chave XMLDATA na cláusula FOR XML. Se você quiser um esquema XSD, use a palavra-chave XMLSCHEMA.
Este artigo descreve a palavra-chave XMLSCHEMA e explica a estrutura do esquema XSD embutido resultante. A seguir estão as limitações quando estiver a solicitar esquemas inline:
Você pode especificar XMLSCHEMA somente nos modos RAW e AUTO, não no modo EXPLICIT.
Se uma consulta FOR XML aninhada especificar a diretiva TYPE, o resultado da consulta será de tipo xml e esse resultado será tratado como uma instância de dados XML não tipados. Para obter mais informações, consulte Dados XML (SQL Server).
Ao especificar XMLSCHEMA em uma consulta FOR XML, você recebe um esquema e dados XML, o resultado da consulta. Cada elemento de nível superior dos dados refere-se ao esquema anterior usando uma declaração de namespace padrão que, por sua vez, se refere ao namespace de destino do esquema embutido.
Por exemplo:
<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" />
O resultado inclui o esquema XML e o resultado XML. O <ProductModel>
elemento de nível superior no resultado refere-se ao esquema usando a declaração de namespace padrão, xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" .
A parte do esquema do resultado pode conter vários documentos de esquema que descrevem vários namespaces. No mínimo, os dois documentos de esquema a seguir são retornados:
Um documento de esquema para o Sqltypes namespace e para o qual os tipos SQL base estão sendo retornados.
Outro documento de esquema que descreve a forma do resultado da consulta FOR XML.
Além disso, se qualquer tipo de dados xml digitado for incluído no resultado da consulta, os esquemas associados a esses tipos de dados xml digitados serão incluídos.
O namespace de destino do documento de esquema que descreve a forma do resultado FOR XML contém uma parte fixa e uma parte numérica que aumenta automaticamente. O formato desse namespace é mostrado a seguir, onde n é um inteiro positivo. Por exemplo, na consulta anterior, urn:schemas-microsoft-com:sql:SqlRowSet1 é o namespace de destino.
urn:schemas-microsoft-com:sql:SqlRowSetn
A alteração nos namespaces de destino no resultado que ocorreu de uma execução para outra pode não ser desejável. Por exemplo, se você consultar o XML resultante, a alteração no namespace de destino exigirá que você atualize sua consulta. Opcionalmente, você pode especificar um namespace de destino quando a opção XMLSCHEMA for adicionada na cláusula FOR XML. O XML resultante incluirá o namespace fornecido e permanecerá o mesmo, independentemente de quantas vezes você executar a consulta.
SELECT ProductModelID, Name
FROM Production.ProductModel
WHERE ProductModelID=1
FOR XML AUTO, XMLSCHEMA ('MyURI');
Elementos da entidade
Para discutir os detalhes da estrutura do esquema XSD gerada para o resultado da consulta, o elemento de entidade deve primeiro ser descrito
Um elemento de entidade nos dados XML retornados pela consulta FOR XML é um elemento gerado a partir de uma tabela e não de uma coluna. Por exemplo, a seguinte consulta FOR XML retorna informações de contato da tabela Person
no banco de dados AdventureWorks2022
.
SELECT BusinessEntityID, FirstName
FROM Person.Person
WHERE BusinessEntityID = 1
FOR XML AUTO, ELEMENTS;
Este é o resultado:
<Person>
<BusinessEntityID>1</BusinessEntityID>
<FirstName>Ken</FirstName>
</Person>
Neste resultado, <Person>
é o elemento da entidade. Pode haver vários elementos de entidade no resultado XML e cada um deles tem uma declaração global no esquema XSD embutido. Por exemplo, a consulta a seguir recupera o cabeçalho da ordem de venda e informações detalhadas de uma ordem específica.
SELECT SalesOrderHeader.SalesOrderID, ProductID, OrderQty
FROM Sales.SalesOrderHeader, Sales.SalesOrderDetail
WHERE SalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
AND SalesOrderHeader.SalesOrderID=5001
FOR XML AUTO, ELEMENTS, XMLSCHEMA;
Como a consulta especifica a diretiva ELEMENTS, o XML resultante é centrado em elementos. A consulta também especifica a diretiva XMLSCHEMA. Portanto, um esquema XSD integrado é retornado. Este é o resultado:
<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>
Observe o seguinte da consulta anterior:
No resultado,
<SalesOrderHeader>
e<SalesOrderDetail>
são elementos de entidade. Por isso, eles são declarados globalmente no esquema. Ou seja, a declaração aparece no nível superior dentro do elemento<Schema>
.Os
<SalesOrderID>
,<ProductID>
e<OrderQty>
não são elementos de entidade, pois correspondem a colunas. Os dados da coluna são retornados como elementos no XML, devido à diretiva ELEMENTS. Eles são mapeados para elementos locais do tipo complexo do elemento da entidade. Se a diretiva ELEMENTS não for especificada, os valoresSalesOrderID
,ProductID
eOrderQty
serão mapeados para atributos locais do tipo complexo do elemento de entidade correspondente.
Conflitos de nome de atributo
A discussão que se segue baseia-se nos quadros CustOrder
e CustOrderDetail
. Para testar os seguintes exemplos, crie estas tabelas e adicione seus próprios dados de exemplo:
CREATE TABLE CustOrder (OrderID int primary key, CustomerID int);
GO
CREATE TABLE CustOrderDetail (OrderID int, ProductID int, Qty int);
GO
Em FOR XML, o mesmo nome às vezes é usado para indicar diferentes propriedades, atributos. Por exemplo, a seguinte consulta de modo RAW centrada em atributos gera dois atributos que têm o mesmo nome, OrderID. Isso gera um erro.
SELECT CustOrder.OrderID,
CustOrderDetail.ProductID,
CustOrderDetail.OrderID
FROM dbo.CustOrder, dbo.CustOrderDetail
WHERE CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA;
No entanto, como é aceitável ter dois elementos com o mesmo nome, você pode eliminar o problema adicionando a diretiva ELEMENTS:
SELECT CustOrder.OrderID,
CustOrderDetail.ProductID,
CustOrderDetail.OrderID
from dbo.CustOrder, dbo.CustOrderDetail
where CustOrder.OrderID = CustOrderDetail.OrderID
FOR XML RAW, XMLSCHEMA, ELEMENTS;
Este é o resultado. Observe que no esquema XSD embutido, o elemento OrderID é definido duas vezes. Uma das declarações tem minOccurs definido como 0, correspondendo ao OrderID da tabela CustOrderDetail, e a segunda mapeia para a coluna de chave primária OrderID da tabela CustOrder
onde minOccurs é 1 por padrão.
<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>
Conflitos de nome de elemento
Em FOR XML, o mesmo nome pode ser usado para indicar dois subelementos. Por exemplo, a consulta a seguir recupera os valores ListPrice e DealerPrice dos produtos, mas a consulta especifica o mesmo alias, Price, para essas duas colunas. Portanto, o conjunto de linhas resultante terá duas colunas com o mesmo nome.
Caso 1: Ambos os subelementos são colunas não-chave do mesmo tipo e podem ser NULL
Na consulta a seguir, ambos os subelementos são colunas não-chave do mesmo tipo e podem ser 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;
Este é o XML correspondente gerado. Apenas uma fração do XSD embutido é mostrada:
...
<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>
Observe o seguinte no esquema XSD embutido:
Tanto o ListPrice quanto o DealerPrice são do mesmo tipo,
money
, e ambos podem ser NULL na tabela. Portanto, como eles não podem ser retornados no XML resultante, há apenas um elemento filho<Price>
na declaração de tipo complexo do elemento<row>
que temminOccurs=0
emaxOccurs=2
.No resultado, como o valor
DealerPrice
é NULL na tabela, somenteListPrice
é retornado como um elemento<Price>
. Se você adicionar o parâmetroXSINIL
à diretiva ELEMENTS, receberá ambos os elementos que têm o valorxsi:nil
definido como TRUE para o elemento<Price>
que corresponde a DealerPrice. Você também receberá dois elementos filho<Price>
na definição de tipo complexo<row>
no esquema XSD embutido com o atributonillable
definido como TRUE para ambos. Este fragmento é um resultado parcial:
...
<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: Uma coluna chave e uma coluna não-chave do mesmo tipo
A consulta a seguir ilustra uma coluna chave e uma coluna não-chave do mesmo tipo.
CREATE TABLE T (Col1 int primary key, Col2 int, Col3 nvarchar(20));
GO
INSERT INTO T VALUES (1, 1, 'test');
GO
A consulta a seguir na tabela T especifica o mesmo alias para Col1 e Col2, onde Col1 é uma chave primária e não pode ser nula e Col2 pode ser null. Isso gera dois elementos irmãos que são filhos do elemento <row>
.
SELECT Col1 as Col, Col2 as Col, Col3
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA
Este é o resultado. Apenas um fragmento do esquema XSD embutido é mostrado.
...
<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>
Observe no esquema XSD embutido que o elemento <Col>
correspondente ao Col2 tem minOccurs definido como 0.
Caso 3: Ambos os elementos de tipos diferentes e colunas correspondentes podem ser NULL
A consulta a seguir é especificada em relação à tabela de exemplo mostrada no caso 2:
SELECT Col1, Col2 as Col, Col3 as Col
FROM T
FOR XML RAW, ELEMENTS, XMLSCHEMA;
Na consulta a seguir, Col2 e Col3 recebem os mesmos aliases. Isso gera dois elementos irmãos que têm o mesmo nome e que são ambos filhos do elemento <raw>
no resultado. Ambas as colunas são de tipos diferentes e ambas podem ser NULL. Este é o resultado. Apenas o esquema XSD parcial em linha é exibido.
...
<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>
Observe o seguinte no esquema XSD embutido:
Como Col2 e Col3 podem ser NULL, a declaração do elemento
<Col>
especifica minOccurs como 0 e maxOccurs como 2.Como ambos os elementos
<Col>
são irmãos, há uma declaração de elemento no esquema. Além disso, como ambos os elementos também são de tipos diferentes, embora ambos sejam tipos simples, o tipo do elemento no esquema éxsd:anySimpleType
. No resultado, cada tipo de instância é identificado pelo atributoxsi:type
.No resultado, cada instância do elemento
<Col>
refere-se ao seu tipo de instância usando o atributoxsi:type
.