Указание связей при помощи sql:relationship (SQLXML 4.0)
Элементы в XML-документе могут участвовать в связях. Элементы могут иметь иерархическую вложенность, и между ними могут быть заданы связи ID, IDREF или IDREFS.
Например, в XSD-схеме элемент <Customer> содержит дочерние элементы <Order>. Когда схема сопоставляется базе данных AdventureWorks, элемент <Customer> сопоставляется таблице Sales.Customer, а элемент <Order> сопоставляется таблице Sales.SalesOrderHeader. Базовые таблицы Sales.Customer и Sales.SalesOrderHeader связаны, так как заказчики размещают заказы. CustomerID в таблице Sales.SalesOrderHeader представляет собой внешний ключ, ссылающийся на первичный ключ CustomerID в таблице Sales.Customer. Можно установить эти связи между соответствующими элементами схемы с использованием заметки sql:relationship.
В аннотированной XDR-схеме заметка sql:relationship используется для иерархического вложения элементов схемы на основе связях между внешним ключом и первичным ключом среди базовых таблиц, которым сопоставляется элемент. Назначая заметку sql:relationship, необходимо указать:
Родительскую таблицу (Sales.Customer) и дочернюю таблицу (Sales.SalesOrderHeader).
Столбец или столбцы, составляющие связь между родительской и дочерней таблицами. Например, столбец CustomerID, который присутствует как в родительской, так и дочерней таблицах.
Эти сведения используются для подготовки правильной иерархии.
Чтобы предоставить имена таблиц и необходимые сведения о соединении, следующие атрибуты указываются на заметке sql:relationship. Эти атрибуты действительны только с элементом <ql:relationship>:
Name
Указывает уникальное имя связи.Родительский
Задает родительское взаимоотношение (таблицу). Это необязательный атрибут; если атрибут не указан, имя родительской таблицы извлекается из сведений в дочерней иерархии в документе. Если схема указывает две иерархии типа «родитель-потомок», которые используют ту же заметку <sql:relationship>, но другие родительские элементы, в <sql:relationship> не задается родительский атрибут. Эти сведения извлекаются из иерархии в схеме .parent-key
Указывает родительский ключ для родителя. Если родительский ключ составлен из нескольких столбцов, между указанными значениями вводятся пробелы. Между значениями, заданными для ключа, состоящего из нескольких столбцов, и соответствующего дочернего ключа, существует позиционное сопоставление.Потомок
Задает дочернее взаимоотношение (таблицу).child-key
Задает дочерний ключ в потомке, который ссылается на атрибут parent-key в родителе. Если дочерний ключ составлен из нескольких атрибутов (столбцов), между значениями атрибута child-key вводятся пробелы. Между значениями, заданными для ключа, состоящего из нескольких столбцов, и соответствующего родительского ключа, существует позиционное сопоставление.Inverse
Этот атрибут, указываемый на элементе <sql:relationship>, используется диаграммами обновления. Дополнительные сведения см. в разделе Задание значения атрибута sql:inverse для sql:relationship.
Заметка sql:key-fields должна быть указана в элементе, содержащем дочерний элемент, который имеет <sql:relationship>, определенный между элементом и потомком, и который не предоставляет первичного ключа таблицы, указанной в родительском элементе. Даже если схема не задает <sql:relationship>, необходимо указать заметку sql:key-fields, чтобы сформировать правильную иерархию Дополнительные сведения см. в разделе Определение ключевых столбцов с помощью sql:key-fields.
Чтобы правильно организовать вложенность в результатах, рекомендуется во всех схемах задавать заметку sql:key-fields.
Примеры
Чтобы создать рабочие образцы на основе следующих примеров, необходимо выполнить определенные требования. Дополнительные сведения см. в разделе Требования к запуску примеров SQLXML.
А. Задание заметки sql:relationship на элементе
Следующая аннотированная XDR-схема включает элементы <Customer> и <Order>. Элемент <Order> является дочерним для элемента <Customer>.
В схеме задана заметка sql:relationship для дочернего элемента <Order>. Сама связь определяется в элементе <xsd:appinfo>.
Элемент <relationship> определяет CustomerID в таблице Sales.SalesOrderHeader как внешний ключ, ссылающийся на первичный ключ CustomerID в таблице Sales.Customer. Поэтому заказы, принадлежащие заказчику, отображаются как дочерний элемент этого элемента <Customer>.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:mapping-schema"><xsd:annotation> <xsd:appinfo> <sql:relationship name="CustOrders" parent="Sales.Customer" parent-key="CustomerID" child="Sales.SalesOrderHeader" child-key="CustomerID" /> </xsd:appinfo></xsd:annotation> <xsd:element name="Customer" sql:relation="Sales.Customer" type="CustomerType" /> <xsd:complexType name="CustomerType" > <xsd:sequence> <xsd:element name="Order" sql:relation="Sales.SalesOrderHeader" sql:relationship="CustOrders" > <xsd:complexType> <xsd:attribute name="SalesOrderID" type="xsd:integer" /> <xsd:attribute name="CustomerID" type="xsd:string" /> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="CustomerID" type="xsd:string" /> </xsd:complexType></xsd:schema>
В предыдущей схеме используется именованная связь. Также можно указать неименованную связь. Результаты одинаковы.
Измененная схема, в которой указана неименованную связь:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:mapping-schema"> <xsd:element name="Customer" sql:relation="Sales.Customer" type="CustomerType" /> <xsd:complexType name="CustomerType" > <xsd:sequence> <xsd:element name="Order" sql:relation="Sales.SalesOrderHeader"> <xsd:annotation> <xsd:appinfo> <sql:relationship parent="Sales.Customer" parent-key="CustomerID" child="Sales.SalesOrderHeader" child-key="CustomerID" /> </xsd:appinfo> </xsd:annotation> <xsd:complexType> <xsd:attribute name="SalesOrderID" type="xsd:integer" /> <xsd:attribute name="CustomerID" type="xsd:string" /> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="CustomerID" type="xsd:string" /> </xsd:complexType></xsd:schema>
Проверка образца запроса XPath к схеме
Скопируйте приведенный выше код схемы и вставьте его в текстовый файл. Сохраните файл с именем sql-relationship.xml.
Скопируйте приведенный ниже шаблон и вставьте его в текстовый файл. Сохраните файл под именем sql-relationshipT.xml в том же каталоге, где был сохранен файл sql-relationship.xml.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <sql:xpath-query mapping-schema="sql-relationship.xml"> /Customer[@CustomerID=1] </sql:xpath-query></ROOT>Путь к каталогу схемы сопоставления (файл sql-relationship.xml) задается относительно каталога, в котором сохранен шаблон. Можно также задать абсолютный путь, например:
mapping-schema="C:\MyDir\sql-relationship.xml"Создайте и запустите тестовый сценарий SQLXML 4.0 (Sqlxml4test.vbs), чтобы выполнить шаблон.
Дополнительные сведения см. в разделе Использование объектов ADO для выполнения запросов SQLXML.
Полученный результирующий набор показан ниже.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <Customer CustomerID="1"> <Order OrderID="43860" CustomerID="1" /> <Order OrderID="44501" CustomerID="1" /> <Order OrderID="45283" CustomerID="1" /> <Order OrderID="46042" CustomerID="1" /> </Customer> </ROOT>
Б. Указание цепочки связей
Для данного примера предположим, что в следующем XML-документе нужно использовать данные, полученные из базы данных AdventureWorks:
<Order SalesOrderID="43659"> <Product Name="Mountain Bike Socks, M"/> <Product Name="Sport-100 Helmet, Blue"/> ...</Order>...
Для каждого заказа в таблице Sales.SalesOrderHeader в XML-документе имеется один элемент <Order>. А каждый элемент <Order> располагает списком дочерних элементов <Product> , по одному для каждого продукта, запрошенного в заказе.
Чтобы задать XSD-схему, которая сформирует эту иерархию, необходимо указать две связи: OrderOD и ODProduct. Связь OrderOD задает связь типа «родитель-потомок» между таблицами Sales.SalesOrderHeader и Sales.SalesOrderDetail. Связь ODProduct задает связь между таблицами Sales.SalesOrderDetail и Production.Product.
В следующей схеме заметка msdata:relationship на элементе <Product> задает два дочерних элемента: OrderOD и ODProduct. Важен порядок следования этих значений.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:mapping-schema"><xsd:annotation> <xsd:appinfo> <msdata:relationship name="OrderOD" parent="Sales.SalesOrderHeader" parent-key="SalesOrderID" child="Sales.SalesOrderDetail" child-key="SalesOrderID" /> <msdata:relationship name="ODProduct" parent="Sales.SalesOrderDetail" parent-key="ProductID" child="Production.Product" child-key="ProductID" /> </xsd:appinfo></xsd:annotation> <xsd:element name="Order" msdata:relation="Sales.SalesOrderHeader" msdata:key-fields="SalesOrderID" type="OrderType" /> <xsd:complexType name="OrderType" > <xsd:sequence> <xsd:element name="Product" msdata:relation="Production.Product" msdata:key-fields="ProductID" msdata:relationship="OrderOD ODProduct"> <xsd:complexType> <xsd:attribute name="Name" type="xsd:string" /> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="SalesOrderID" type="xsd:integer" /> </xsd:complexType></xsd:schema>
Вместо указания именованной связи можно задать анонимную связь. В этом случае все содержимое <annotation>...</annotation>, которое описывает две связи, отображается как потомок элемента <Product>.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:mapping-schema"> <xsd:element name="Order" msdata:relation="Sales.SalesOrderHeader" msdata:key-fields="SalesOrderID" type="OrderType" /> <xsd:complexType name="OrderType" > <xsd:sequence> <xsd:element name="Product" msdata:relation="Production.Product" msdata:key-fields="ProductID" > <xsd:annotation> <xsd:appinfo> <msdata:relationship parent="Sales.SalesOrderHeader" parent-key="SalesOrderID" child="Sales.SalesOrderDetail" child-key="SalesOrderID" /> <msdata:relationship parent="Sales.SalesOrderDetail" parent-key="ProductID" child="Production.Product" child-key="ProductID" /> </xsd:appinfo> </xsd:annotation> <xsd:complexType> <xsd:attribute name="Name" type="xsd:string" /> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="SalesOrderID" type="xsd:integer" /> </xsd:complexType> </xsd:schema>
Проверка образца запроса XPath к схеме
Скопируйте приведенный выше код схемы и вставьте его в текстовый файл. Сохраните файл с именем relationshipChain.xml.
Скопируйте приведенный ниже шаблон и вставьте его в текстовый файл. Сохраните файл под именем relationshipChainT.xml в том же каталоге, где был сохранен файл relationshipChain.xml.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <sql:xpath-query mapping-schema="relationshipChain.xml"> /Order </sql:xpath-query></ROOT>Путь к каталогу для схемы сопоставления (файл relationshipChain.xml) задается относительно каталога, в котором сохранен шаблон. Можно также задать абсолютный путь, например:
mapping-schema="C:\MyDir\relationshipChain.xml"Создайте и запустите тестовый сценарий SQLXML 4.0 (Sqlxml4test.vbs), чтобы выполнить шаблон.
Дополнительные сведения см. в разделе Использование объектов ADO для выполнения запросов SQLXML.
Полученный результирующий набор показан ниже.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <Order SalesOrderID="43659"> <Product Name="Mountain Bike Socks, M" /> <Product Name="Sport-100 Helmet, Blue" /> <Product Name="AWC Logo Cap" /> <Product Name="Long-Sleeve Logo Jersey, M" /> <Product Name="Long-Sleeve Logo Jersey, XL" /> ... </Order> ...</ROOT>
В. Задание заметки relationship на атрибуте
Пример в этой схеме включает элемент <Customer> с дочерним элементом <CustomerID> и атрибутом OrderIDList типа IDREFS. Элемент <IDREFS сопоставляется с таблицей Sales.Customers в базе данных AdventureWorks. По умолчанию область действия этого сопоставления распространяется на все дочерние элементы или атрибуты, если только sql:relation не указан на дочернем элементе или атрибуте, в случае чего соответствующая связь «первичный ключ — внешний ключ» должна быть определена с использованием элемента <relationship>. Дочерний элемент или атрибут, который указывает другую таблицу с использованием заметки relation, должен также указывать заметку relationship.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:mapping-schema"><xsd:annotation> <xsd:appinfo> <sql:relationship name="CustOrders" parent="Sales.Customer" parent-key="CustomerID" child="Sales.SalesOrderHeader" child-key="CustomerID" /> </xsd:appinfo></xsd:annotation> <xsd:element name="Customer" sql:relation="Sales.Customer" type="CustomerType" /> <xsd:complexType name="CustomerType" > <xsd:sequence> <xsd:element name="CustomerID" type="xsd:string" /> </xsd:sequence> <xsd:attribute name="OrderIDList" type="xsd:IDREFS" sql:relation="Sales.SalesOrderHeader" sql:field="SalesOrderID" sql:relationship="CustOrders" > </xsd:attribute> </xsd:complexType></xsd:schema>
Проверка образца запроса XPath к схеме
Скопируйте приведенный выше код схемы и вставьте его в текстовый файл. Сохраните файл как relationship-on-attribute.xml.
Скопируйте следующий шаблон и вставьте его в файл. Сохраните файл как relationship-on-attributeT.xml в том же каталоге, в котором был сохранен файл relationship-on-attribute.xml. Запрос в шаблоне выбирает заказчика со значением CustomerID, равным 1.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <sql:xpath-query mapping-schema="relationship-on-attribute.xml"> /Customer[CustomerID=1] </sql:xpath-query></ROOT>Путь к каталогу схемы сопоставления (файл relationship-on-attribute.xml) задается относительно каталога, в котором сохранен шаблон. Можно также задать абсолютный путь, например:
mapping-schema="C:\MyDir\relationship-on-attribute.xml"Создайте и запустите тестовый сценарий SQLXML 4.0 (Sqlxml4test.vbs), чтобы выполнить шаблон.
Дополнительные сведения см. в разделе Использование объектов ADO для выполнения запросов SQLXML.
Полученный результирующий набор показан ниже.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <Customer OrderIDList="43860 44501 45283 46042"> <CustomerID>1</CustomerID> </Customer></ROOT>
Г. Укажите sql:relationship на нескольких элементах
В этом примере аннотированная XSD-схема содержит элементы <Customer>, <Order> и <OrderDetail>.
Элемент <Order> является дочерним элементом элемента <Customer>. <sql:relationship> указывается для дочернего элемента <Order>, поэтому заказы, принадлежащие заказчику, отображаются как дочерние элементы <Customer>.
Элемент <Order> содержит дочерний элемент <OrderDetail>. <sql:relationship> указывается для дочернего элемента <OrderDetail>, поэтому подробности заказа отображаются как дочерние элементы этого элемента <Order>.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:mapping-schema"><xsd:annotation> <xsd:appinfo> <sql:relationship name="CustOrders" parent="Sales.Customer" parent-key="CustomerID" child="Sales.SalesOrderHeader" child-key="CustomerID" /> <sql:relationship name="OrderOrderDetail" parent="Sales.SalesOrderHeader" parent-key="SalesOrderID" child="Sales.SalesOrderDetail" child-key="SalesOrderID" /> </xsd:appinfo></xsd:annotation> <xsd:element name="Customer" sql:relation="Sales.Customer" > <xsd:complexType> <xsd:sequence> <xsd:element name="Order" sql:relation="Sales.SalesOrderHeader" sql:relationship="CustOrders" maxOccurs="unbounded" > <xsd:complexType> <xsd:sequence> <xsd:element name="OrderDetail" sql:relation="Sales.SalesOrderDetail" sql:relationship="OrderOrderDetail" maxOccurs="unbounded" > <xsd:complexType> <xsd:attribute name="SalesOrderID" type="xsd:integer" /> <xsd:attribute name="ProductID" type="xsd:string" /> <xsd:attribute name="OrderQty" type="xsd:integer" /> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="SalesOrderID" type="xsd:integer" /> <xsd:attribute name="OrderDate" type="xsd:date" /> <xsd:attribute name="CustomerID" type="xsd:string" /> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="CustomerID" type="xsd:string" /> </xsd:complexType> </xsd:element></xsd:schema>
Проверка образца запроса XPath к схеме
Скопируйте приведенный выше код схемы и вставьте его в текстовый файл. Сохраните файл с именем relationship-multiple-elements.xml.
Скопируйте следующий шаблон и вставьте его в текстовый файл. Сохраните файл как relationship-multiple-elementsT.xml в том же каталоге, в котором был сохранен файл relationship-multiple-elements.xml. Запрос в шаблоне возвращает сведения о заказчике со значением CustomerID, равным 1, и значением SalesOrderID, равным 43860.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <sql:xpath-query mapping-schema="relationship-multiple-elements.xml"> /Customer[@CustomerID=1]/Order[@SalesOrderID=43860] </sql:xpath-query></ROOT>Путь к каталогу схемы сопоставления (файл relationship-multiple-elements.xml) задается относительно каталога, в котором сохранен шаблон. Можно также задать абсолютный путь, например:
mapping-schema="C:\MyDir\relationship-multiple-elements.xml"Создайте и запустите тестовый сценарий SQLXML 4.0 (Sqlxml4test.vbs), чтобы выполнить шаблон.
Дополнительные сведения см. в разделе Использование объектов ADO для выполнения запросов SQLXML.
Полученный результирующий набор показан ниже.
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <Order SalesOrderID="43860" OrderDate="2001-08-01" CustomerID="1"> <OrderDetail SalesOrderID="43860" ProductID="761" OrderQty="2" /> <OrderDetail SalesOrderID="43860" ProductID="770" OrderQty="1" /> <OrderDetail SalesOrderID="43860" ProductID="758" OrderQty="2" /> <OrderDetail SalesOrderID="43860" ProductID="765" OrderQty="2" /> <OrderDetail SalesOrderID="43860" ProductID="732" OrderQty="1" /> <OrderDetail SalesOrderID="43860" ProductID="762" OrderQty="1" /> <OrderDetail SalesOrderID="43860" ProductID="738" OrderQty="1" /> <OrderDetail SalesOrderID="43860" ProductID="768" OrderQty="1" /> <OrderDetail SalesOrderID="43860" ProductID="753" OrderQty="2" /> <OrderDetail SalesOrderID="43860" ProductID="729" OrderQty="1" /> <OrderDetail SalesOrderID="43860" ProductID="763" OrderQty="1" /> <OrderDetail SalesOrderID="43860" ProductID="756" OrderQty="1" /> </Order></ROOT>
Д. Указание <sql:relationship> без родительского атрибута.
Этот пример показывает задание <sql:relationship> без атрибута parent. Например, предположим, что есть следующая таблица сотрудников:
Emp1(SalesPersonID, FirstName, LastName, ReportsTo)Emp2(SalesPersonID, FirstName, LastName, ReportsTo)
В следующем XML-представлении элементы <Emp1> и <Emp2> сопоставляются таблицам Sales.Emp1 и Sales.Emp2.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:mapping-schema"><xsd:annotation> <xsd:appinfo> <sql:relationship name="EmpOrders" parent-key="SalesPersonID" child="Sales.SalesOrderHeader" child-key="SalesPersonID" /> </xsd:appinfo></xsd:annotation> <xsd:element name="Emp1" sql:relation="Sales.Emp1" type="EmpType" /> <xsd:element name="Emp2" sql:relation="Sales.Emp2" type="EmpType" /> <xsd:complexType name="EmpType" > <xsd:sequence> <xsd:element name="Order" sql:relation="Sales.SalesOrderHeader" sql:relationship="EmpOrders" > <xsd:complexType> <xsd:attribute name="SalesOrderID" type="xsd:integer" /> <xsd:attribute name="CustomerID" type="xsd:string" /> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="SalesPersonID" type="xsd:integer" /> <xsd:attribute name="LastName" type="xsd:string" /> </xsd:complexType></xsd:schema>
В схеме как элемент <Emp1>, так и элемент <Emp2> имеют тип EmpType. Тип EmpType описывает дочерний элемент <Order> и соответствующий <sql:relationship>. В этом случае не существует одного родителя, которого можно определить в <sql:relationship> с использованием атрибута parent. В этой ситуации не указывается атрибут parent в <sql:relationship>; сведения атрибута parent извлекаются из иерархии в схеме.
Проверка образца запроса XPath к схеме
Создайте следующие таблицы в базе данных AdventureWorks:
USE AdventureWorksCREATE TABLE Sales.Emp1 ( SalesPersonID int primary key, FirstName varchar(20), LastName varchar(20), ReportsTo int)GoCREATE TABLE Sales.Emp2 ( SalesPersonID int primary key, FirstName varchar(20), LastName varchar(20), ReportsTo int)GoДобавьте следующий образец данных в таблицы:
INSERT INTO Sales.Emp1 values (279, 'Nancy', 'Devolio',NULL)INSERT INTO Sales.Emp1 values (282, 'Andrew', 'Fuller',1)INSERT INTO Sales.Emp1 values (276, 'Janet', 'Leverling',1)INSERT INTO Sales.Emp2 values (277, 'Margaret', 'Peacock',3)INSERT INTO Sales.Emp2 values (283, 'Steven', 'Devolio',4)INSERT INTO Sales.Emp2 values (275, 'Nancy', 'Buchanan',5)INSERT INTO Sales.Emp2 values (281, 'Michael', 'Suyama',6)Скопируйте приведенный выше код схемы и вставьте его в текстовый файл. Сохраните файл с именем relationship-noparent.xml.
Скопируйте следующий шаблон и вставьте его в текстовый файл. Сохраните файл как relationship-noparentT.xml в том же каталоге, в котором был сохранен файл relationship-noparent.xml. Запрос в шаблоне выбирает все элементы <Emp1> (поэтому родитель — Emp1).
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <sql:xpath-query mapping-schema="relationship-noparent.xml"> /Emp1 </sql:xpath-query></ROOT>Путь к каталогу схемы сопоставления (файл relationship-noparent.xml) задается относительно каталога, в котором сохранен шаблон. Можно также задать абсолютный путь, например:
mapping-schema="C:\MyDir\relationship-noparent.xml"Создайте и запустите тестовый сценарий SQLXML 4.0 (Sqlxml4test.vbs), чтобы выполнить шаблон.
Дополнительные сведения см. в разделе Использование объектов ADO для выполнения запросов SQLXML.
Вот частичный результирующий набор:
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql"><Emp1 SalesPersonID="276" LastName="Leverling"> <Order SalesOrderID="43663" CustomerID="510" /> <Order SalesOrderID="43666" CustomerID="511" /> <Order SalesOrderID="43859" CustomerID="259" /> ...</Emp1>