我的表Web.Log
的列Properties
包含以下内容
<properties>
...
<property key="ActivityId" />
<property key="UserName">John Doe</property>
</properties>
如何仅对包含Web.Log
userName属性的行过滤John Doe
表?
现在我使用
select * from Web.Log
where cast(Properties as nvarchar(max))
like '%<property key="UserName">John Doe</property>%'
这似乎是解决方法:-)
使用XQUERY和一个EXISTS
:
SELECT {Columns}
FROM Web.Log L
WHERE EXISTS (SELECT 1
FROM L.[Properties].nodes('/properties/property')p(p)
WHERE p.p.value('(text())[1]','nvarchar(50)') = 'John Doe')
使用本机XML方法.exist()
应该更快。
首先创建一个模型场景以模拟您的问题:
DECLARE @tbl TABLE(ID INT IDENTITY, SomeText VARCHAR(100),Properties XML);
INSERT INTO @tbl VALUES('John Doe exists'
,'<properties>
<property key="ActivityId" />
<property key="UserName">John Doe</property>
</properties>')
,('John Doe doesn''t exist'
,'<properties>
<property key="ActivityId" />
<property key="UserName">Someone else</property>
</properties>')
,('John Doe exists'
,'<properties>
<property key="ActivityId" />
<property key="UserName">John Doe</property>
</properties>');
-我们可以使用变量进行一般性过滤
DECLARE @SearchFor VARCHAR(100)='UserName';
DECLARE @FindThis VARCHAR(100)='John Doe';
-这是查询:
SELECT *
FROM @tbl t
WHERE t.Properties.exist('/properties/property[@key=sql:variable("@SearchFor") and text()[1]=sql:variable("@FindThis")]')=1;
简而言之:
.exist()
。=1
可以设置为=0
,以便返回负值设置<property>
。