我有一个表,带有 XML 字段(描述符)的实体,如下所示:
<component uid="a1">
<files>
<group name="component">
<file path="a1.bmp" md5="0315DBA4FBEEB917F41AFF1A1BFF549B" />
<file path="a2.jpg" md5="C3107D8BFA0EF0C02434FB7FC7472EAC" />
<file path="a3.bmp" md5="603B9635A4921C25D50844254A2B573D" />
<file path="a4.ini" md5="9C12CC7F5C1F1F4240DA407F7E3B145E" />
</group>
</files>
</component>
我想找到具有特定 md5 值的"file"的实体:
select ... from ...
where Descriptor.value('(/component/files/group/file/@md5)[1]',
'nvarchar(100)')='C3107D8BFA0EF0C02434FB7FC7472EAC'
问题是当第一个文件具有特定的 md5 值时它会找到该项目。我想要的是什么时候找到任何文件项具有特定的 md5 值。
最佳答案
您可以使用 XML 方法 exist()
简单地检查元素的存在
我使用声明的表变量来模拟您的场景。插入三个不同的案例:
DECLARE @dummy TABLE(EntityID INT IDENTITY,SomeText VARCHAR(100),Descriptor XML);
INSERT INTO @dummy VALUES
('MD5 03... on first place',
N'<component uid="a1">
<files>
<group name="component">
<file path="a1.bmp" md5="0315DBA4FBEEB917F41AFF1A1BFF549B" />
<file path="a2.jpg" md5="C3107D8BFA0EF0C02434FB7FC7472EAC" />
<file path="a3.bmp" md5="603B9635A4921C25D50844254A2B573D" />
<file path="a4.ini" md5="9C12CC7F5C1F1F4240DA407F7E3B145E" />
</group>
</files>
</component>')
,('MD5 03... somewhere',
N'<component uid="a1">
<files>
<group name="component">
<file path="a2.jpg" md5="C3107D8BFA0EF0C02434FB7FC7472EAC" />
<file path="a3.bmp" md5="603B9635A4921C25D50844254A2B573D" />
<file path="a1.bmp" md5="0315DBA4FBEEB917F41AFF1A1BFF549B" />
<file path="a4.ini" md5="9C12CC7F5C1F1F4240DA407F7E3B145E" />
</group>
</files>
</component>')
,('MD5 03... not existing',
N'<component uid="a1">
<files>
<group name="component">
<file path="a2.jpg" md5="C3107D8BFA0EF0C02434FB7FC7472EAC" />
<file path="a3.bmp" md5="603B9635A4921C25D50844254A2B573D" />
<file path="a4.ini" md5="9C12CC7F5C1F1F4240DA407F7E3B145E" />
</group>
</files>
</component>');
这是一个硬编码查询:
SELECT *
FROM @dummy
WHERE Descriptor.exist('/component/files/group/file[@md5="0315DBA4FBEEB917F41AFF1A1BFF549B"]')=1;
但是您可能希望将搜索值作为 sql 变量参数引入
DECLARE @md5 VARCHAR(100)='0315DBA4FBEEB917F41AFF1A1BFF549B';
SELECT *
FROM @dummy
WHERE Descriptor.exist('/component/files/group/file[@md5=sql:variable("@md5")]')=1;
如果这个 MD5 可以位于不同的地方,您可能还想检查深度搜索
DECLARE @md5 VARCHAR(100)='0315DBA4FBEEB917F41AFF1A1BFF549B';
SELECT *
FROM @dummy
WHERE Descriptor.exist('//file[@md5=sql:variable("@md5")]')=1;
暗示
搜索 XML 数据永远不会高效......我强烈建议 - 如果您更频繁地需要它并且如果性能很重要,请维护一个带有 MD5 值和 rowID 的边表。您可以使用类似于索引。我不会走 XML 索引之路……
关于sql - T-SQL 中的 XPath 选择实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41846425/