我在数据库中有XML列表。现在我需要从XML中选择两个属性的行。到目前为止,我已经想出了这个:
SELECT o.Id
FROM Objects o
WHERE o.SerializedObject.value('(/object/param[@id="111"]/@value)[1]', 'varchar(8)') = '-1'
AND o.SerializedObject.value('(/object/param[@id="222"]/@value)[1]', 'varchar(8)') = '8'
编辑:
XML就像:
<object>
<param id="1" value="111"/>
<param id="2" value="222"/>
...
<param id="200" value="4545"/>
<object>
每个物体都有~2k参数。
我想知道单个XML查询是否有更好的方法来做到这一点。
这取决于你的XML(你没有展示一个例子,但我认为这是一种EAV)。
您可以尝试使用XML的方法.exist()
:
DECLARE @mockup TABLE(ID INT IDENTITY,Comment VARCHAR(100),SerializedObject XML);
INSERT INTO @mockup VALUES
('just one of them','<object><param id="111" value="-1"/></object>')
,('both, but wrong values','<object><param id="111" value="-1"/><param id="222" value="-1"/></object>')
,('both, should fit','<object><param id="111" value="-1"/><param id="222" value="8"/></object>')
SELECT o.Id,o.Comment,o.SerializedObject
FROM @mockup o
WHERE o.SerializedObject.exist('/object[param[@id="111" and @value="-1"] and param[@id="222" and @value="8"]]')=1;
.exist()
在这里是最快的,因为它没有返回任何价值。它将在第一次发现时返回1
。这是特别快,当有很多<param id="111" value="???">
出现时,否则你必须粉碎整个批次并将过滤器放在整个结果集上。
而且当然! - 必要的提示:正如Jeroen Mostert在评论中所说,处理更大的XML可能会成为瓶颈。如果你经常需要这个,你可能会考虑关系设计而不是大XML ...