四、sql server 2005 中的客户端 xml 处理
xml 数据类型的客户端支持.net 框架 v2.0 中的 ado.net xml 支持在 sqldatareader.getsqlxml() 方法的 system.data.sqltypes 命名空间中,xml 数据类型是作为类 sqlxml 公开的。可以使用 sqlxml.createreader() 函数从 sqlxml 对象获得 xmlreader。
类型化 xml 列的 xml 架构集合的名称由三部分组成,可以从 xml 列的元数据中获得(通过使用 sqldatareader 对象中的 getschematable() 或 getsqlmetadata (int)),其三个部分作为三个属性,分别表示数据库 (xmlschemacollectiondatabase)、关系架构 (xmlschemacollectionowingschema) 和 xml 架构集合 (xmlschemacollectionname) 的名称。
客户端可以使用新的架构行集 xmlschema 从服务器检索 xml 架构。xmlschema 行集包含 xml 架构集合、目标命名空间和 xml 架构内容本身这样三列。
下面的示例显示了用于对 xml 数据类型进行托管访问的主干代码。
例:对 xml 数据类型进行进程内访问
下面的 c# 代码演示了如何从进程内提供程序访问 xml 数据类型。用于 sql 客户端访问的代码需要适当地改变进程内访问。
using system;
using system.xml;
using system.data;
using system.data.sqltypes;
using system.data.sqlserver;
class xmldtadonetreadaccessinproc
{
static void readxmldatatype () {
// in-proc connection to server
sqlconnection conn = sqlcontext.getconnection();
// prepare query to select xml data
sqlcommand cmd = conn.createcommand();
cmd.commandtext = "select xcol from docs";
// execute query and retrieve incoming data
sqldatareader r = cmd.executereader();
r.read();
// access xml data type field in rowset
sqlxml xml = r.getsqlxml(0);
new xmltextwriter(console.out).writenode(
xml.createreader(), true);
}
}
例:使用 sql 客户端提供程序更新 xml 数据类型列
下面的代码所显示的 writexmldaratype() 方法使用 sql 客户端程序提供程序来替换 xml 列中的值。用于进程内提供程序的代码是相似的。
using system;
using system.xml;
using system.data;
using system.data.sqltypes;
using system.data.sqlclient;
class xmldtadonetupdateaccess
{
static void writexmldatatype () {
// connection to server
sqlconnection conn = new sqlconnection("server=server1;" +
" database=xmltest; integrated security=sspi");
conn.open();
// update xml column at the server
sqlcommand cmd = conn.createcommand();
cmd.commandtext = "update docs set [email protected] where id=1";
// set value of xml parameter
sqlparameter p = cmd.parameters.add("@x", sqldbtype.xml);
p.value = new sqlxml(new xmltextreader("<hello/>",
xmlnodetype.document, null));
// execute update and close connection
cmd.executenonquery();
conn.close();
}
}
sql 本机客户端访问 在新的 sql 本机访问 (sqlncli) 的 ole db 提供程序中,可以通过 isequentialstream 来将 xml 数据类型列作为 unicode 字符串(dbtype_xml、dbtype_bstr、dbtype_wstr 和 dbtype_variant)或 unicode 字符串流进行检索。默认为 dbtype_xml。
由三部分组成的 xml 架构集合名称是在由 idbschemarowset::getrowset() 返回的 columns 架构行集的三个新列中携带的:ss_xml_catalogname 给出目录的名称;ss_xml_schemaname 给出 xml 架构集合所驻留的关系架构的名称;ss_xml_schemacollectionname 给出 xml 架构集合的名称。这些名称都属于 dbtype_wstr 类型。对于非类型化的 xml 列,这些列具有 null 值。
可以对 procedure_parameters 架构行集和 icolumnrowset:getcolumnrowset() 进行类似的改变。
要检索 xml 架构集合的内容,客户端可以通过在对 xml_schema_namespace() 的调用中使用这些名称来单独访问服务器,并且返回 xml 架构作为 xml 数据类型。另外,带有新的 ss_xmlschema 架构行集的 idbschemarowset 可以返回目录的名称、关系架构的名称、xml 架构集合的名称、目标命名空间和 xml 架构。
要使用 sqlncli 进行 odbc 访问,需要将 xml 数据类型映射到名为 sql_ss_xml 的 unicode 可变长度字符数据。由三部分组成的 xml 架构集合的名称是通过用于 xml 列的 sqlcolattribute 作为 characterattributeptr 出现的。这些字段标识符为 sql_desc_ss_xml_schema_catalog_name、sql_desc_ss_xml_schema_schema_name 和 sql_desc_ss_xml_schema_collection_name,分别用于数据库、关系架构和 xml 架构集合的名称。
用户必须安装 sql server 2005 版的数据库服务器或客户端工具才能获取 sql 本机客户端。在撰写本文时,还不能使用 mdac 2.8 ado 对 xml 数据类型进行 ole db 访问。
sqlxml — xml 和关系架构之间的映射
可以使用 sqlxml 映射技术来创建关系数据的逻辑 xml 视图。xml 视图(也称为“映射”或“带注解的架构”)是通过将特殊的注解添加到特定的 xsd 架构中创建的。于是,其他的 sqlxml 技术就可以使用这种带注解的架构,将针对逻辑 xml 视图进行的查询和更新转换成针对关系表进行的查询和更新:
•
当 xml 视图与 xpath 查询组合在一起时,sqlxml 将生成 for xml 查询来查找请求数据,并且根据架构的指定对其进行构形。
|||
•
sqlxml updategrams 表示对 xml 实例进行的更改,当与带注解的架构组合在一起时,将使用开放式并发将这些更改重新保存到关系更改中,以确保更新正确的数据。
•
sqlxml bulkload 使用 xml 视图将 xml 数据“切碎”并存放到关系表中。
有关这些主题的更多信息,请访问 sqlxml documentation。
创建关系表的 xml 视图要创建数据库的 xml 视图,需要从用于 xml 数据的 xsd 架构开始。数据库表/视图中的行将映射为该架构中复杂类型的元素。数据库中的列值映射为属性或简单类型的元素。
默认情况下,如果没有给出显式注解,sqlxml 就会假定复杂类型的元素将映射到表,而简单类型的元素和属性将映射到列。只有当元素和属性的名称与数据库中表和列的名称完全相同时,这才有效。
如果元素/属性的名称与它映射到的表/视图或列的名称不同,则必须创建显式映射。下面的注解用于指定 xml 文档中的元素或属性间的映射和数据库中的表(视图)或列之间的映射:
•
sql:relation — 将 xml 元素映射到数据库表。
•
sql:field — 将元素或属性映射到数据库列。
通过映射关系创建 xml 视图中的层次在数据库中,表可以通过外键关系来关联。在 xml 中,这些相同的关系是通过嵌套的元素层次来表示的。为了在映射中构造正确的嵌套,必须指定关联元素的方式。可以使用 sql:relationship 注解在映射架构元素中建立这些关系。在这种注解中,可以指定父表和子表,以及每个表中需要用于执行加入的列。然后,sqlxml 将利用这些信息为映射构造正确的嵌套层次。
使用溢出存储未使用的数据当 xml 数据有正规的结构时映射是有效的。然而,在 xml 中,可能有一些数据是非结构化的,还可能有一些数据没有映射到特定的列。要存储这种数据并随后检索它,可以使用 sql:overflow 注解。sql:overflow 注解指定存储所有未使用数据的列以及查询时从何处检索数据。
|||
通过溢出列,还可以扩展 xml,而不必将其添加到数据库。可以在任何时候将元素和属性添加到 xml 结构,而不必在数据库中添加列来存储它们。可以将它们简单地存储到溢出字段,并且在适当的时候对其进行检索。
更多信息有关创建 xml 视图和映射示例的详细信息,请参阅 creating xml views by using annotated xsd schemas。
使用 xpath 来查询 xml 视图一旦创建好数据库的 xml 视图,就可以使用 xpath 查询语言来查询视图,就好像它是实际的 xml 文档一样。sqlxml 支持 xpath 1.0 查询语言中的一个子集。当针对映射进行 xpath 查询时,sqlxml 将它们组合在一起,并且创建发送到 sql server 的 for xml explicit 语句。然后检索正确的数据,并根据映射对其进行构形。
请参阅 sqlxml 文档以获得关于 xml 视图中支持的 xpath 子集的详细信息。
使用 updategrams 通过 xml 视图进行更新可以通过 xml 视图修改(插入、更新或删除)sql server 中的数据库,方法是针对数据库的 xml 视图使用 updategram。
updategram 的结构updategram 是一个 xml 文档,带有<sync>、<before> 和<after> 元素,这些元素构成了 updategram 的语法。每个<sync> 块包含一个或多个<before> 和<after> 块。<before> 标识记录实例的现有状态(也称为“前状态”)。<after> 标识要更改的数据的新状态。updategram 是删除、插入还是更新记录实例取决于<before> 和<after> 块的内容。
插入操作当记录实例出现在<after> 块而没有出现在相应的<before> 块中时,updategram 指示插入操作。在这种情况下,updategram 将<after> 块中的记录插入数据库。
|||删除操作
当记录实例出现在<before> 块而没有相应的记录出现在<after> 块中时,updategram 指示删除操作。在这种情况下,updategram 从数据库中删除<before> 块中的记录。
如果在 updategram 中指定的元素或者匹配表中的多行或者不匹配表中的任何行,则 updategram 会返回错误,并取消整个<sync> 块。updategram 中的元素一次只能删除一条记录。
更新操作当更新现有的数据时,必须指定<before> 和<after> 块。updategram 使用<before> 块中指定的元素来标识数据库中的现有记录。<after> 块中相应的元素指示在执行更新操作之后记录的外观应该怎样。
<before>块中的元素必须只与数据库中的一个表行相匹配。如果该元素匹配多个表行或不匹配任何表行,则 updategram 都会返回错误,并且取消整个<sync> 块。
更多信息
要获得更多关于通过 xml 视图创建和使用 updategram 修改数据的信息,请参阅 using updategrams to modify data。
通过 xml 视图大量加载 xml 数据xml bulk load 是一个 com 对象,它允许您将 xml 数据加载到 sql server 表中。虽然通过使用 insert 语句和 openxml 函数可以将 xml 数据插入 sql server 数据库中,但是当需要插入大量的 xml 数据时,这种大量加载实用程序提供了更高的性能。xml bulk load 解释映射架构并标识 xml 数据要插入的表。然后,它将 xml 数据“切碎”并存放到关系表中。
在进行大量加载处理时,由于源 xml 文档可能很大,所以并不将整个文档读入内存。相反,xml bulk load 将 xml 数据解释为流,并且边解释它边读取它。当该实用程序读取数据时,它标识数据库表,从 xml 数据源生成适当的记录,然后将记录发送到 sql server,以供插入。
要获得更多关于 bulk load 如何工作和使用的信息,请参阅 performing bulk load of xml data。
sqlxml 数据访问方法由于有了 sql server 2000,所以又增加了两种访问 sqlxml 功能的新方法:
•
sqlxml 托管类
•
sqlxml web 服务
另外,还增强了对 sql server 的 http 访问,以提供对模板中的 updategram 的支持。
sqlxml 托管类sqlxml 托管类公开 microsoft .net 框架内的 sqlxml 3.0 的功能。通过 sqlxml 托管类,可以编写 c# 应用程序从 sql server 的实例访问 xml 数据,将数据带入 .net 框架环境,处理数据,并将更新重新发送回 sql server 以应用这些更新。
要获得更多关于如何使用 sqlxml 托管类的细节,请参阅 sqlxml .net support。
sqlxml web 服务sqlxml 中的 web 服务支持将 sql server 作为 web 服务公开,从而为客户端提供 sql server 功能。可以将 soap http 请求发送到正在运行 sqlxml 的服务器,以执行存储过程、用户定义的函数 (udf) 和模板。
通过使用所包括的用于 sql server 实用程序的 iis 虚拟目录管理,也可以设置 web 服务。一旦 web 服务虚拟目录设置完毕,就可以将存储程序和模板添加到站点。然后,客户端就可以通过 http 之上的 soap 协议来访问这些服务。
sql server 2005 现在包括对服务器中的 web 服务的本机支持。然而,只有 sqlxml 支持通过 web 服务访问 xml 模板。另外,可以在不同于数据库服务器的服务器上设置 sqlxml,创建远离数据库的单独中间层盒子。
要获得更多关于 sqlxml web 服务的细节,请访问 web services (soap) support in sqlxml。
.net 框架 2.0 中的 xquery为了在 sql server 2005 中补充引入 xquery,在 visual studio 2005 beta 的 .net 框架 v2.0 版中,system.xml.query 命名空间内置了一个中间层 xquery 处理器。在这一部分中,我们说明该处理器如何提供查询和聚合完全不同的数据源的能力,例如文件和关系数据存储 sql server 数据库。
|||简单的说,下面的代码示例显示了一个查询,用于选择书店中所有 genre 属性值为 autobiography 的书,并且将这些书的标题作为一个新的书店写出。执行查询的称为“books.xml”的本地文件被加载,而将结果写入另一个称为“output.xml”的本地文件。
using (xmlwriter writer = xmlwriter.create("output.xml"))
{
xquerycommand xq = new xquerycommand();
string query =
"<bookstore>" +
"{ for $s in /bookstore/book " +
"where $s/@genre='autobiography' " +
"return $s/title }" +
"</bookstore>";
xq.compile(query);
xq.execute("books.xml", new xmlurlresolver(), writer);
}
查询表达式如下:
<bookstore>
{for $s in /bookstore/book
where $s/@genre='autobiography'
return $s/title}
</bookstore>
xquerycommand 类是 xquery 处理器。首先由 compile 方法编译查询表达式,该方法对值进行类型检查,并且生成一个可执行文件。execute 方法执行接受 books.xml 文档作为输入的查询。
在 sql server(具有将 t-sql 语句内嵌到 xquery 表达式的功能)中,xquerycommand 类还能够对关系表中的数据进行查询。事实上,这使得能够将两个不同的查询语言之间的集成运用于不同的域,并且还补充了反向 sql server 2005,其中,t-sql 语句内嵌到 xquery 语句。下面的代码示例显示了一个查询,用于从样本 northwind 数据库中选择所有的顾客。
商业源码热门下载www.html.org.cn
|||declare namespace sql='http://schemas.microsoft.com/framework/2003/xml/sql';
<customers>{
$for $customer in sql:query("select * from customers", "conn")/*
return customer
}</customers>
sql:query 方法使您能够对连接进行 t-sql 查询,其结果以与 xquery doc() 函数完全相同的风格作为 xml 文档返回。如果结果是由关系类型组成的,则在客户端作为有效流转换成 xml。如果 sql 查询的结果已经是 xml,例如 for xml 查询或 xml 数据类型的查询,则使用该查询的结果。如果没有返回结果,像在大多数 t-sql dml 语句的情况下,这解释为空文档,它是有效的。来自此 xquery 的输出如下所示,它列出了用 customers 元素包装的顾客表中所有的顾客。在结果中自动为表中的每一行创建行元素。
<customers>
<row>
<customerid>alfki</customerid>
<companyname>alfreds futterkiste</companyname>
<contactname>maria anders</contactname>
<contacttitle>sales representative</contacttitle>
<address>obere str. 57</address>
<city>berlin</city>
<postalcode>12209</postalcode>
<country>germany</country>
<phone>030-0074321</phone>
<fax>030-0076545</fax>
</row>
<row>
<customerid>anatr</customerid>
<companyname>ana trujillo emparedados y helados</companyname>
<contactname>ana trujillo</contactname>
<contacttitle>owner</contacttitle>
<address>avda. de la constitucion 2222</address
<city>mexico d.f.</city
<postalcode>05021</postalcode>
<country>mexico</country>
<phone>(5) 555-4729</phone>
<fax>(5) 555-3745</fax>
</row>
...
</customers>
为了通过 sql server 执行此查询,需要使用下面的代码。
static string connectionstring = "database=northwind;data source=localhost;integrated security=sspi";
using (sqlconnection connection = new sqlconnection(connectionstring))
{
xmldatasourceresolver resolver = new xmldatasourceresolver();
resolver.add("conn", connection);
xquerycommand xq = new xquerycommand();
streamreader reader = new streamreader("query.xml");
xq.compile(reader);
xmlwritersettings settings = new xmlwritersettings();
settings.indent = true;
settings.conformancelevel = conformancelevel.auto;
using (xmlwriter writer = xmlwriter.create("output.xml", settings))
{
try
{
connection.open();
xq.execute(resolver, writer);
}
catch (exception e)
{
console.out.writeline(e.message);
console.out.writeline(e.innerexception.message);
}
}
}
这里,xmldatasourceresolver 类提供使数据库连接与 sql:query 调用内可以使用的名称相关联的角色。首先从名为 query.xml 的本地文件中读取该查询,再进行编译,然后创建 xmlwriter 来写入结果。需要注意 xmlwriter 中使用的 conformancelevel.auto 设置,它自动检测创建片段还是创建文档,这是必要的,因为可以借此构造结果中的元素,xquery 能够生成这两者。在执行查询之前,向数据库打开连接,然后执行查询,并将结果写入文件。
新闻热点
疑难解答