[英]How to store data in a table using openxml with While loop in SQL for multiple XMLs
我有一個包含 3 個 XML 的臨時表:
CREATE TABLE #XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
);
go
INSERT INTO #XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT
CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM
OPENROWSET(BULK 'D:\Test\Test1.xml', SINGLE_BLOB) AS x;
INSERT INTO #XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT
CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM
OPENROWSET(BULK 'D:\Test\Test2.xml', SINGLE_BLOB) AS x;
INSERT INTO #XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT
CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM
OPENROWSET(BULK 'D:\Test\Test2.xml', SINGLE_BLOB) AS x;
go
我正在嘗試從中提取一些數據到另一個臨時表中,並且使用以下代碼成功地這樣做了:
DECLARE @XML AS XML, @hDoc as int, @SQL nvarchar(max)
SELECT @XML = XMLData
FROM #XMLwithOpenXML
SELECT @XML
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
EXEC Rm #DocNameForCapsilonFieldId
SELECT
DocTypeName = typeName, DataPointName, FieldId = FieldName, ValueData
INTO
#DocNameForCapsilonFieldId
FROM
OPENXML(@hDoc, 'documents/document/dataPoints/dataPoint/field/value')
WITH
(
typeName [varchar](256) '../../../../typeName',
DataPointName [varchar](256) '../../@name',
FieldName [varchar](256) '../@name',
ValueData [varchar](256) '../value'
) AS DocTypeName
EXEC sp_xml_removedocument @hDoc
go
但問題是它只拾取第一個 XML 並提取其數據。 我想從所有 3 個 XML 中提取數據並將其存儲在#DocNameForCapsilonFieldId
或數據庫中的任何表中。 我知道這是通過 While 循環完成的,但我真的不知道如何實現它。 有人可以幫我解決這個問題,甚至可以將其設為存儲過程嗎?
首先: FROM OPENXML
以及用於准備和刪除文檔的 SP 已過時,不應再使用(存在罕見的例外情況)。
始終嘗試使用由 XML 數據類型提供的本機 XML 方法。 即.nodes()
,用於在派生集中檢索與多行相同的重復元素,以及.value()
以獲取標量值。
這並不是一個真正的新答案,更多的是對@AlwaysLearning 答案的補充。
向后導航(父軸,在您的示例中使用多個../
)表現非常糟糕。 更好地使用.nodes()
的APPLY
級聯,在實際XPaths上越來越深入:
(DDL 和示例的學分:@AlwaysLearning 的答案)
drop table if exists #XMLwithOpenXML;
create table #XMLwithOpenXML (
XMLData xml
);
insert #XMLwithOpenXML values
(N'<documents>
<document>
<typeName>Example1</typeName>
<dataPoints>
<dataPoint name="dp11">
<field name="foo">
<value>42</value>
</field>
</dataPoint>
<dataPoint name="dp12">
<field name="bar">
<value>47</value>
</field>
</dataPoint>
</dataPoints>
</document>
</documents>'),
(N'<documents>
<document>
<typeName>Example2</typeName>
<dataPoints>
<dataPoint name="dp21">
<field name="baz">
<value>21</value>
</field>
</dataPoint>
<dataPoint name="dp22">
<field name="chaz">
<value>22</value>
</field>
</dataPoint>
</dataPoints>
</document>
</documents>');
--查詢:
SELECT A.doc.value('(typeName/text())[1]','nvarchar(max)') AS TypeName
,B.dp.value('@name','nvarchar(max)') AS DataPoint_Name
,C.fld.value('@name','nvarchar(max)') AS Field_Name
,C.fld.value('(value/text())[1]','int') AS Field_Value
FROM #XMLwithOpenXML t
CROSS APPLY XMLData.nodes('/documents/document') A(doc)
OUTER APPLY A.doc.nodes('dataPoints/dataPoint') B(dp)
OUTER APPLY B.dp.nodes('field') C(fld);
結果
TypeName DataPoint_Name Field_Name Field_Value
Example1 dp11 foo 42
Example1 dp12 bar 47
Example2 dp21 baz 21
Example2 dp22 chaz 22
您應該能夠在沒有WHILE
循環的情況下執行此操作 - 使用帶有nodes()
和value()
XML 函數的CROSS APPLY
代替,例如如下所示:
drop table if exists #DocNameForCapsilonFieldId;
create table #DocNameForCapsilonFieldId (
DocTypeName nvarchar(256),
DataPointName nvarchar(256),
FieldId nvarchar(256),
ValueData nvarchar(256)
);
drop table if exists #XMLwithOpenXML;
create table #XMLwithOpenXML (
XMLData xml
);
insert #XMLwithOpenXML values
(N'<documents>
<document>
<typeName>Example1</typeName>
<dataPoints>
<dataPoint name="dp11">
<field name="foo">
<value>42</value>
</field>
</dataPoint>
<dataPoint name="dp12">
<field name="bar">
<value>47</value>
</field>
</dataPoint>
</dataPoints>
</document>
</documents>'),
(N'<documents>
<document>
<typeName>Example2</typeName>
<dataPoints>
<dataPoint name="dp21">
<field name="baz">
<value>21</value>
</field>
</dataPoint>
<dataPoint name="dp22">
<field name="chaz">
<value>22</value>
</field>
</dataPoint>
</dataPoints>
</document>
</documents>');
insert #DocNameForCapsilonFieldId (DocTypeName, DataPointName, FieldId, ValueData)
select
x.n.value(N'../../../../typeName[1]', N'nvarchar(256)'),
x.n.value(N'../../@name[1]', N'nvarchar(256)'),
x.n.value(N'../@name[1]', N'nvarchar(256)'),
x.n.value(N'.', N'nvarchar(256)')
from #XMLwithOpenXML
cross apply XMLData.nodes(N'documents/document/dataPoints/dataPoint/field/value') x(n);
這會產生結果......
DocTypeName DataPointName FieldId ValueData
Example1 dp11 foo 42
Example1 dp12 bar 47
Example2 dp21 baz 21
Example2 dp22 chaz 22
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.