我正在尝试使用查询和值函数查询带有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
注意查询路径如何“向上移动”到变量。我会继续调查..
答案 0 :(得分:3)
literal
与variable
相反。该消息意味着您无法将变量作为第一个参数传递给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'
似乎没有相应的路径。