Bagikan melalui


Membuat skema XSD sebaris

Berlaku untuk: SQL ServerAzure SQL Database

Dalam klausul FOR XML, Anda bisa meminta kueri mengembalikan skema sebaris bersama dengan hasil kueri. Jika Anda menginginkan skema XDR, Anda menggunakan kata kunci XMLDATA dalam klausa FOR XML. Jika Anda menginginkan skema XSD, Anda menggunakan kata kunci XMLSCHEMA.

Artikel ini menjelaskan kata kunci XMLSCHEMA dan menjelaskan struktur skema XSD sebaris yang dihasilkan. Berikut ini adalah batasan saat Anda meminta skema sebaris:

  • Anda hanya dapat menentukan XMLSCHEMA dalam mode RAW dan AUTO, bukan dalam mode EKSPLISIT.

  • Jika kueri XML BERlapis menentukan direktif TYPE, hasil kueri adalah jenis xml , dan hasil ini diperlakukan sebagai instans data XML yang tidak dititik. Untuk informasi selengkapnya, lihat Data XML (SQL Server).

Saat Anda menentukan XMLSCHEMA dalam kueri FOR XML, Anda menerima data skema dan XML, hasil kueri. Setiap elemen tingkat atas data mengacu pada skema sebelumnya dengan menggunakan deklarasi namespace default yang, pada gilirannya, mengacu pada namespace target skema sebaris.

Contohnya:

<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" />

Hasilnya mencakup skema XML dan hasil XML. Elemen <ProductModel> tingkat atas dalam hasil mengacu pada skema dengan menggunakan deklarasi namespace default, xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" .

Bagian skema dari hasil mungkin berisi beberapa dokumen skema yang menjelaskan beberapa namespace. Minimal, dua dokumen skema berikut dikembalikan:

  • Satu dokumen skema untuk namespace layanan Sqltypes , dan yang jenis SQL dasarnya dikembalikan.

  • Dokumen skema lain yang menjelaskan bentuk hasil kueri FOR XML.

Selain itu, jika ada jenis data xml yang diketik disertakan dalam hasil kueri, skema yang terkait dengan jenis data xml yang diketik disertakan.

Namespace layanan target dari dokumen skema yang menjelaskan bentuk hasil FOR XML berisi bagian tetap dan bagian numerik yang bertahakan secara otomatis. Format namespace ini diperlihatkan dalam berikut ini di mana n adalah bilangan bulat positif. Misalnya, dalam kueri sebelumnya, urn:schemas-microsoft-com:sql:SqlRowSet1 adalah namespace target.

urn:schemas-microsoft-com:sql:SqlRowSetn

Perubahan namespace target dalam hasil yang terjadi dari satu eksekusi ke eksekusi lainnya mungkin tidak diinginkan. Misalnya, jika Anda mengkueri XML yang dihasilkan, perubahan dalam namespace layanan target akan mengharuskan Anda memperbarui kueri Anda. Anda dapat secara opsional menentukan namespace layanan target saat opsi XMLSCHEMA ditambahkan dalam klausa FOR XML. XML yang dihasilkan akan menyertakan namespace yang Anda berikan dan akan tetap sama, terlepas dari berapa kali Anda menjalankan kueri.

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

Elemen entitas

Untuk membahas detail struktur skema XSD yang dihasilkan untuk hasil kueri, elemen entitas harus terlebih dahulu dijelaskan

Elemen entitas dalam data XML yang dikembalikan oleh kueri FOR XML adalah elemen yang dihasilkan dari tabel dan bukan dari kolom. Misalnya, kueri FOR XML berikut mengembalikan informasi kontak dari Person tabel dalam AdventureWorks2022 database.

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

Ini adalah hasilnya:

<Person>
  <BusinessEntityID>1</BusinessEntityID>
  <FirstName>Ken</FirstName>
</Person>

Dalam hasil ini, <Person> adalah elemen entitas. Mungkin ada beberapa elemen entitas dalam hasil XML dan masing-masing memiliki deklarasi global dalam skema XSD sebaris. Misalnya, kueri berikut mengambil header pesanan penjualan dan informasi detail untuk pesanan tertentu.

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

Karena kueri menentukan arahan ELEMENTS, XML yang dihasilkan berpusat pada elemen. Kueri juga menentukan arahan XMLSCHEMA. Oleh karena itu, skema XSD sebaris dikembalikan. Ini adalah hasilnya:

<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>

Perhatikan hal berikut ini dari kueri sebelumnya:

  • Dalam hasilnya, <SalesOrderHeader> dan <SalesOrderDetail> merupakan elemen entitas. Karena itu, mereka secara global dinyatakan dalam skema. Artinya, deklarasi muncul di tingkat atas di dalam <Schema> elemen .

  • <SalesOrderID>, <ProductID>, dan <OrderQty> bukan elemen entitas, karena dipetakan ke kolom. Data kolom dikembalikan sebagai elemen dalam XML, karena arahan ELEMENTS. Ini dipetakan ke elemen lokal dari jenis kompleks elemen entitas. Jika arahan ELEMENTS tidak ditentukan, SalesOrderIDnilai , ProductID dan OrderQty dipetakan ke atribut lokal dari jenis kompleks elemen entitas yang sesuai.

