今天我花了很长时间才开始工作,我很困惑为什么这两次执行会给出不同的结果。
假设我有以下 XML:
<Main>
<job id="1">
<Action>true</Action>
</job>
<job id="2">
<Action>false</Action>
</job>
</Main>
下面的 SQL 将为 actionvalue 给出一个
null
(我从示例 A here 得到语法):
exec sp_executesql
N'
select
j.value(''(job[@id="@jobid"])[1]/Action[1]'',''varchar(max)'') as actionvalue
from dbo.xmlstuff
cross apply content.nodes(''/Main'') a(j)
N'@jobid varchar(1)',
@jobid = '1'
虽然下面给出了实际值(在本例中为
true
)(我从这里得到了这个语法):
declare @sql nvarchar(500),
@jobid varchar(1) = '1'
set @sql =
'
select
j.value(''(job[@id="' + @jobid + '"])[1]/Action[1]'',''varchar(max)'') as actionvalue
from dbo.xmlstuff
cross apply content.nodes(''/Main'') a(j)
exec sp_executesql @sql, N'@jobid varchar(1)', @jobid=@jobid;
为什么会这样? 这显然与动态构建的字符串执行的工作方式和嵌入式参数执行的工作方式有关,但上述 2 个查询似乎应该完成同样的事情。
我试着用相同的结果制作 jobid int 和 varchar。我还尝试在顶级查询中使用更多变量,它们工作得很好。只是
job
后方括号内的那一段,似乎在使用变量方面有问题。
他们的行为不同,因为他们不一样。您的第一次尝试在引号中传递变量的名称,这意味着它被推断为文字值
"@jobid"
该参数的值。
后者尝试使用注入,那些injects一个
1
到字符串中。
然而,您在这里不需要动态 SQL。而是告诉 XQuery 您正在向它传递一个变量并且执行有效:
declare @xml xml = '<Main>
<job id="1">
<Action>true</Action>
</job>
<job id="2">
<Action>false</Action>
</job>
</Main>';
declare @jobid char(1) = '1';
select
j.value('(job[@id=sql:variable("@jobid")])[1]/Action[1]','varchar(max)') as actionvalue
from (VALUES(@XML)) X(content)
cross apply content.nodes('/Main') a(j);