我尝试使用sql:column-function创建一个使用xml.exist的查询,其中列的值应该转换为可用的XQuery序列。
这是具有静态序列的查询,这是有效的。
SELECT
FieldA
, FieldB
FROM
MyTable
WHERE
FieldC.exist('DSAuth/role[@id=("195", "267", "350")')
为了得到一个动态序列,我将使用一个表函数,返回一个带有“IDsequence”列的表,其中所有id都是一个字符串。例如'“195”,“267”,“350”'。
表函数应该只返回一行!有多行可行,但我必须将结果分组,这对性能有害。
SELECT
FieldA
, FieldB
FROM
MyTable
CROSS APPLY
dbo.MyFunc(0) AS f
WHERE
FieldC.exist('DSAuth/role[@id=sql:column("f.IDsequence")]')
有没有办法从sql:column(“f.IDsequence”)获取XQuery的可用序列?
感谢帮助。
编辑:
性能问题是FieldB(以及更多字段)是一个xml列,所以我必须将其转换为group by。
SELECT
FieldA
, CAST(CAST(FieldB AS nvarchar(max)) AS xml) AS FieldB
FROM
MyTable
CROSS APPLY
dbo.MyFunc(0) AS f
WHERE
FieldC.exist('DSAuth/role[@id=sql:column("f.IDsequence")]')
GROUP BY
FieldA
, CAST(FieldB AS nvarchar(max))
我不知道这是否是最简单的方法,但您可能会尝试将列表包含在XML中并在谓词中使用它,如下所示:
- 一个显示原则的样机表
DECLARE @tbl TABLE(TheXml XML)
INSERT INTO @tbl VALUES
(
N'<root>
<a>1</a>
<a>2</a>
</root>'
)
,(
N'<root>
<a>1</a>
</root>'
)
,(
N'<root>
<a>3</a>
<a>4</a>
</root>'
);
- 这很容易:只有一个值
SELECT * FROM @tbl WHERE TheXml.exist('/root/a[. cast as xs:int?=1]')=1;
- 这是你的顺序。
- 但是你不能用sql:column()
或sql:variable()
介绍价值表。
SELECT * FROM @tbl WHERE TheXml.exist('/root/a[. cast as xs:int?=(2,3)]')=1;
- 但是你可以像在这个cte中那样将值添加到XML中
DECLARE @values TABLE(val INT);
INSERT INTO @values VALUES(2),(3);
WITH cte(NewXml) AS
(
SELECT (SELECT (SELECT val AS [@val] FROM @values FOR XML PATH('values'),TYPE)
,TheXml AS [*]
FOR XML PATH(''),TYPE
)
FROM @tbl t
)
SELECT NewXml.query('/root') TheXml
FROM cte
WHERE NewXml.exist('/root/a[. cast as xs:int?=/values/@val]')=1;
中间XML看起来像这样:
<values val="2" />
<values val="3" />
<root>
<a>1</a>
<a>2</a>
</root>
最终的.query('/root')
将返回先前的XML不变。
同样适用于字符串基础的介绍,如下所示:
WITH cte(NewXml) AS
(
SELECT (SELECT CAST(N'<values val="2" /><values val="3" />' AS XML)
,TheXml AS [*]
FOR XML PATH(''),TYPE
)
FROM @tbl t
)
SELECT NewXml.query('/root') TheXml
FROM cte
WHERE NewXml.exist('/root/a[. cast as xs:int?=/values/@val]')=1