在XML字段上使用.value()
时,是否可以使用变量来定义整个XQuery路径?
使用[local-name()=sql:variable("@FilterA")]
,我可以定义过滤器我想要作为一对变量应用,但是我无法获得整个XQuery路径的有效语法。< / p>
示例
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
我知道将整个查询转换为字符串和“EXEC” - 它应该可以工作,但这可能不适合我想要应用它的更大的情况。
修改
在阅读有关XY问题后,这个问题应改为:
“有没有办法使用格式SomeNode=SomeValue
的参数来过滤XML列?”
答案 0 :(得分:2)
正如所指出的,除了动态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: - )
答案 1 :(得分:1)
无法使用动态XQuery路径。 .value()方法和其他方法的路径参数被视为字符串文字,而不是变量。