我正在尝试使用@count变量来循环XML值,但是我无法理解如何使用参数
create function sbill(@s xml)
returns varchar(max)
as begin
DECLARE @SBILLNO VARCHAR(MAX),@count int
set @count =5
while @count <> 0
Begin
select @SBILLNO= @s.value('(/Transaction/BodyData/TransBody/BillwiseData/BillAdjustment/sBillNo)[@count]','varchar(max)')
set @count=@count-1
end
returns @SBILLNO
end
答案 0 :(得分:1)
您自己的代码看起来就像您要从XML中获取多个重复的元素一样。因此,您正在使用WHILE循环以便一个接一个地读取第一个,第二个,第n个值。到目前为止正确吗?
大概您实际上是在寻找这个东西:
--create a mockup-table with two rows
DECLARE @tbl TABLE(ID INT IDENTITY, SomeXml XML);
INSERT INTO @tbl VALUES
('<a>
<b>b11</b>
<b>b12</b>
<b>b13</b>
<b>b14</b>
<b>b15</b>
</a>>')
,('<a>
<b>b21</b>
<b>b22</b>
<b>b23</b>
</a>');
-查询
SELECT b.value('text()[1]','varchar(10)')
FROM @tbl t
CROSS APPLY t.SomeXml.nodes('/a/b') A(b);
.nodes()
方法将返回一行中的每个<b>
作为派生表(表的名称为A
,列的名称为{{1 }}。您可以根据需要设置两个名称。返回的列是XML类型,并且是一个相对片段。在此列上使用b
方法来检索内容
无论如何,只要可以避免循环,就应该避免循环。您可以使用即时提示以基于集合的方式解决您自己的方法:
.value()
这将使用1到5的列表,以便使用DECLARE @count INT=5;
WITH Tally(Nmbr) AS (SELECT TOP(@count) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values)
SELECT t.ID
,Nmbr
,t.SomeXml.value('(/a/b[sql:column("Nmbr")])[1]','varchar(10)') AS Numbered_B
FROM @tbl t
CROSS JOIN Tally;
按位置读取XML元素。第二行将返回两个NULL值,因为没有第四或第五个元素。
但是您甚至可以根据sql:column()
元素的实际数量来创建即时提示,例如:
<b>
这与之前的查询类似,但是将使用1到n的列表,其中n是动态找到的。
答案 1 :(得分:0)
尝试sql:variable
https://docs.microsoft.com/en-us/sql/xquery/xquery-extension-functions-sql-variable?view=sql-server-2017
演示
declare @x xml =
'<a>
<b>123</b>
<b>456</b>
</a>'
declare @count int = 2;
select t.n.value('(/a/b)[sql:variable("@count")][1]','int')
from @x.nodes('.') t(n);
答案 2 :(得分:0)
几种方法:
1.使用sql:variable()
:
select @SBILLNO=
@s.value('(/Transaction/BodyData/TransBody/BillwiseData/BillAdjustment/sBillNo)[sql:variable("@count")]','varchar(max)')