【问题标题】:Stored procedure parameter with XML query in MSSQL gives "argument must be string literal"MSSQL 中带有 XML 查询的存储过程参数给出“参数必须是字符串文字”
【发布时间】:2012-03-21 13:46:55
【问题描述】:

我正在尝试使用带有查询和值函数的 xml 数据列查询表。使用常规字符串文字时一切正常,但如果我将它放在存储过程中并尝试使用变量,它就不起作用了。

我想我没有使用正确的数据类型,但经过一番搜索后,我无法弄清楚查询函数想要什么数据类型。

示例: 表包含

| Id | xmldata                         |
| 1  | <data><node>value</node></data> |

现在,使用选择查询

select id
from table
where xmldata.query('/data/node').value('.', 'VARCHAR(50)') = 'value'

得到我想要的数据。但是,如果我在存储过程中使用它并使用参数@xpath varchar(100) 并将其作为xmldata.query(@xpath) 传递给查询方法 我得到了错误

The argument 1 of the xml data type method "query" must be a string literal.

我猜 varchar(100) 不正确,但是我可以使用什么数据类型来让 MSSQL 开心?


更新: 可以,然后呢。显然,您不能“像那样”将参数传递给查询方法,但是可以将 sql:variable 与 local-name 结合使用来解决其中的一部分问题。因此,例如,这将起作用

declare @xpath VarChar(100)
set @xpath='node'
select objectData.query('/data/*[local-name() = sql:variable("@xpath")]')
                 .value('.', 'varchar(100)') as xmldata
from table

并且在列 xmldata 中选择了值。但是(!)它要求根节点是查询函数中的第一个值。以下将工作

declare @xpath VarChar(100)
set @xpath='/data/node'
select objectData.query('*[local-name() = sql:variable("@xpath")]')
                 .value('.', 'varchar(100)') as xmldata
from table

注意查询路径是如何“上移”到变量的。我会继续我的调查..

【问题讨论】:

  • 据我所知,无法用变量替换整个 XPath 表达式(动态 SQL 除外)。您可以像您一样使用local-name() 将节点名称与变量进行比较。如果您不关心根节点名称是什么,您可以使用 //*[local-name() = sql:variable("@xpath")] 对匹配 @xpath 的所有节点进行深度搜索,无论它们位于 XML 中的什么位置。
  • @MikaelEriksson:哦,好吧.. 我不认为双重 // 有效,但感谢您的提示。我想我会使用那个或不使用参数..
  • @JeremyCaney 这个问题是8 年前提出的。我当时从事的项目不再是我维护的东西。如果您阅读了建议副本中的答案,那么这些解决方案已在此线程中提到,因此不应成为此处所问问题的答案。
  • @Patrick:我很抱歉;我忘记了自动生成的评论,这在这里完全是荒谬的。我的目标是帮助整合类似的问题,因为现在,有很多关于同一主题的问题。我选择了另一个作为“规范”,因为它更关注核心问题,因此最有可能在未来帮助遇到类似问题的人。
  • 啊哈,我没有意识到评论是由于投票结果接近,对此感到抱歉。无论哪种方式,即使问题是相关的,这也是询问如何将查询路径值参数化作为用户输入,而另一个 IIRC 只是如何使用变量。您可以发布带有指向另一个问题的链接的评论,但它会显示在右侧的“链接问题”列表中。

标签: sql sql-server-2008 xquery sqlxml sqlparameter


【解决方案1】:

literalvariable 相反。该消息意味着您不能将变量作为第一个参数传递给query

一种方法是动态 SQL:

declare @sql varchar(max)
set @sql = 'select id from table where xmldata.query(''' + @path + 
    ''').value(''.'', ''VARCHAR(50)'') = ''value'''
exec @sql

如您所见,动态 SQL 不会产生非常可读的代码。我当然会研究替代方案。

编辑:您对 local-name() 的建议适用于节点名称。

declare @nodename varchar(max)
set @nodename = 'node'
...
where   xmldata.query('//*[local-name()=sql:variable("@nodename")]')
            .value('.', 'varchar(50)') = 'value'

似乎没有路径的等价物。

【讨论】:

  • 嗯……好吧。所以最简单的方法是使用“静态”xpaths而不使用变量? :)
  • 等一下……看来你可以reference SQL variables in XPath
  • 是的,我发现stackoverflow.com/questions/5965000/… 似乎引用了这个。仅仅使用sql-variable 是行不通的,但是看起来很有趣的*[local-name(.)= 它得到了解决..
  • 酷,是的,我认为它只允许您获取变量的值。也许您可以发布您的解决方案作为答案
  • 是的,我正在调查。目前它不起作用:P 我会回复你
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 2020-05-05
  • 2017-05-06
  • 2019-11-04
  • 1970-01-01
  • 2022-08-21
相关资源
最近更新 更多