使用 sql:relationship 指定关系 (SQLXML 4.0)
可以对 XML 文档中的元素建立相关性。元素可以按层次结构方式嵌套,并且可以在元素之间指定 ID、IDREF 或 IDREFS 关系。
例如,在 XSD 架构中,<Customer> 元素包含 <Order> 子元素。当此架构映射到 AdventureWorks2008R2 数据库时,<Customer> 元素映射到 Sales.Customer 表,而 <Order> 元素映射到 Sales.SalesOrderHeader 表。由于是由客户下订单,因此,基础表 Sales.Customer 和 Sales.SalesOrderHeader 是相关的。Sales.SalesOrderHeader 表中的 CustomerID 是外键,它引用 Sales.Customer 表中的 CustomerID 主键。您可以使用 sql:relationship 批注在映射架构元素之间建立这些关系。
在带批注的 XSD 架构中,sql:relationship 批注用于根据元素所映射到的各基础表之间的主键和外键关系,按层次结构方式嵌套架构元素。在指定 sql:relationship 批注时,必须标识以下内容:
父表 (Sales.Customer) 和子表 (Sales.SalesOrderHeader)。
组成父表与子表间关系的一列或多列。例如,CustomerID 列,该列同时出现在父表和子表中。
此信息用于生成适当的层次结构。
为了提供表名和必需的联接信息,应针对 sql:relationship 批注指定以下属性。这些属性仅对于 <sql:relationship> 元素有效:
名称
指定关系的唯一名称。Parent
指定父关系(表)。这是一个可选属性;如果未指定此属性,将从文档的子层次结构中的信息获得父表名称。如果架构指定了两个父子层次结构,并且两者使用相同的 <sql:relationship> 但使用不同的父元素,则您未在 <sql:relationship> 中指定父属性。此信息将从架构的层次结构中获得。parent-key
指定父项的父键。如果父键由多列组成,则指定值时应在各值之间使用空格。在为多列键指定的值与为对应的子键指定的值之间存在位置映射。Child
指定子关系(表)。child-key
在引用父项中父键的子项中指定子键。如果子键由多个属性(列)组成,则指定子键值时应在各值之间使用空格。在为多列键指定的值与为对应的父键指定的值之间存在位置映射。Inverse
针对 <sql:relationship> 指定的这一属性由 updategram 使用。有关详细信息,请参阅针对 sql:relationship 指定 sql:inverse 属性。
必须在包含某个子元素、在自身与该子元素之间定义了 <sql:relationship> 且未提供表的主键(在父元素中指定)的元素中指定 sql:key-fields 批注。即使架构未指定 <sql:relationship>,您也必须指定 sql:key-fields 以生成适当的层次结构。有关详细信息,请参阅使用 sql:key-fields 标识键列。
为了在结果中生成适当的嵌套,建议在所有架构中指定 sql:key-fields。
示例
若要创建使用以下示例的工作示例,必须满足某些要求。有关详细信息,请参阅运行 SQLXML 示例的要求。
A. 针对元素指定 sql:relationship 批注
以下带批注的 XSD 架构包含 <Customer> 和 <Order> 元素。<Order> 元素是 <Customer> 元素的子元素。
在此架构中,针对 <Order> 子元素指定 sql:relationship 批注。关系本身在 <xsd:appinfo> 元素中定义。
<relationship> 元素将 Sales.SalesOrderHeader 表中的 CustomerID 标识为一个外键,该外键引用 Sales.Customer 表中的 CustomerID 主键。因此,属于某个客户的订单将显示为该 <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-relationship.xml 的相同目录中将该文件另存为 sql-relationshipT.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>
B. 指定关系链
对于本示例,假定您需要以下 XML 文档,该文档使用从 AdventureWorks2008R2 数据库获得的数据:
<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 表之间的关系。
在下面的架构中,<Product> 元素上的 msdata:relationship 批注指定两个值: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。
复制下面的模板,然后将其粘贴到文本文件中。在您保存 relationshipChain.xml 的相同目录中将该文件另存为 relationshipChainT.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>
C. 针对属性指定关系批注
本示例中的架构包括一个 <Customer> 元素,该元素具有一个 <CustomerID> 子元素和一个类型为 IDREFS 的 OrderIDList 属性。<Customer> 元素映射到 AdventureWorks2008R2 数据库中的 Sales.Customer 表。默认情况下,此映射的作用域应用于所有子元素或属性,除非针对该子元素或属性指定了 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-attribute.xml 的相同目录中将该文件另存为 relationship-on-attributeT.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>
D. 针对多个元素指定 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-elements.xml 的相同目录中将该文件另存为 relationship-multiple-elementsT.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>
E. 在不使用父属性的情况下指定 <sql:relationship>
本示例说明如何在不使用 parent 属性的情况下指定 <sql:relationship>。例如,假设您具有以下员工表:
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>。在这种情况下,通过使用 parent 属性无法在 <sql:relationship> 中标识任何单个父项。此时,您未在 <sql:relationship> 中指定 parent 属性;parent 属性信息将从架构的层次结构中获得。
针对该架构测试示例 XPath 查询
在 AdventureWorks2008R2 数据库中创建以下表:
USE AdventureWorks2008R2; GO CREATE TABLE Sales.Emp1 ( SalesPersonID int primary key, FirstName varchar(20), LastName varchar(20), ReportsTo int) Go CREATE 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-noparent.xml 的相同目录中将该文件另存为 relationship-noparentT.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>