如何使用 SQL 从 XML DML 中的节点传递索引值
How to pass index value from a node in XML DML with SQL
从 SQL 服务器中的 XML DML 开始,目前还不错,但我面临着这个挑战。我需要遍历存储在 SQL 服务器中的 XML 数据中的一些已定义节点。
已经检查过这个作为参考,它提供了一个线索,但我仍然没有弄清楚如何在 XML DML Reference 中发送一个 SQL 变量作为索引。
假设以下 XML 数据:
<materials>
<est_mat>
<pos>20</pos>
<item>BOX</item>
<qty>0.004</qty>
</est_mat>
<est_mat>
<pos>30</pos>
<item>xxx-xxx-xxx01</item>
<qty>1</qty>
</est_mat>
<est_mat>
<pos>40</pos>
<item>xxx-xxx-xxx02</item>
<qty>1</qty>
</est_mat>
</materials>
所以我正在寻找的是遍历所有数量的 <est_mat>
节点并从 10 开始替换 <pos>
属性,然后下一个节点将是 20,依此类推。
到目前为止我有这个:
--starting of code
declare @cnt int = 10
declare @totalchildren varchar(300)
declare @pos int = 1
--returns the number of nodes
SET @totalchildren = (SELECT (XMLData.value('count(/materials/est_mat)', 'int'))
FROM TABLE_XMLFiles
WHERE myref = 173)
WHILE @cnt < @totalchildren
BEGIN
--PRINT @cnt
UPDATE TABLE_XMLFiles
SET XMLData.modify('replace value of (/materials/est_mat/pos[sql:variable("@pos")])[[1]] with sql:variable("@cnt")')
WHERE myref = 173
SET @cnt = @cnt + 1
SET @pos = @pos + 10
END
--end of code
错误:
XQuery [BinControl_XMLFiles.XMLData.modify()]: The target of 'replace value of' must be a non-metadata attribute or an element with simple typed content, found 'element(pos,xdt:untyped) ?'
问题是:如何发送一个 SQL 变量作为索引位置,如下所示:
SET XMLData.modify('replace value of (/materials/est_mat/pos/text())[sql:variable("@pos")]
with sql:variable("@cnt")')
因为我要替换它的值是通过使用 sql:variable("@cnt")
以这种方式发送它来工作的-已经尝试过并且可以工作,但是我仍然不知道如何通过索引上下文发送变量。
提前感谢您的关注。
为什么不忽略现有的 <pos>
元素和 re-build XML?
DECLARE @xml XML=
N'<materials>
<est_mat>
<pos>20</pos>
<item>BOX</item>
<qty>0.004</qty>
</est_mat>
<est_mat>
<pos>30</pos>
<item>xxx-xxx-xxx01</item>
<qty>1</qty>
</est_mat>
<est_mat>
<pos>40</pos>
<item>xxx-xxx-xxx02</item>
<qty>1</qty>
</est_mat>
</materials>';
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) * 10 AS pos
,em.value(N'item[1]',N'nvarchar(max)') AS item
,em.value(N'qty[1]',N'decimal(16,4)') AS qty
FROM @xml.nodes(N'/materials/est_mat') AS A(em)
FOR XML PATH('est_mat'),ROOT('materials')
更新您的follow-up问题
(请避免变色龙问题!)
您的结构可能会在两个组合步骤中被查询。一个查询挑选出所有 not called <materials>
的现有节点,然后将我上面提到的查询添加为 sub-element.
提示 XML 中合适的日期格式是 ISO8601。您的价值观 02092017
取决于文化,因此您应该避免。最好 2017-02-09
或 2017-02-09T00:00:00
(如果不是 9 月 2 日 :-))
DECLARE @xml XML=
N'<order>
<orderbook>
<date> 02092017 </date>
</orderbook>
<materials>
<est_mat>
<pos>20</pos>
<item>BOX</item>
<qty>0.004</qty>
</est_mat>
<est_mat>
<pos>30</pos>
<item>xxx-xxx-xxx01</item>
<qty>1</qty>
</est_mat>
<est_mat>
<pos>40</pos>
<item>xxx-xxx-xxx02</item>
<qty>1</qty>
</est_mat>
</materials>
</order>';
SELECT @xml.query(N'/order/*[local-name()!="materials"]') AS [*]
,(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) * 10 AS pos
,em.value(N'item[1]',N'nvarchar(max)') AS item
,em.value(N'qty[1]',N'decimal(16,4)') AS qty
FROM @xml.nodes(N'order/materials/est_mat') AS A(em)
FOR XML PATH('est_mat'),ROOT('materials'),TYPE
)
FOR XML PATH(N'order');
注意:XML的节点内部顺序可能会改变...
从 SQL 服务器中的 XML DML 开始,目前还不错,但我面临着这个挑战。我需要遍历存储在 SQL 服务器中的 XML 数据中的一些已定义节点。
已经检查过这个作为参考,它提供了一个线索,但我仍然没有弄清楚如何在 XML DML Reference 中发送一个 SQL 变量作为索引。
假设以下 XML 数据:
<materials>
<est_mat>
<pos>20</pos>
<item>BOX</item>
<qty>0.004</qty>
</est_mat>
<est_mat>
<pos>30</pos>
<item>xxx-xxx-xxx01</item>
<qty>1</qty>
</est_mat>
<est_mat>
<pos>40</pos>
<item>xxx-xxx-xxx02</item>
<qty>1</qty>
</est_mat>
</materials>
所以我正在寻找的是遍历所有数量的 <est_mat>
节点并从 10 开始替换 <pos>
属性,然后下一个节点将是 20,依此类推。
到目前为止我有这个:
--starting of code
declare @cnt int = 10
declare @totalchildren varchar(300)
declare @pos int = 1
--returns the number of nodes
SET @totalchildren = (SELECT (XMLData.value('count(/materials/est_mat)', 'int'))
FROM TABLE_XMLFiles
WHERE myref = 173)
WHILE @cnt < @totalchildren
BEGIN
--PRINT @cnt
UPDATE TABLE_XMLFiles
SET XMLData.modify('replace value of (/materials/est_mat/pos[sql:variable("@pos")])[[1]] with sql:variable("@cnt")')
WHERE myref = 173
SET @cnt = @cnt + 1
SET @pos = @pos + 10
END
--end of code
错误:
XQuery [BinControl_XMLFiles.XMLData.modify()]: The target of 'replace value of' must be a non-metadata attribute or an element with simple typed content, found 'element(pos,xdt:untyped) ?'
问题是:如何发送一个 SQL 变量作为索引位置,如下所示:
SET XMLData.modify('replace value of (/materials/est_mat/pos/text())[sql:variable("@pos")]
with sql:variable("@cnt")')
因为我要替换它的值是通过使用 sql:variable("@cnt")
以这种方式发送它来工作的-已经尝试过并且可以工作,但是我仍然不知道如何通过索引上下文发送变量。
提前感谢您的关注。
为什么不忽略现有的 <pos>
元素和 re-build XML?
DECLARE @xml XML=
N'<materials>
<est_mat>
<pos>20</pos>
<item>BOX</item>
<qty>0.004</qty>
</est_mat>
<est_mat>
<pos>30</pos>
<item>xxx-xxx-xxx01</item>
<qty>1</qty>
</est_mat>
<est_mat>
<pos>40</pos>
<item>xxx-xxx-xxx02</item>
<qty>1</qty>
</est_mat>
</materials>';
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) * 10 AS pos
,em.value(N'item[1]',N'nvarchar(max)') AS item
,em.value(N'qty[1]',N'decimal(16,4)') AS qty
FROM @xml.nodes(N'/materials/est_mat') AS A(em)
FOR XML PATH('est_mat'),ROOT('materials')
更新您的follow-up问题
(请避免变色龙问题!)
您的结构可能会在两个组合步骤中被查询。一个查询挑选出所有 not called <materials>
的现有节点,然后将我上面提到的查询添加为 sub-element.
提示 XML 中合适的日期格式是 ISO8601。您的价值观 02092017
取决于文化,因此您应该避免。最好 2017-02-09
或 2017-02-09T00:00:00
(如果不是 9 月 2 日 :-))
DECLARE @xml XML=
N'<order>
<orderbook>
<date> 02092017 </date>
</orderbook>
<materials>
<est_mat>
<pos>20</pos>
<item>BOX</item>
<qty>0.004</qty>
</est_mat>
<est_mat>
<pos>30</pos>
<item>xxx-xxx-xxx01</item>
<qty>1</qty>
</est_mat>
<est_mat>
<pos>40</pos>
<item>xxx-xxx-xxx02</item>
<qty>1</qty>
</est_mat>
</materials>
</order>';
SELECT @xml.query(N'/order/*[local-name()!="materials"]') AS [*]
,(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) * 10 AS pos
,em.value(N'item[1]',N'nvarchar(max)') AS item
,em.value(N'qty[1]',N'decimal(16,4)') AS qty
FROM @xml.nodes(N'order/materials/est_mat') AS A(em)
FOR XML PATH('est_mat'),ROOT('materials'),TYPE
)
FOR XML PATH(N'order');
注意:XML的节点内部顺序可能会改变...