问题描述
我在MS sql中有一个表,其中的字段包含一个表示XML的字符串,如下所示:
< Root >
< Value_Tab2 ID = "182" >
< Value_Tab3 >
< Value > 1219 </ Value >
</ Value_Tab3 >
</ Value_Tab2 >
< Value_Tab2 ID = "187" >
< Value_Tab3 >
< Value > 3192 </ Value >
</ Value_Tab3 >
</ Value_Tab2 >
</ Root >
我可以将此字段转换字符串查询为XML,但是对于MyTable1的50000行,查询需要7到8秒的时间。我使用的查询是这样的:
SELECT MT1.ID,cast(MT1.StringXml as xml).value('(Root/Value_Tab2/@ID)[1]','INT') AS MT1_ID1,cast(MT1.StringXml as xml).value('(Root/Value_Tab2/@ID)[2]','INT') AS MT1_ID2,cast(MT1.StringXml as xml).value('(Root/Value_Tab2/Value_Tab3/Value)[1]','INT') AS VALUE_ID1,cast(MT1.StringXml as xml).value('(Root/Value_Tab2/Value_Tab3/Value)[2]','INT') AS VALUE_ID2
FROM MyTable1 MT1 with (NOLOCK)
WHERE MT1.Published = 1
StringXML是MyTable1,归档为nvarchar(MAX);这是查询字符串字段并转换为XML的正确方法吗?
解决方法
您需要做的就是XML粉碎。
请尝试以下操作。
正如@PanagiotisKanavos指出的那样,CAST操作仅执行一次。所有XPath表达式都针对性能进行了优化。
SQL
-- DDL and sample data population,start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY,Published BIT,StringXml NVARCHAR(MAX));
INSERT INTO @tbl (Published,StringXml) VALUES
(1,N'<Root>
<Value_Tab2 ID="182">
<Value_Tab3>
<Value>1219</Value>
</Value_Tab3>
</Value_Tab2>
<Value_Tab2 ID="187">
<Value_Tab3>
<Value>3192</Value>
</Value_Tab3>
</Value_Tab2>
</Root>');
-- DDL and sample data population,end
;WITH rs AS
(
SELECT ID,Published,TRY_CAST(StringXml AS XML) AS xmldata
FROM @tbl
)
SELECT ID,c.value('Value_Tab2[1]/@ID','INT') AS MT1_ID1,c.value('Value_Tab2[2]/@ID','INT') AS MT1_ID2,c.value('(Value_Tab2[1]/Value_Tab3/Value/text())[1]','INT') AS VALUE_ID1,c.value('(Value_Tab2[2]/Value_Tab3/Value/text())[1]','INT') AS VALUE_ID2
FROM rs
CROSS APPLY xmldata.nodes('/Root') AS t(c)
WHERE rs.Published = 1;
输出
+----+---------+---------+-----------+-----------+
| ID | MT1_ID1 | MT1_ID2 | VALUE_ID1 | VALUE_ID2 |
+----+---------+---------+-----------+-----------+
| 1 | 182 | 187 | 1219 | 3192 |
+----+---------+---------+-----------+-----------+