SQL 使用 OpenXML 检索多个元素
SQL Using OpenXML to retrieve multiple Elements
我正在查询使用 OpenXML 来检索 XML 中主题元素之间的上限元素 我不想要支持元素之间的上限。该查询非常适合检索一个值,但当存在多个元素节点时会失败。
<First>
<Test id="83847">
<subject>
<cap>15</cap>
<cap>25</cap>
<cap>100</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
<Test id="83848">
<subject>
<cap>150</cap>
<cap>2</cap>
<cap>10</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
</First>
CREATE Table #XmlTemp(XmlField Xml);
Set Nocount On;
Insert Into #XmlTemp(XmlField)
Select '<First>
<Test id="83847">
<subject>
<cap>15</cap>
<cap>25</cap>
<cap>100</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
<Test id="83848">
<subject>
<cap>150</cap>
<cap>2</cap>
<cap>10</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
</First>'As XmlField;
Declare @xmlData Xml;
Select @xmlData = XmlField From #XmlTemp;
Declare @document int;
Exec sp_xml_preparedocument @document Output, @xmlData, NULL;
SELECT ID,Cap FROM(
SELECT ID,Cap FROM OpenXml(@document,'./First/Test', 0) With (ID varchar(max)'./@id', Cap Varchar(max) './subject/cap')) alias
drop table #xmltemp
由于涉及测试,将查询更改为更多地使用 .nodes 方法会相当耗时,因此我希望它尽可能保持打开状态XML。
我只想检索 ID,然后检索多个 cap 元素值。
感谢您的宝贵时间。
我不明白为什么使用 .nodes 的查询很复杂。刚刚
SELECT t.n.value('(/First/Test/@id)[1]', 'int') id
, t.n.value('(.)[1]', 'int') cap
from @xmlData.nodes('./First/Test/subject/cap') t(n);
和 OpenXML 版本
SELECT ID,Cap FROM(
SELECT ID,Cap
FROM OpenXml(@document,'./First/Test/subject/cap', 0)
With (ID varchar(max) '/First/Test/@id'
, Cap Varchar(max) '.')) alias
已编辑问题的版本
SELECT ID,Cap FROM(
SELECT ID,Cap
FROM OpenXml(@document,'/First/Test/subject/cap', 0)
With (ID varchar(max) '../../@id'
, Cap Varchar(max) '.')) alias
它 returns 只有 subject/cap
和 @id
的正确 parent:
ID Cap
1 83847 15
2 83847 25
3 83847 100
4 83848 150
5 83848 2
6 83848 10
您的 XML 是双重嵌套的。 <First>
中有 1:n
个元素,<First>
中有 1:n
个元素,<subject>
.
中有 <cap>
个元素
正确的查询方式是进入XML strict forward:
CREATE Table #XmlTemp(XmlField Xml);
Set Nocount On;
Insert Into #XmlTemp(XmlField)
Select '<First>
<Test id="83847">
<subject>
<cap>15</cap>
<cap>25</cap>
<cap>100</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
<Test id="83848">
<subject>
<cap>150</cap>
<cap>2</cap>
<cap>10</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
</First>'As XmlField;
--查询将使用 .nodes()
获取所有 <Test>
元素并再次使用 .nodes()
获取相关的 <cap>
元素:
SELECT t.value('@id', 'int') id
,c.value('text()[1]', 'int') cap
from #XmlTemp AS tbl
CROSS APPLY tbl.XmlField.nodes('/First/Test') AS A(t)
CROSS APPLY A.t.nodes('subject/cap') AS B(c);
GO
DROP TABLE #XmlTemp;
我正在查询使用 OpenXML 来检索 XML 中主题元素之间的上限元素 我不想要支持元素之间的上限。该查询非常适合检索一个值,但当存在多个元素节点时会失败。
<First>
<Test id="83847">
<subject>
<cap>15</cap>
<cap>25</cap>
<cap>100</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
<Test id="83848">
<subject>
<cap>150</cap>
<cap>2</cap>
<cap>10</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
</First>
CREATE Table #XmlTemp(XmlField Xml);
Set Nocount On;
Insert Into #XmlTemp(XmlField)
Select '<First>
<Test id="83847">
<subject>
<cap>15</cap>
<cap>25</cap>
<cap>100</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
<Test id="83848">
<subject>
<cap>150</cap>
<cap>2</cap>
<cap>10</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
</First>'As XmlField;
Declare @xmlData Xml;
Select @xmlData = XmlField From #XmlTemp;
Declare @document int;
Exec sp_xml_preparedocument @document Output, @xmlData, NULL;
SELECT ID,Cap FROM(
SELECT ID,Cap FROM OpenXml(@document,'./First/Test', 0) With (ID varchar(max)'./@id', Cap Varchar(max) './subject/cap')) alias
drop table #xmltemp
由于涉及测试,将查询更改为更多地使用 .nodes 方法会相当耗时,因此我希望它尽可能保持打开状态XML。 我只想检索 ID,然后检索多个 cap 元素值。
感谢您的宝贵时间。
我不明白为什么使用 .nodes 的查询很复杂。刚刚
SELECT t.n.value('(/First/Test/@id)[1]', 'int') id
, t.n.value('(.)[1]', 'int') cap
from @xmlData.nodes('./First/Test/subject/cap') t(n);
和 OpenXML 版本
SELECT ID,Cap FROM(
SELECT ID,Cap
FROM OpenXml(@document,'./First/Test/subject/cap', 0)
With (ID varchar(max) '/First/Test/@id'
, Cap Varchar(max) '.')) alias
已编辑问题的版本
SELECT ID,Cap FROM(
SELECT ID,Cap
FROM OpenXml(@document,'/First/Test/subject/cap', 0)
With (ID varchar(max) '../../@id'
, Cap Varchar(max) '.')) alias
它 returns 只有 subject/cap
和 @id
的正确 parent:
ID Cap
1 83847 15
2 83847 25
3 83847 100
4 83848 150
5 83848 2
6 83848 10
您的 XML 是双重嵌套的。 <First>
中有 1:n
个元素,<First>
中有 1:n
个元素,<subject>
.
<cap>
个元素
正确的查询方式是进入XML strict forward:
CREATE Table #XmlTemp(XmlField Xml);
Set Nocount On;
Insert Into #XmlTemp(XmlField)
Select '<First>
<Test id="83847">
<subject>
<cap>15</cap>
<cap>25</cap>
<cap>100</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
<Test id="83848">
<subject>
<cap>150</cap>
<cap>2</cap>
<cap>10</cap>
</subject>
<support>
<cap>9</cap>
</support>
</Test>
</First>'As XmlField;
--查询将使用 .nodes()
获取所有 <Test>
元素并再次使用 .nodes()
获取相关的 <cap>
元素:
SELECT t.value('@id', 'int') id
,c.value('text()[1]', 'int') cap
from #XmlTemp AS tbl
CROSS APPLY tbl.XmlField.nodes('/First/Test') AS A(t)
CROSS APPLY A.t.nodes('subject/cap') AS B(c);
GO
DROP TABLE #XmlTemp;