SQL2005用XML数据类型进行数据建模(二)

日期: 2008-06-09 作者:Shankar Pal 来源:TechTarget中国

  创建属性表


  您可能希望将XML数据中的某些多值属性提升到一个或多个表中,在这些表上创建索引,并且重定向查询以使用这些表。典型的情形是一小部分属性覆盖了大部分查询工作负荷。您可以执行以下操作:



  • 创建一个或多个表以存放多值属性。您可能发现采用以下处理方式会很方便:每个表存储一个属性,并且在属性表中复制基表的主键以便与基表进行向后联接。

  • 如果您希望保持属性的相对顺序,则需要为相对顺序引入一个单独的列。

  • 在XML列上创建触发器以便维护属性表。在触发器中,执行以下操作: 

  •  使用XML数据类型方法(如nodes() 和 value()在属性表中插入和删除行。(有关 nodes() 方法的详细信息,请参阅Value()、Nodes()和OpenXML()。)

  • 在CLR中创建流式表值函数,以便在属性表中插入和删除行。

  • 编写查询,以便对属性表进行SQL访问,以及对基表中的XML列进行XML访问,这需要使用这些表的主键将其相互联接。

  示例:创建属性表


  假设您希望提升作者的名字。书籍有一个或多个作者,因此名字是一个多值属性。每个名字都存储在属性表的单独行中。在属性表中复制了基表的主键以便向后联接。



  create table tblPropAuthor (propPK int, propAuthor varchar(max))
 


  示例:创建用户定义的函数以便从XML实例生成行集


  下面的表值函数udf_XML2Table接受一个主键值和一个XML实例。它将检索 元素的所有作者的名字,并返回(主键,名字)对行集。



  create function udf_XML2Table (@pk int, @xCol xml)
returns @ret_Table table (propPK int, propAuthor varchar(max))
with schemabinding
as
begin
      insert into @ret_Table
      select @pk, nref.value(’.’, ’varchar(max)’)
      from   @xCol.nodes(’/book/author/first-name’) R(nref)
      return
end


  示例:创建触发器以填充属性表


  插入触发器:在属性表中插入行



create trigger trg_docs_INS on T for insert
as
      declare @wantedXML xml
      declare @FK int
select @wantedXML = xCol from inserted
      select @FK = PK from inserted


insert into tblPropAuthor
select * from dbo.udf_XML2Table(@FK, @wantedXML)
 


  删除触发器:基于删除行的主键值,从属性表中删除行



create trigger trg_docs_DEL on T for delete
as
   declare @FK int
   select @FK = PK from deleted
   delete tblPropAuthor where propPK = @FK
 


  更新触发器:在与更新的XML实例对应的属性表中删除现有行,并且在该属性表中插入新行
 


create trigger trg_docs_UPD
on T
for update
as
if update(xCol) or update(pk)
begin
      declare @FK int
      declare @wantedXML xml
      select @FK = PK from deleted
      delete tblPropAuthor where propPK = @FK


select @wantedXML = xCol from inserted
select @FK = pk from inserted


insert into tblPropAuthor
      select * from dbo.udf_XML2Table(@FK, @wantedXML)
end
 


  示例:查找作者的名字为”David”的XML实例


  可以在XML列上表示该查询。另外,还可以在属性表中搜索名字”David”,然后与基表执行向后联接以返回XML实例,如下所示:



select xCol
FROM     T join tblPropAuthor ON T.pk = tblPropAuthor.propPK
where    tblPropAuthor.propAuthor = ’David’


  示例:使用CLR流式表值函数的解决方案


  该解决方案包括以下步骤:(a)定义CLR类SqlReaderBase,它实现了ISqlReader,并且通过在XML实例上应用路径表达式来生成流式表值输出;(b) 创建一个程序集和一个T-SQL用户定义函数(UDF)来激活该CLR 类;(c) 使用 UDF 定义插入、更新和删除触发器,以维护属性表。


首先,创建流式CLR函数,其主干如下所示。XML数据类型被公开为ADO.NET中的托管类SqlXml;它支持返回XmlReader的方法createReader()。



public class c_streaming_xml_tvf {
public static ISqlReader streaming_xml_tvf
(SqlXml xmlDoc, string pathExpression) {
return (new TestSqlReaderBase (xmlDoc, pathExpression));
}
}


// Class that implements ISqlReader
public class TestSqlReaderBase : ISqlReader {
XPathNodeIterator m_iterator;        
???public Sqlchars FirstName;
// Metadata for current resultset
private SqlMetaData[] m_rgSqlMetaData;     


public TestSqlReaderBase (SqlXml xmlDoc, string pathExpression) {  
// Variables for XPath navigation
      XPathDocument xDoc;
      XPathNavigator xNav;
      XPathExpression xPath;


      // Set sql meta data
      m_rgSqlMetaData = new SqlMetaData[1];
      m_rgSqlMetaData[0] = new SqlMetaData (“FirstName”, 
SqlDbType.NVarchar,50);  


      //Set up the Navigator
      if (!xmlDoc.IsNull)
          xDoc = new XPathDocument (xmlDoc.createReader());
      else
          xDoc = new XPathDocument ();
      xNav = xDoc.createNavigator();
      xPath = xNav.Compile (pathExpression);
      m_iterator = xNav.select(xPath);
}
public bool Read() {
      bool moreRows = true;
      if (moreRows = m_iterator.MoveNext())
      ???FirstName = new Sqlchars (m_iterator.Current.Value);
      return moreRows;
}
}
 


  接下来,创建一个程序集,以及一个与CLR函数 streaming_xml_tvf 对应的 T-SQL 用户定义函数SQL_streaming_xml_tvf(未显示)。该UDF用于定义表值函数CLR_udf_XML2Table 以便生成行集:



create function CLR_udf_XML2Table (@pk int, @xCol xml)
returns @ret_Table table (FK int, FirstName varchar(max))
with schemabinding
as
begin
      insert into @ret_Table
select @pk, FirstName
FROM   SQL_streaming_xml_tvf (@xCol, ’/book/author/first-name’)
      return
end
 


  最后,定义触发器,如示例创建触发器以填充属性表中所示,但用函数CLR_udf_XML2Table 替换 udf_XML2Table。因此,插入触发器将如下所示:



create trigger CLR_trg_docs_INS on T for insert
as
declare @wantedXML xml
declare @FK int
select @wantedXML = xCol from inserted
select @FK = PK from inserted


insert into tblPropAuthor
      select *
from    dbo.CLR_udf_XML2Table(@FK, @wantedXML)
 


  删除触发器与非CLR版本完全相同,而更新触发器只是将函数udf_XML2Table()替换为CLR_udf_XML2Table()。


  XML架构集合


  XML架构集合是一个元数据实体,其范围由关系架构确定,包含一个或多个可能相关(例如,通过 )或无关的XML架构。XML架构集合中的单独XML架构由其目标命名空间标识。


  XML架构集合是使用create XML SCHEMA COLLECTION语法创建的,并且提供了一个或多个XML架构。可以向现有XML架构中添加更多的XML架构组件,并且可以使用alter XML SCHEMA COLLECTION语法向XML架构集合中添加更多的架构。可以使用SQL Server 2005中的安全模型像任何SQL对象那样保证 XML 架构集合的安全。


  多类型化列


  XML架构集合C按照多个XML架构将 XML 列 xCol 类型化。此外,标志DOCUMENT或CONTENT分别指定XML树或片段是否可以存储在列xCol 中。


  对于 DOCUMENT,每个 XML 实例都会按照用来对其进行验证和类型化的命名空间,指定实例中顶级元素的目标命名空间。另一方面,对于CONTENT,每个顶级元素都可以指定 C 中的任一目标命名空间。XML 实例将按照实例中存在的所有目标命名空间进行验证和类型化。


  架构演变


  XML架构集合用于类型化XML列、变量和参数。它提供了一种XML架构演变机制。假设您将带有目标命名空间BOOK-V1的XML架构添加到XML架构集合C中。使用C加以类型化的XML列xCol可以存储符合BOOK-V1架构的XML数据。


  假设某个应用程序希望通过新的架构组件(例如复杂类型定义和顶级元素声明)来扩展XML架构。这些新的架构组件可以添加到BOOK-V1架构中,并且不要求对列xCol中的现有 XML 数据进行重新验证。


  假设该应用程序后来希望提供该XML架构的新版本,并且为该新版本选择目标命名空间BOOK-V2。该XML架构可以添加到C中。XML列可以存储BOOK-V1和BOOK-V2二者的实例,并且对符合这些命名空间的XML实例执行查询和数据修改。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐

  • Oracle Hyperion 11.1.2.1 迁移特性与问题

    Oracle Hyperion 11.1.2.1包含可以简化移植的新工具,它们在很多情况下能够减少操作步骤。但还是有诸如Essbase Studio的一些问题必须在以后的版本中进行修复。

  • SQL Server 数据访问策略:CLR

    CLR在很大程度上解放了TSQL逻辑运算能力不足的问题,而且CLR拥有丰富的语言支持,C#,VB.NET等;在.Net Framework基础上,拥有复杂的过程逻辑和计算。

  • 在Oracle数据库中使用XML数据获取业务信息

    只需要通过从一个XML表中提取数据,我们就能发送XML格式化的采购订单给下游使用,这与需要更多转换步骤的多个关系型表才能实现形成明显对比。

  • 详解如何将关系型数据发布为XML

    抽取是通过使用XMLType视图实现的,本质上是物化为SQL执行的一个存储查询结果。XMLType视图允许文档为中心的应用程序把底层的关系结构查询为虚拟的XML文档。