我将XML数据存储到名为BikeTable
的表中。 XML数据来自使用.Net序列化程序序列化的对象。
BikeTable看起来像这样:
Id - UniqueIdentifier
XmlData - XML
XmlData
列中存储的XML如下所示:
记录1:
<Bike>
<Material>
<Cage>EIECH</Cage>
<Mpn>B258-C436-B001</
</Material>
<Roles>
<string>Race</string>
<string>Mountain</string>
<string>City</string>
</Roles>
</Bike>
记录2:
<Bike>
<Material>
<Cage>ABCDE</Cage>
<Mpn>B258-C436-B001</Mpn>
</Material>
<Roles>
<string>Race</string>
</Roles>
</Bike>
我希望能够在我的表格中找到包含例如Race和Mountain的记录。
示例,如果我想要包含&#39; Road&#39;和&#39; Mountain&#34;的记录的ID。我发现的唯一方法就是这样:
select Id
from BikeTable
where XmlData.exist('/Bike/Roles/string[contains(., "Road")]') = 1
or XmlData.exist('/Bike/Roles/string[contains(., "Mountain")]') = 1
我不喜欢这个选项,因为如果我想查找匹配一个或多个角色的记录,它会强制我生成查询。 角色可以包含无限数量的值,我需要能够找到一个或多个值的记录。 例如:包含Race的记录,包含Race或Montain的记录,包含City的记录,包含City和Mountain的记录等。
有没有办法知道列表是否包含多个值?
答案 0 :(得分:0)
是的,你可以。这有点猜测,正如你所说,你想做SELECT *
;没有桌子的DDL就无法提供任何数据的东西。因此,相反,我已经归还了自行车的Cage和Mpn:
CREATE TABLE BikeTable (xmlData xml);
--The Close tag for Mpn was missing in your sample data, I assume it wasn't mean to be
INSERT INTO BikeTable
VALUES('<Bike>
<Material>
<Cage>EIECH</Cage>
<Mpn>B258-C436-B001</Mpn>
</Material>
<Roles>
<string>Race</string>
<string>Mountain</string>
<string>City</string>
</Roles>
</Bike>')
GO
WITH Bikes AS (
SELECT B.Material.value('(Cage/text())[1]','varchar(15)') AS Cage, --Data Type guessed
B.Material.value('(Mpn/text())[1]','varchar(15)') AS Mpn, --Data Type guessed
BR.String.value('(./text())[1]','varchar(15)') AS String --Data Type guessed
FROM BikeTable BT
CROSS APPLY BT.xmlData.nodes('/Bike/Material') B(Material)
CROSS APPLY BT.xmlData.nodes('/Bike/Roles/string') BR(String))
SELECT Cage, Mpn
FROM Bikes
GROUP BY Cage, Mpn
HAVING COUNT(String) > 1;
GO
DROP TABLE BikeTable;