2

我正在尝试使用带有查询和值函数的 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

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

4

1 回答 1

3

Aliteral是 a 的反义词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'

路径似乎没有等价物。

于 2012-03-21T13:48:31.753 回答