我有以下查询:
SELECT
CAST(spi.dbo.UserInfo.XmlContent AS xml).value('(/UserInfo[1]/@SystemId)','VARCHAR(32)') as SystemId,
CAST(spi.dbo.UserInfo.XmlContent AS xml).value('(/UserInfo[1]/@LoginId)','VARCHAR(32)') as LoginId,
--CAST(spi.dbo.UserInfo.XmlContent AS xml).value('(/UserInfo[1]/ChangeInfo/@UserId)[3]','VARCHAR(32)')AS SystemID
CAST(spi.dbo.UserInfo.XmlContent AS xml).value('count(/UserInfo/ChangeInfo)', 'INT') AS 'Count'
FROM UserInfo
WHERE CAST(spi.dbo.UserInfo.XmlContent AS xml).value('(/UserInfo[1]/ChangeInfo)[1]','VARCHAR(32)') = 'John'
我遇到的问题是节点ChangeInfo
在某些XML记录中可能是多个。
如何搜索所有节点,而不必明确地命名节点的数量,例如说ChangeInfo[1]
?
答案 0 :(得分:0)
为什么需要强制转换列XmlContent
?这应该是本机XML类型列。此转换非常昂贵,而将XML保留在非XML列中是非常错误的...
没有显示您的XML,这是被蒙住眼睛,但是我的魔幻水晶球告诉我,您可能正在寻找这样的东西:
SELECT
A.CastedToXml.value('(/UserInfo/@SystemId)[1]','VARCHAR(32)') as SystemId,
A.CastedToXml.value('(/UserInfo/@LoginId)[1]','VARCHAR(32)') as LoginId,
B.ci.value('(/UserInfo/ChangeInfo/@UserId)[1]','VARCHAR(32)') AS ChangeInfo_UserID,
A.CastedToXml.value('count(/UserInfo/ChangeInfo)', 'INT') AS ChangeInfo_Count
FROM spi.dbo.UserInfo ui
OUTER APPLY(SELECT CAST(ui.XmlContent AS xml)) A(CastedToXml)
OUTER APPLY A.CastedToXml.nodes('/UserInfo/ChangeInfo') B(ci)
WHERE CastedToXml.exist('/UserInfo/ChangeInfo[text()="John"]')=1;
我使用APPLY
将 xml-casted 列添加到结果集中。第二个APPLY
将返回所有嵌套的<ChangeInfo>
元素作为派生表。
WHERE
子句使用XML方法.exist()
。这将检查XML中任何位置给定Xpath
的出现情况。如果需要,您可以从外部动态地用sql:variable()
或sql:column
引入文字“ John”。
一个提示:尝试了解表别名以及如何避免重复代码。