IT *_*her 2 xml sql-server sql-server-2008-r2 xquery
我之前问过有关不区分大小写标记的 XML 查询的问题,我也找到了解决方案。但我也找到了一些其他的解决方案。所以桌子就像
DECLARE @myTable TABLE ( yourXML XML )
INSERT INTO @myTable SELECT '<z><a><b>1</b><c>2</c></a></z>'
INSERT INTO @myTable SELECT '<Z><A><b>1</b><c>2</c></A></Z>'
Run Code Online (Sandbox Code Playgroud)
以下所有解决方案都返回我想要的(不区分大小写的标签)
-----Solution 1----------
SELECT * FROM @myTable WHERE ( [yourXML].exist('for $x in /*[lower-case(local-name(.)) = "z"]/*[lower-case(local-name(.)) = "a"] where ( ($x/*[lower-case(local-name(.)) = "b"][1]) = 1 ) return $x')>0 )
-------------------------
-----Solution 2----------
SELECT * FROM @myTable
WHERE
(CONVERT(XML,LOWER(CONVERT(VARCHAR(MAX),[yourXML]))).exist('for $x in /z/a where ( ($x/b[1]) = 1 ) return $x')>0 )
-------------------------
-----Solution 3----------
SELECT * FROM @myTable WHERE
([yourXML].exist('for $x in (/Z/A,/z/a) where ( ($x/b[1],$x/B[1]) = 1 ) return $x') > 0 )
-------------------------
Run Code Online (Sandbox Code Playgroud)
现在我想通过考虑它的所有 X-query 命令(支持 value()、exist()、count()、query() 等)、性能、效率等来知道哪个更好用。
您可以轻松地自己测试性能。
创建一个常规表,您可以在其上测试您的查询。
create table myTable ( yourXML XML )
Run Code Online (Sandbox Code Playgroud)
添加几行可以匹配。
INSERT INTO myTable SELECT '<z><a><b>1</b><c>2</c></a></z>'
INSERT INTO myTable SELECT '<Z><A><b>1</b><c>2</c></A></Z>'
INSERT INTO myTable SELECT '<Z><A><B>1</B><c>2</c></A></Z>'
Run Code Online (Sandbox Code Playgroud)
添加一大堆在 XML 的不同部分不匹配的行。
insert into myTable
select top(10000) '<X><A><B>1</B><c>2</c></A></X>'
from sys.all_objects as o1, sys.all_objects as o2
insert into myTable
select top(10000) '<Z><X><B>1</B><c>2</c></X></Z>'
from sys.all_objects as o1, sys.all_objects as o2
insert into myTable
select top(10000) '<Z><A><X>1</X><c>2</c></A></Z>'
from sys.all_objects as o1, sys.all_objects as o2
Run Code Online (Sandbox Code Playgroud)
使用SET STATISTICS IO (Transact-SQL)和SET STATISTICS TIME (Transact-SQL)并在 SQL Server Management Studio 中执行查询。
set statistics time on
set statistics io on
-----Solution 1----------
SELECT * FROM myTable WHERE ( [yourXML].exist('for $x in /*[lower-case(local-name(.)) = "z"]/*[lower-case(local-name(.)) = "a"] where ( ($x/*[lower-case(local-name(.)) = "b"][1]) = 1 ) return $x')>0 )
-------------------------
-----Solution 2----------
SELECT * FROM myTable
WHERE
(CONVERT(XML,LOWER(CONVERT(VARCHAR(MAX),[yourXML]))).exist('for $x in /z/a where ( ($x/b[1]) = 1 ) return $x')>0 )
-------------------------
-----Solution 3----------
SELECT * FROM myTable WHERE
([yourXML].exist('for $x in (/Z/A,/z/a) where ( ($x/b[1],$x/B[1]) = 1 ) return $x') > 0 )
-------------------------
-----Solution 4----------
select *
from myTable
where yourXML.exist('(Z/A,z/a)[(b,B)=1]') = 1
Run Code Online (Sandbox Code Playgroud)
切换到消息选项卡并评估执行时间和所需的读取。
据推测,您的数据库中有更好的数据可供测试。性能特征将根据您在现实世界中必须处理的 XML的实际结构而变化。
附带说明是,您的查询是不等价的。
第一个很容易适应更长的元素名称。
第二个查询更改元素的内容,而不仅仅是元素名称。
第三个查询并没有真正处理不区分大小写的元素名称,它只是枚举所有可能的元素名称,在这种情况下,这些元素名称仅在案例中有所不同。如果你想用你的第三个解决方案来处理一个 3 个字母的元素名称,你将有 8 个(我认为)不同的排列来处理。
我添加了第四个解决方案,主要是因为它简短漂亮,与您的第三个解决方案具有相同的局限性。在我的测量中,它比使用 FLWOR 略快。