SQL - 在 XML.value() 中使用变量作为整个 XQuery 路径

标签 sql xml xquery

在 XML 字段上使用 .value() 时,是否可以使用变量来定义整个 XQuery 路径?

使用 [local-name()=sql:variable("@FilterA")],我可以将要应用的过滤器定义为一对变量,但我无法获得使整个 XQuery 路径正常工作的有效语法。

示例

DECLARE @myData AS TABLE (myID INT, Parameter XML)
INSERT INTO @myData VALUES
(1, '<paramdata><Date>19/06/15</Date><term>1</term></paramdata>'),
(2, '<paramdata><Date>19/06/15</Date><term>5</term></paramdata>')

--This works as expected
SELECT * FROM @myData
WHERE Parameter.value('/paramdata/term=5','bit') = 1


--Two variables is possible
DECLARE @FilterA VARCHAR(255) = 'term'
DECLARE @FilterB VARCHAR(255) = '5'

SELECT * FROM @myData
WHERE Parameter.value('(/paramdata/*[local-name()=sql:variable("@FilterA")])[1]','int') = @FilterB

--but a single variable isn't
DECLARE @Filter1 VARCHAR(255) = '/paramdata/term=5'
SELECT * FROM @myData
WHERE Parameter.value('[local-name()=sql:variable("@Filter1")]','bit') = 1

我知道将整个查询转换为一个字符串并“执行”它应该可以工作,但这可能不适合我想应用它的较大情况。

编辑

在阅读了 XY 问题之后,这个问题应该改写为:
“有没有办法使用格式为 SomeNode=SomeValue 的参数来过滤 XML 列?”

最佳答案

正如所指出的,除了动态 sql 和 EXEC 之外,绝对不可能使用可变路径。

但是你可能会这样做:

DECLARE @myData AS TABLE (myID INT, Parameter XML)
INSERT INTO @myData VALUES
(1, '<paramdata><Date>19/06/15</Date><term>1</term></paramdata>'),
(2, '<paramdata><Date>19/06/15</Date><term>5</term></paramdata>')

DECLARE @Filter1 VARCHAR(255) = 'term=5';

WITH Splitted AS
(
    SELECT LEFT(@Filter1,CHARINDEX('=',@Filter1)-1) AS NodeName
          ,RIGHT(@Filter1,CHARINDEX('=',REVERSE(@Filter1))-1) AS SearchValue
)
SELECT md.myID
      ,md.Parameter
      ,md.Parameter.value('(/paramdata/*[local-name()=sql:column("NodeName")])[1]','nvarchar(max)')
FROM Splitted
CROSS APPLY @myData AS md

(您也可以在 WHERE 子句中使用此表达式

另一种方法可能是这样的:

DECLARE @myData AS TABLE (myID INT, Parameter XML)
INSERT INTO @myData VALUES
(1, '<paramdata><Date>19/06/15</Date><term>1</term></paramdata>'),
(2, '<paramdata><Date>19/06/15</Date><term>5</term></paramdata>')

DECLARE @Filter1 VARCHAR(255) = 'term=5';

WITH TheRightID AS
(
    SELECT md.myID
    FROM  @myData AS md     
    CROSS APPLY md.Parameter.nodes('/paramdata/*') AS A(Nd)
    WHERE Nd.value('local-name(.)','nvarchar(max)') + N'=' + Nd.value('.','nvarchar(max)')=@Filter1
)
SELECT * FROM @myData WHERE myID IN(SELECT x.myID FROM TheRightID AS x)

编辑

您甚至可以使用它来完整回答您最初的问题:

    WHERE N'/' + Nd.value('local-name(..)','nvarchar(max)') 
        + N'/' +Nd.value('local-name(.)','nvarchar(max)') 
        + N'=' + Nd.value('.','nvarchar(max)')=@Filter1

建议

但我的建议是阅读 about the XY-problem :-)

关于SQL - 在 XML.value() 中使用变量作为整个 XQuery 路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40040073/

相关文章:

sql - 根据查询插入记录(oracle、sql)

php - 用逗号分隔具有相同行数的值

javascript - 优化我的 Javascript/jQuery XML 函数

java - Android 中的微调器颜色样式

java - java中的xml解析问题

SQL Server XQuery 修改

sql - 无法连接到SQL

mysql - 按最高和最低排序

xml - 查找 xml 之间的增量差异并在 Xquery 中列出差异

sql - 如何使用 XQuery/SQL 进行解码等?