四、sql server 2005 中的客戶端 xml 處理
xml 數(shù)據(jù)類型的客戶端支持.net 框架 v2.0 中的 ado.net xml 支持在 sqldatareader.getsqlxml() 方法的 system.data.sqltypes 命名空間中,xml 數(shù)據(jù)類型是作為類 sqlxml 公開(kāi)的。可以使用 sqlxml.createreader() 函數(shù)從 sqlxml 對(duì)象獲得 xmlreader。
類型化 xml 列的 xml 架構(gòu)集合的名稱由三部分組成,可以從 xml 列的元數(shù)據(jù)中獲得(通過(guò)使用 sqldatareader 對(duì)象中的 getschematable() 或 getsqlmetadata (int)),其三個(gè)部分作為三個(gè)屬性,分別表示數(shù)據(jù)庫(kù) (xmlschemacollectiondatabase)、關(guān)系架構(gòu) (xmlschemacollectionowingschema) 和 xml 架構(gòu)集合 (xmlschemacollectionname) 的名稱。
客戶端可以使用新的架構(gòu)行集 xmlschema 從服務(wù)器檢索 xml 架構(gòu)。xmlschema 行集包含 xml 架構(gòu)集合、目標(biāo)命名空間和 xml 架構(gòu)內(nèi)容本身這樣三列。
下面的示例顯示了用于對(duì) xml 數(shù)據(jù)類型進(jìn)行托管訪問(wèn)的主干代碼。
例:對(duì) xml 數(shù)據(jù)類型進(jìn)行進(jìn)程內(nèi)訪問(wèn)
下面的 c# 代碼演示了如何從進(jìn)程內(nèi)提供程序訪問(wèn) xml 數(shù)據(jù)類型。用于 sql 客戶端訪問(wèn)的代碼需要適當(dāng)?shù)馗淖冞M(jìn)程內(nèi)訪問(wèn)。
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 數(shù)據(jù)類型列
下面的代碼所顯示的 writexmldaratype() 方法使用 sql 客戶端程序提供程序來(lái)替換 xml 列中的值。用于進(jìn)程內(nèi)提供程序的代碼是相似的。
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 本機(jī)客戶端訪問(wèn) 在新的 sql 本機(jī)訪問(wèn) (sqlncli) 的 ole db 提供程序中,可以通過(guò) isequentialstream 來(lái)將 xml 數(shù)據(jù)類型列作為 unicode 字符串(dbtype_xml、dbtype_bstr、dbtype_wstr 和 dbtype_variant)或 unicode 字符串流進(jìn)行檢索。默認(rèn)為 dbtype_xml。
由三部分組成的 xml 架構(gòu)集合名稱是在由 idbschemarowset::getrowset() 返回的 columns 架構(gòu)行集的三個(gè)新列中攜帶的:ss_xml_catalogname 給出目錄的名稱;ss_xml_schemaname 給出 xml 架構(gòu)集合所駐留的關(guān)系架構(gòu)的名稱;ss_xml_schemacollectionname 給出 xml 架構(gòu)集合的名稱。這些名稱都屬于 dbtype_wstr 類型。對(duì)于非類型化的 xml 列,這些列具有 null 值。
可以對(duì) procedure_parameters 架構(gòu)行集和 icolumnrowset:getcolumnrowset() 進(jìn)行類似的改變。
要檢索 xml 架構(gòu)集合的內(nèi)容,客戶端可以通過(guò)在對(duì) xml_schema_namespace() 的調(diào)用中使用這些名稱來(lái)單獨(dú)訪問(wèn)服務(wù)器,并且返回 xml 架構(gòu)作為 xml 數(shù)據(jù)類型。另外,帶有新的 ss_xmlschema 架構(gòu)行集的 idbschemarowset 可以返回目錄的名稱、關(guān)系架構(gòu)的名稱、xml 架構(gòu)集合的名稱、目標(biāo)命名空間和 xml 架構(gòu)。
要使用 sqlncli 進(jìn)行 odbc 訪問(wèn),需要將 xml 數(shù)據(jù)類型映射到名為 sql_ss_xml 的 unicode 可變長(zhǎng)度字符數(shù)據(jù)。由三部分組成的 xml 架構(gòu)集合的名稱是通過(guò)用于 xml 列的 sqlcolattribute 作為 characterattributeptr 出現(xiàn)的。這些字段標(biāo)識(shí)符為 sql_desc_ss_xml_schema_catalog_name、sql_desc_ss_xml_schema_schema_name 和 sql_desc_ss_xml_schema_collection_name,分別用于數(shù)據(jù)庫(kù)、關(guān)系架構(gòu)和 xml 架構(gòu)集合的名稱。
用戶必須安裝 sql server 2005 版的數(shù)據(jù)庫(kù)服務(wù)器或客戶端工具才能獲取 sql 本機(jī)客戶端。在撰寫本文時(shí),還不能使用 mdac 2.8 ado 對(duì) xml 數(shù)據(jù)類型進(jìn)行 ole db 訪問(wèn)。
sqlxml — xml 和關(guān)系架構(gòu)之間的映射
可以使用 sqlxml 映射技術(shù)來(lái)創(chuàng)建關(guān)系數(shù)據(jù)的邏輯 xml 視圖。xml 視圖(也稱為“映射”或“帶注解的架構(gòu)”)是通過(guò)將特殊的注解添加到特定的 xsd 架構(gòu)中創(chuàng)建的。于是,其他的 sqlxml 技術(shù)就可以使用這種帶注解的架構(gòu),將針對(duì)邏輯 xml 視圖進(jìn)行的查詢和更新轉(zhuǎn)換成針對(duì)關(guān)系表進(jìn)行的查詢和更新:
•
當(dāng) xml 視圖與 xpath 查詢組合在一起時(shí),sqlxml 將生成 for xml 查詢來(lái)查找請(qǐng)求數(shù)據(jù),并且根據(jù)架構(gòu)的指定對(duì)其進(jìn)行構(gòu)形。
|||
•
sqlxml updategrams 表示對(duì) xml 實(shí)例進(jìn)行的更改,當(dāng)與帶注解的架構(gòu)組合在一起時(shí),將使用開(kāi)放式并發(fā)將這些更改重新保存到關(guān)系更改中,以確保更新正確的數(shù)據(jù)。
•
sqlxml bulkload 使用 xml 視圖將 xml 數(shù)據(jù)“切碎”并存放到關(guān)系表中。
有關(guān)這些主題的更多信息,請(qǐng)?jiān)L問(wèn) sqlxml documentation。
創(chuàng)建關(guān)系表的 xml 視圖要?jiǎng)?chuàng)建數(shù)據(jù)庫(kù)的 xml 視圖,需要從用于 xml 數(shù)據(jù)的 xsd 架構(gòu)開(kāi)始。數(shù)據(jù)庫(kù)表/視圖中的行將映射為該架構(gòu)中復(fù)雜類型的元素。數(shù)據(jù)庫(kù)中的列值映射為屬性或簡(jiǎn)單類型的元素。
默認(rèn)情況下,如果沒(méi)有給出顯式注解,sqlxml 就會(huì)假定復(fù)雜類型的元素將映射到表,而簡(jiǎn)單類型的元素和屬性將映射到列。只有當(dāng)元素和屬性的名稱與數(shù)據(jù)庫(kù)中表和列的名稱完全相同時(shí),這才有效。
如果元素/屬性的名稱與它映射到的表/視圖或列的名稱不同,則必須創(chuàng)建顯式映射。下面的注解用于指定 xml 文檔中的元素或?qū)傩蚤g的映射和數(shù)據(jù)庫(kù)中的表(視圖)或列之間的映射:
•
sql:relation — 將 xml 元素映射到數(shù)據(jù)庫(kù)表。
•
sql:field — 將元素或?qū)傩杂成涞綌?shù)據(jù)庫(kù)列。
通過(guò)映射關(guān)系創(chuàng)建 xml 視圖中的層次在數(shù)據(jù)庫(kù)中,表可以通過(guò)外鍵關(guān)系來(lái)關(guān)聯(lián)。在 xml 中,這些相同的關(guān)系是通過(guò)嵌套的元素層次來(lái)表示的。為了在映射中構(gòu)造正確的嵌套,必須指定關(guān)聯(lián)元素的方式。可以使用 sql:relationship 注解在映射架構(gòu)元素中建立這些關(guān)系。在這種注解中,可以指定父表和子表,以及每個(gè)表中需要用于執(zhí)行加入的列。然后,sqlxml 將利用這些信息為映射構(gòu)造正確的嵌套層次。
使用溢出存儲(chǔ)未使用的數(shù)據(jù)當(dāng) xml 數(shù)據(jù)有正規(guī)的結(jié)構(gòu)時(shí)映射是有效的。然而,在 xml 中,可能有一些數(shù)據(jù)是非結(jié)構(gòu)化的,還可能有一些數(shù)據(jù)沒(méi)有映射到特定的列。要存儲(chǔ)這種數(shù)據(jù)并隨后檢索它,可以使用 sql:overflow 注解。sql:overflow 注解指定存儲(chǔ)所有未使用數(shù)據(jù)的列以及查詢時(shí)從何處檢索數(shù)據(jù)。
|||
通過(guò)溢出列,還可以擴(kuò)展 xml,而不必將其添加到數(shù)據(jù)庫(kù)。可以在任何時(shí)候?qū)⒃睾蛯傩蕴砑拥?xml 結(jié)構(gòu),而不必在數(shù)據(jù)庫(kù)中添加列來(lái)存儲(chǔ)它們。可以將它們簡(jiǎn)單地存儲(chǔ)到溢出字段,并且在適當(dāng)?shù)臅r(shí)候?qū)ζ溥M(jìn)行檢索。
更多信息有關(guān)創(chuàng)建 xml 視圖和映射示例的詳細(xì)信息,請(qǐng)參閱 creating xml views by using annotated xsd schemas。
使用 xpath 來(lái)查詢 xml 視圖一旦創(chuàng)建好數(shù)據(jù)庫(kù)的 xml 視圖,就可以使用 xpath 查詢語(yǔ)言來(lái)查詢視圖,就好像它是實(shí)際的 xml 文檔一樣。sqlxml 支持 xpath 1.0 查詢語(yǔ)言中的一個(gè)子集。當(dāng)針對(duì)映射進(jìn)行 xpath 查詢時(shí),sqlxml 將它們組合在一起,并且創(chuàng)建發(fā)送到 sql server 的 for xml explicit 語(yǔ)句。然后檢索正確的數(shù)據(jù),并根據(jù)映射對(duì)其進(jìn)行構(gòu)形。
請(qǐng)參閱 sqlxml 文檔以獲得關(guān)于 xml 視圖中支持的 xpath 子集的詳細(xì)信息。
使用 updategrams 通過(guò) xml 視圖進(jìn)行更新可以通過(guò) xml 視圖修改(插入、更新或刪除)sql server 中的數(shù)據(jù)庫(kù),方法是針對(duì)數(shù)據(jù)庫(kù)的 xml 視圖使用 updategram。
updategram 的結(jié)構(gòu)updategram 是一個(gè) xml 文檔,帶有<sync>、<before> 和<after> 元素,這些元素構(gòu)成了 updategram 的語(yǔ)法。每個(gè)<sync> 塊包含一個(gè)或多個(gè)<before> 和<after> 塊。<before> 標(biāo)識(shí)記錄實(shí)例的現(xiàn)有狀態(tài)(也稱為“前狀態(tài)”)。<after> 標(biāo)識(shí)要更改的數(shù)據(jù)的新?tīng)顟B(tài)。updategram 是刪除、插入還是更新記錄實(shí)例取決于<before> 和<after> 塊的內(nèi)容。
插入操作當(dāng)記錄實(shí)例出現(xiàn)在<after> 塊而沒(méi)有出現(xiàn)在相應(yīng)的<before> 塊中時(shí),updategram 指示插入操作。在這種情況下,updategram 將<after> 塊中的記錄插入數(shù)據(jù)庫(kù)。
|||刪除操作
當(dāng)記錄實(shí)例出現(xiàn)在<before> 塊而沒(méi)有相應(yīng)的記錄出現(xiàn)在<after> 塊中時(shí),updategram 指示刪除操作。在這種情況下,updategram 從數(shù)據(jù)庫(kù)中刪除<before> 塊中的記錄。
如果在 updategram 中指定的元素或者匹配表中的多行或者不匹配表中的任何行,則 updategram 會(huì)返回錯(cuò)誤,并取消整個(gè)<sync> 塊。updategram 中的元素一次只能刪除一條記錄。
更新操作當(dāng)更新現(xiàn)有的數(shù)據(jù)時(shí),必須指定<before> 和<after> 塊。updategram 使用<before> 塊中指定的元素來(lái)標(biāo)識(shí)數(shù)據(jù)庫(kù)中的現(xiàn)有記錄。<after> 塊中相應(yīng)的元素指示在執(zhí)行更新操作之后記錄的外觀應(yīng)該怎樣。
<before>塊中的元素必須只與數(shù)據(jù)庫(kù)中的一個(gè)表行相匹配。如果該元素匹配多個(gè)表行或不匹配任何表行,則 updategram 都會(huì)返回錯(cuò)誤,并且取消整個(gè)<sync> 塊。
更多信息
要獲得更多關(guān)于通過(guò) xml 視圖創(chuàng)建和使用 updategram 修改數(shù)據(jù)的信息,請(qǐng)參閱 using updategrams to modify data。
通過(guò) xml 視圖大量加載 xml 數(shù)據(jù)xml bulk load 是一個(gè) com 對(duì)象,它允許您將 xml 數(shù)據(jù)加載到 sql server 表中。雖然通過(guò)使用 insert 語(yǔ)句和 openxml 函數(shù)可以將 xml 數(shù)據(jù)插入 sql server 數(shù)據(jù)庫(kù)中,但是當(dāng)需要插入大量的 xml 數(shù)據(jù)時(shí),這種大量加載實(shí)用程序提供了更高的性能。xml bulk load 解釋映射架構(gòu)并標(biāo)識(shí) xml 數(shù)據(jù)要插入的表。然后,它將 xml 數(shù)據(jù)“切碎”并存放到關(guān)系表中。
在進(jìn)行大量加載處理時(shí),由于源 xml 文檔可能很大,所以并不將整個(gè)文檔讀入內(nèi)存。相反,xml bulk load 將 xml 數(shù)據(jù)解釋為流,并且邊解釋它邊讀取它。當(dāng)該實(shí)用程序讀取數(shù)據(jù)時(shí),它標(biāo)識(shí)數(shù)據(jù)庫(kù)表,從 xml 數(shù)據(jù)源生成適當(dāng)?shù)挠涗洠缓髮⒂涗洶l(fā)送到 sql server,以供插入。
要獲得更多關(guān)于 bulk load 如何工作和使用的信息,請(qǐng)參閱 performing bulk load of xml data。
sqlxml 數(shù)據(jù)訪問(wèn)方法由于有了 sql server 2000,所以又增加了兩種訪問(wèn) sqlxml 功能的新方法:
•
sqlxml 托管類
•
sqlxml web 服務(wù)
另外,還增強(qiáng)了對(duì) sql server 的 http 訪問(wèn),以提供對(duì)模板中的 updategram 的支持。
sqlxml 托管類sqlxml 托管類公開(kāi) microsoft .net 框架內(nèi)的 sqlxml 3.0 的功能。通過(guò) sqlxml 托管類,可以編寫 c# 應(yīng)用程序從 sql server 的實(shí)例訪問(wèn) xml 數(shù)據(jù),將數(shù)據(jù)帶入 .net 框架環(huán)境,處理數(shù)據(jù),并將更新重新發(fā)送回 sql server 以應(yīng)用這些更新。
要獲得更多關(guān)于如何使用 sqlxml 托管類的細(xì)節(jié),請(qǐng)參閱 sqlxml .net support。
sqlxml web 服務(wù)sqlxml 中的 web 服務(wù)支持將 sql server 作為 web 服務(wù)公開(kāi),從而為客戶端提供 sql server 功能。可以將 soap http 請(qǐng)求發(fā)送到正在運(yùn)行 sqlxml 的服務(wù)器,以執(zhí)行存儲(chǔ)過(guò)程、用戶定義的函數(shù) (udf) 和模板。
通過(guò)使用所包括的用于 sql server 實(shí)用程序的 iis 虛擬目錄管理,也可以設(shè)置 web 服務(wù)。一旦 web 服務(wù)虛擬目錄設(shè)置完畢,就可以將存儲(chǔ)程序和模板添加到站點(diǎn)。然后,客戶端就可以通過(guò) http 之上的 soap 協(xié)議來(lái)訪問(wèn)這些服務(wù)。
sql server 2005 現(xiàn)在包括對(duì)服務(wù)器中的 web 服務(wù)的本機(jī)支持。然而,只有 sqlxml 支持通過(guò) web 服務(wù)訪問(wèn) xml 模板。另外,可以在不同于數(shù)據(jù)庫(kù)服務(wù)器的服務(wù)器上設(shè)置 sqlxml,創(chuàng)建遠(yuǎn)離數(shù)據(jù)庫(kù)的單獨(dú)中間層盒子。
要獲得更多關(guān)于 sqlxml web 服務(wù)的細(xì)節(jié),請(qǐng)?jiān)L問(wèn) web services (soap) support in sqlxml。
.net 框架 2.0 中的 xquery為了在 sql server 2005 中補(bǔ)充引入 xquery,在 visual studio 2005 beta 的 .net 框架 v2.0 版中,system.xml.query 命名空間內(nèi)置了一個(gè)中間層 xquery 處理器。在這一部分中,我們說(shuō)明該處理器如何提供查詢和聚合完全不同的數(shù)據(jù)源的能力,例如文件和關(guān)系數(shù)據(jù)存儲(chǔ) sql server 數(shù)據(jù)庫(kù)。
|||簡(jiǎn)單的說(shuō),下面的代碼示例顯示了一個(gè)查詢,用于選擇書(shū)店中所有 genre 屬性值為 autobiography 的書(shū),并且將這些書(shū)的標(biāo)題作為一個(gè)新的書(shū)店寫出。執(zhí)行查詢的稱為“books.xml”的本地文件被加載,而將結(jié)果寫入另一個(gè)稱為“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);
}查詢表達(dá)式如下:
<bookstore>
{for $s in /bookstore/book
where $s/@genre='autobiography'
return $s/title}
</bookstore>xquerycommand 類是 xquery 處理器。首先由 compile 方法編譯查詢表達(dá)式,該方法對(duì)值進(jìn)行類型檢查,并且生成一個(gè)可執(zhí)行文件。execute 方法執(zhí)行接受 books.xml 文檔作為輸入的查詢。
在 sql server(具有將 t-sql 語(yǔ)句內(nèi)嵌到 xquery 表達(dá)式的功能)中,xquerycommand 類還能夠?qū)﹃P(guān)系表中的數(shù)據(jù)進(jìn)行查詢。事實(shí)上,這使得能夠?qū)蓚€(gè)不同的查詢語(yǔ)言之間的集成運(yùn)用于不同的域,并且還補(bǔ)充了反向 sql server 2005,其中,t-sql 語(yǔ)句內(nèi)嵌到 xquery 語(yǔ)句。下面的代碼示例顯示了一個(gè)查詢,用于從樣本 northwind 數(shù)據(jù)庫(kù)中選擇所有的顧客。
商業(yè)源碼熱門下載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 方法使您能夠?qū)B接進(jìn)行 t-sql 查詢,其結(jié)果以與 xquery doc() 函數(shù)完全相同的風(fēng)格作為 xml 文檔返回。如果結(jié)果是由關(guān)系類型組成的,則在客戶端作為有效流轉(zhuǎn)換成 xml。如果 sql 查詢的結(jié)果已經(jīng)是 xml,例如 for xml 查詢或 xml 數(shù)據(jù)類型的查詢,則使用該查詢的結(jié)果。如果沒(méi)有返回結(jié)果,像在大多數(shù) t-sql dml 語(yǔ)句的情況下,這解釋為空文檔,它是有效的。來(lái)自此 xquery 的輸出如下所示,它列出了用 customers 元素包裝的顧客表中所有的顧客。在結(jié)果中自動(dòng)為表中的每一行創(chuàng)建行元素。
<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>為了通過(guò) sql server 執(zhí)行此查詢,需要使用下面的代碼。
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 類提供使數(shù)據(jù)庫(kù)連接與 sql:query 調(diào)用內(nèi)可以使用的名稱相關(guān)聯(lián)的角色。首先從名為 query.xml 的本地文件中讀取該查詢,再進(jìn)行編譯,然后創(chuàng)建 xmlwriter 來(lái)寫入結(jié)果。需要注意 xmlwriter 中使用的 conformancelevel.auto 設(shè)置,它自動(dòng)檢測(cè)創(chuàng)建片段還是創(chuàng)建文檔,這是必要的,因?yàn)榭梢越璐藰?gòu)造結(jié)果中的元素,xquery 能夠生成這兩者。在執(zhí)行查詢之前,向數(shù)據(jù)庫(kù)打開(kāi)連接,然后執(zhí)行查詢,并將結(jié)果寫入文件。
新聞熱點(diǎn)
疑難解答
圖片精選