Bentrokan nama atribut

Diskusi berikut didasarkan pada CustOrder tabel dan CustOrderDetail . Untuk menguji sampel berikut, buat tabel ini dan tambahkan data sampel Anda sendiri:

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

Di FOR XML, nama yang sama terkadang digunakan untuk menunjukkan properti, atribut yang berbeda. Misalnya, kueri mode RAW yang ber sentris atribut berikut menghasilkan dua atribut yang memiliki nama yang sama, OrderID. Ini menghasilkan kesalahan.

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

Namun, karena dapat diterima untuk memiliki dua elemen yang memiliki nama yang sama, Anda dapat menghilangkan masalah dengan menambahkan arahan ELEMENTS:

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

Ini adalah hasilnya. Perhatikan dalam skema XSD sebaris, elemen OrderID ditentukan dua kali. Salah satu deklarasi memiliki minOccurs yang diatur ke 0, sesuai dengan OrderID dari tabel CustOrderDetail, dan yang kedua memetakan ke kolom kunci utama OrderID dari CustOrder tabel di mana minOccurs adalah 1 secara default.

<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>

Bentrokan nama elemen

Di FOR XML, nama yang sama dapat digunakan untuk menunjukkan dua subelemen. Misalnya, kueri berikut mengambil nilai ListPrice dan DealerPrice produk, tetapi kueri menentukan alias yang sama, Harga, untuk dua kolom ini. Oleh karena itu, himpunan baris yang dihasilkan akan memiliki dua kolom dengan nama yang sama.

Kasus 1: Kedua subelemen adalah kolom non-kunci dengan jenis yang sama dan dapat berupa NULL

Dalam kueri berikut, kedua sublemen adalah kolom non-kunci dengan jenis yang sama dan bisa 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;

Ini adalah XML terkait yang dihasilkan. Hanya sebagian kecil dari XSD sebaris yang ditampilkan:

...
<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>

Perhatikan hal berikut dalam skema XSD sebaris:

  • ListPrice dan DealerPrice memiliki jenis yang sama, money, dan keduanya dapat berupa NULL dalam tabel. Oleh karena itu, karena mungkin tidak dikembalikan dalam XML yang dihasilkan, hanya ada satu <Price> elemen turunan dalam deklarasi <row> jenis kompleks elemen yang memiliki minOccurs=0 dan maxOccurs=2.

  • Dalam hasilnya, karena DealerPrice nilainya adalah NULL dalam tabel, hanya ListPrice dikembalikan sebagai <Price> elemen. Jika Anda menambahkan XSINIL parameter ke arahan ELEMENTS, Anda akan menerima kedua elemen yang memiliki xsi:nil nilai yang diatur ke TRUE untuk<Price> elemen yang sesuai dengan DealerPrice. Anda juga akan menerima dua <Price> elemen anak dalam <row> definisi jenis kompleks dalam skema XSD sebaris dengan atribut yang nillable diatur ke TRUE untuk keduanya. Fragmen ini adalah hasil parsial:

...
<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>

Kasus 2: Satu kunci dan satu kolom non-kunci dengan jenis yang sama

Kueri berikut mengilustrasikan satu kunci dan satu kolom non-kunci dengan jenis yang sama.

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

Kueri berikut terhadap tabel T menentukan alias yang sama untuk Col1 dan Col2, di mana Col1 adalah kunci utama dan tidak boleh null, dan Col2 bisa null. Ini menghasilkan dua elemen saudara yang merupakan anak dari <row> elemen .

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

Ini adalah hasilnya. Hanya fragmen skema XSD sebaris yang ditampilkan.

...
<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>

Perhatikan dalam skema XSD sebaris bahwa elemen yang <Col> sesuai dengan Col2 memiliki minOccurs yang diatur ke 0.

Kasus 3: Kedua elemen dari berbagai jenis dan kolom terkait dapat berupa NULL

Kueri berikut ditentukan terhadap tabel sampel yang diperlihatkan dalam kasus 2:

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

Dalam kueri berikut, Col2 dan Col3 diberi alias yang sama. Ini menghasilkan dua elemen saudara yang memiliki nama yang sama dan keduanya merupakan anak dari <raw> elemen dalam hasilnya. Kedua kolom ini memiliki tipe yang berbeda dan keduanya dapat berupa NULL. Ini adalah hasilnya. Hanya skema XSD sebaris parsial yang ditampilkan.

...
<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>

Perhatikan hal berikut dalam skema XSD sebaris:

  • Karena Col2 dan Col3 dapat berupa NULL, <Col> deklarasi elemen menentukan minOccurs sebagai 0 dan maxOccurs sebagai 2.

  • Karena kedua elemen tersebut <Col> adalah saudara kandung, ada satu deklarasi elemen dalam skema. Selain itu, karena kedua elemen juga memiliki jenis yang berbeda, meskipun keduanya adalah jenis sederhana, jenis elemen dalam skema adalah xsd:anySimpleType. Dalam hasilnya, setiap jenis instans diidentifikasi oleh xsi:type atribut .

  • Dalam hasilnya, setiap instans <Col> elemen mengacu pada jenis instansnya dengan menggunakan xsi:type atribut .