使用sp_xml_preparedocument處理XML文檔的方法
有時(shí)會(huì)在存儲(chǔ)過(guò)程中處理一些XML格式的數(shù)據(jù),所以會(huì)用到sp_xml_preparedocument,他可以將XML數(shù)據(jù)進(jìn)行讀取,然后使用 MSXML 分析器 (Msxmlsql.dll) 對(duì)其進(jìn)行分析。我們就可以很容易的在存儲(chǔ)過(guò)程中得到XML中我們想要的數(shù)據(jù)。下面的代碼就是使用sp_xml_preparedocument讀取XML:
DECLARE @hdoc int
DECLARE @doc varchar(1000)
SET @doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
<Order CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00">
<OrderDetail OrderID="10248" ProductID="11" Quantity="12"/>
<OrderDetail OrderID="10248" ProductID="42" Quantity="10"/>
</Order>
</Customer>
<Customer CustomerID="LILAS" ContactName="Carlos Gonzlez">
<Order CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00">
<OrderDetail OrderID="10283" ProductID="72" Quantity="3"/>
</Order>
</Customer>
</ROOT>'
EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc
上面只是讀取了XML,要想獲取XML數(shù)據(jù)還需要使用OPENXML,代碼如下:
SELECT *
FROM openxml(@hdoc,'/ROOT/Customer',1)
WITH (CustomerID VARCHAR(40),ContactName VARCHAR(40))
OPENXML有三個(gè)參數(shù):
第一個(gè)是sp_xml_preparedocument讀取是的OUTPUT參數(shù),在本示例中就是@hdoc;
第二個(gè)是一個(gè)XPath表達(dá)式,用來(lái)獲取指定位置的數(shù)據(jù);
第三個(gè)是一個(gè)可選項(xiàng),用來(lái)表示獲取的方式,有0,1,2,8四種取值,詳細(xì)解釋請(qǐng)看
FROM后面的WITH也是可選的,用來(lái)指定獲取哪些數(shù)據(jù)字段,上面代碼中只取了CustomerID和ContactName。上面的查詢(xún)結(jié)果如下:
CustomerID ContactName
—————————————- —————————————-
VINET Paul Henriot
LILAS Carlos Gonzlez
如果不指定WITH子句,查詢(xún)出來(lái)的是一個(gè)默認(rèn)的表結(jié)構(gòu),如下:
表格列的解釋說(shuō)明:
| 列名 | 數(shù)據(jù)類(lèi)型 | 說(shuō)明 |
|---|---|---|
| id | bigint | 文檔節(jié)點(diǎn)的唯一 ID。
根元素的 ID 值為 0。保留負(fù) ID 值。 |
| parentid | bigint | 標(biāo)識(shí)節(jié)點(diǎn)的父節(jié)點(diǎn)。此 ID 標(biāo)識(shí)的父節(jié)點(diǎn)不一定是父元素。具體情況取決于此 ID 所標(biāo)識(shí)節(jié)點(diǎn)的子節(jié)點(diǎn)的節(jié)點(diǎn)類(lèi)型。例如,如果節(jié)點(diǎn)為文本節(jié)點(diǎn),則其父節(jié)點(diǎn)可能是一個(gè)屬性節(jié)點(diǎn)。
如果節(jié)點(diǎn)位于 XML 文檔的頂層,則其 ParentID 為 NULL。 |
| 節(jié)點(diǎn)類(lèi)型 | int | 標(biāo)識(shí)節(jié)點(diǎn)類(lèi)型,是對(duì)應(yīng)于 XML 對(duì)象模型 (DOM) 節(jié)點(diǎn)類(lèi)型編號(hào)的一個(gè)整數(shù)。
下列值是可以顯示在此列中以指明節(jié)點(diǎn)類(lèi)型的值: 1 = 元素節(jié)點(diǎn) 2 = 屬性節(jié)點(diǎn) 3 = 文本節(jié)點(diǎn) 4 = CDATA 部分節(jié)點(diǎn) 5 = 實(shí)體引用節(jié)點(diǎn) 6 = 實(shí)體節(jié)點(diǎn) 7 = 處理指令節(jié)點(diǎn) 8 = 注釋節(jié)點(diǎn) 9 = 文檔節(jié)點(diǎn) 10 = 文檔類(lèi)型節(jié)點(diǎn) 11 = 文檔片段節(jié)點(diǎn) 12 = 表示法節(jié)點(diǎn) 有關(guān)詳細(xì)信息,請(qǐng)參閱 Microsoft XML (MSXML) SDK 中的“節(jié)點(diǎn)類(lèi)型屬性”主題。 |
| localname | nvarchar(max) | 提供元素或?qū)傩缘谋镜孛Q(chēng)。如果 DOM 對(duì)象沒(méi)有名稱(chēng),則為 NULL。 |
| prefix | nvarchar(max) | 節(jié)點(diǎn)名稱(chēng)的命名空間前綴。 |
| namespaceuri | nvarchar(max) | 節(jié)點(diǎn)的命名空間 URI。如果值是 NULL,則命名空間不存在。 |
| datatype | nvarchar(max) | 元素或?qū)傩孕械膶?shí)際數(shù)據(jù)類(lèi)型,否則是 NULL。數(shù)據(jù)類(lèi)型是從內(nèi)聯(lián) DTD 中或從內(nèi)聯(lián)架構(gòu)中推斷得出。 |
| prev | bigint | 前一個(gè)同級(jí)元素的 XML ID。如果前面沒(méi)有同級(jí)元素,則為 NULL。 |
| text | ntext | 包含文本形式的屬性值或元素內(nèi)容。如果邊緣表項(xiàng)不需要值則為 NULL。 |
在WITH子句中,我們還可以通過(guò)設(shè)置來(lái)獲取父級(jí)元素的屬性值:
DECLARE @hdoc int
DECLARE @doc varchar(1000)
SET @doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
<Order OrderID="10248" CustomerID="VINET" EmployeeID="5"
OrderDate="1996-07-04T00:00:00">
<OrderDetail ProductID="11" Quantity="12"/>
<OrderDetail ProductID="42" Quantity="10"/>
</Order>
</Customer>
<Customer CustomerID="LILAS" ContactName="Carlos Gonzlez">
<Order OrderID="10283" CustomerID="LILAS" EmployeeID="3"
OrderDate="1996-08-16T00:00:00">
<OrderDetail ProductID="72" Quantity="3"/>
</Order>
</Customer>
</ROOT>'
EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc
SELECT *
FROM OPENXML (@hdoc, '/ROOT/Customer/Order/OrderDetail',2)
WITH (OrderID int '../@OrderID',
CustomerID varchar(10) '../@CustomerID',
OrderDate datetime '../@OrderDate',
ProdID int '@ProductID',
Qty int '@Quantity')
查詢(xún)的結(jié)果為:
OrderID CustomerID OrderDate ProdID Qty
———– ———- ———————– ———– ———–
10248 VINET 1996-07-04 00:00:00.000 11 12
10248 VINET 1996-07-04 00:00:00.000 42 10
10283 LILAS 1996-08-16 00:00:00.000 72 3
有時(shí)候XML中的數(shù)據(jù)并不是以屬性的方式存在,而是直接放在節(jié)點(diǎn)中,如下:
DECLARE @doc varchar(1000)
SET @doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
<Order>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<EmployeeID>5</EmployeeID>
<OrderDate>1996-07-04T00:00:00</OrderDate>
</Order>
</Customer>
</ROOT>'
此時(shí)要獲Order節(jié)點(diǎn)下的各項(xiàng)的值,可以用下面方法:
DECLARE @hdoc int
DECLARE @doc varchar(1000)
SET @doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
<Order>
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<EmployeeID>5</EmployeeID>
<OrderDate>1996-07-04T00:00:00</OrderDate>
</Order>
</Customer>
</ROOT>'
EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc
SELECT *
FROM OPENXML (@hdoc, '/ROOT/Customer/Order',1)
WITH (OrderID int 'OrderID',
CustomerID varchar(10) 'CustomerID',
EmployeeID int 'EmployeeID',
OrderDate datetime 'OrderDate')
查詢(xún)結(jié)果如下:
OrderID CustomerID EmployeeID OrderDate
———– ———- ———– ———————–
10248 VINET 5 1996-07-04 00:00:00.000
可以看出是取屬性值還是取節(jié)點(diǎn)的文本的值區(qū)別在于WITH子句的第三個(gè)參數(shù)是否有@符號(hào)
相關(guān)文章
SQL Server復(fù)制功能要避開(kāi)缺陷的干擾小結(jié)
SQL Server具有強(qiáng)大的復(fù)制功能,除了將數(shù)據(jù)和數(shù)據(jù)庫(kù)對(duì)象從一個(gè)數(shù)據(jù)庫(kù)復(fù)制并準(zhǔn)確分發(fā)的另一個(gè)數(shù)據(jù)庫(kù)中,還要實(shí)行數(shù)據(jù)庫(kù)之間的同步。2011-03-03
sql分類(lèi)匯總及Select的自增長(zhǎng)腳本
對(duì)錯(cuò)誤信息進(jìn)行分類(lèi)匯總,并實(shí)現(xiàn)錯(cuò)誤數(shù)據(jù)的自增長(zhǎng)編號(hào)2012-07-07
SQLSERVER2022創(chuàng)建用戶(hù)的圖文教程
用戶(hù)是數(shù)據(jù)庫(kù)中的實(shí)體,用于控制對(duì)數(shù)據(jù)庫(kù)對(duì)象的訪問(wèn)權(quán)限,本文主要介紹了SQLSERVER2022創(chuàng)建用戶(hù)的圖文教程,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04
MSSQL報(bào)錯(cuò):參數(shù)數(shù)據(jù)類(lèi)型 text 對(duì)于 replace 函數(shù)的參數(shù) 1 無(wú)效的解決辦法
在sql中使用replace函數(shù)可以替換某個(gè)字段中的一些內(nèi)容,但是如果字段是text類(lèi)型那么使用replace函數(shù)就會(huì)報(bào)“參數(shù)數(shù)據(jù)類(lèi)型text 對(duì)于replace 函數(shù)的參數(shù)1 無(wú)效?!?,這個(gè)錯(cuò)誤說(shuō)明對(duì)text或ntext類(lèi)型的數(shù)據(jù)在查詢(xún)中不能進(jìn)行字符串操作2014-03-03
SqlServer實(shí)現(xiàn)類(lèi)似Oracle的before觸發(fā)器示例
本節(jié)主要介紹了SqlServer如何實(shí)現(xiàn)類(lèi)似Oracle的before觸發(fā)器,需要的朋友可以參考下2014-08-08
SQLSERVER的非聚集索引結(jié)構(gòu)深度理解
非聚集索引也是堆結(jié)構(gòu)?其實(shí)SQLSERVER有幾種頁(yè)面類(lèi)型(數(shù)據(jù)都使用一頁(yè)一頁(yè)來(lái)存儲(chǔ),就像Windows的內(nèi)存也是使用頁(yè)面來(lái)組織的)感興趣的朋友可以了解下,希望本文可以增加你們對(duì)非聚集索引結(jié)構(gòu)的理解2013-01-01
Sqlserver中char,nchar,varchar與Nvarchar的區(qū)別分析
Sqlserver中char,nchar,varchar與Nvarchar的區(qū)別分析,使用sqlserver的朋友可以參考下。2011-08-08


