如何在XQuery中使用参数?

时间:2019-06-11 13:53:39

标签: sql sql-server xml xquery-sql

我正在尝试使用@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

3 个答案:

答案 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)')
  1. 对于更复杂的查询,您可能需要使用动态SQL构建动态XQuery。