如何不使用动态SQL,在SQL的.query()中用变量作XQuery表达式
问题解答
直接说结论:不使用动态SQL的话,没法直接把完整的XQuery表达式字符串当SQL变量传入.query()方法执行。因为sql:variable()只能在XQuery里引用SQL变量的值,不能动态解析整个XQuery语句。
不过如果你的需求只是动态指定XML的查询路径(就像示例里的XPath路径),可以用XQuery的路径构造语法结合sql:variable()绕一下,具体方案看下面:
针对路径查询的解决办法
拿你的示例来说,如果只是动态传XPath路径,可以这么写:
DECLARE @xml xml = N'<?xml version="1.0" encoding="utf-16"?> <Table> <Row> <Column>123</Column> </Row> </Table>' DECLARE @xpath varchar(50) = 'Table/Row' -- 这里可以去掉开头的//,或者调整写法 -- 从根节点开始拼接动态路径 SELECT @xml.query('/' + sql:variable("@xpath"))
要是需要支持//这种任意层级匹配的路径,比如匹配所有层级的Row节点,可以用local-name()来实现:
DECLARE @xml xml = N'<?xml version="1.0" encoding="utf-16"?> <Table> <Row> <Column>123</Column> </Row> </Table>' DECLARE @nodeName varchar(50) = 'Row' -- 匹配任意位置的Row节点 SELECT @xml.query('//*[local-name() = sql:variable("@nodeName")]')
注意事项
- 上面的方法只适用于简单的路径查询,如果你的变量里是复杂的XQuery表达式(比如带条件判断、函数调用之类的),不用动态SQL的话搞不定,因为SQL Server的XQuery引擎不支持动态执行字符串形式的XQuery。
- 要是必须支持复杂的动态XQuery,那就只能用动态SQL了,给个参考示例(注意防范SQL注入):
DECLARE @xml xml = N'<?xml version="1.0" encoding="utf-16"?> <Table> <Row> <Column>123</Column> </Row> </Table>' DECLARE @string varchar(50) = '//Table/Row' DECLARE @sql nvarchar(max) = N'SELECT @xml.query(''' + @string + ''')' EXEC sp_executesql @sql, N'@xml xml', @xml
内容的提问来源于stack exchange,提问作者Leah
相关产品推荐
相关产品推荐

