使用 sql:relationship 指定关系 (SQLXML 4.0)
可以对 XML 文档中的元素建立相关性。元素可以按层次结构方式嵌套,并且可以在元素之间指定 ID、IDREF 或 IDREFS 关系。
例如,在 XSD 架构中,<Customer> 元素包含 <Order> 子元素。当此架构映射到 AdventureWorks 数据库时,<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> 元素有效:
Name
指定关系的唯一名称。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 文档,该文档使用从 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 表之间的关系。
在下面的架构中,<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> 元素映射到 AdventureWorks 数据库中的 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 查询
在 AdventureWorks 数据库中创建这些表:
USE AdventureWorks 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>