问题描述
在sql Server中,我试图从XSD字符串中选择值。
例如给出以下sql Server表
CREATE TABLE dbo.textxML (
ID INT PRIMARY KEY,Data NVARCHAR(max))
INSERT INTO dbo.textxML ( ID,Data )
SELECT 1,('<element name="Rownum" value="Row23" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="1234" />
</element>
<element name="ENABLESSL" value="false" />' )
INSERT INTO dbo.textxML ( ID,Data )
SELECT 2,('<element name="Rownum" value="Row24" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="5678" />
</element>
<element name="ENABLESSL" value="true" />' );
我希望能够为给定的元素名称选择值。像...
SELECT ID,Data.CONNECTIONTYPESECTION,Data.EchoData.0007,Data.EchoData.MessageType,Data.ENABLESSL
FROM textxML
WHERE Data.Rownum = "Row23" AND Data.EchoData.MessageType = "1234".
ID Data.CONNECTIONTYPESECTION Data.EchoData.0007 Data.EchoData.MessageType Data.ENABLESSL
1 True 0805193143 1234 true
我可以使用CHARINDEX和SUBSTRING,但必须对“ 名称”值的长度进行硬编码,并且假定“ 值”的长度始终相同。我希望有一种更好,更有效的方法来做到这一点。
我已经尝试了CROSS APPPLY和XML VALUE函数,但这仅返回Data字段中的第一个元素。我也找不到如何搜索特定元素“ 名称”以获取其值
解决方法
请尝试以下T-SQL。
-- DDL and sample data population,start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY,Data NVARCHAR(max));
INSERT INTO @tbl (Data) VALUES
(N'<element name="Rownum" value="Row23"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="1234"/>
</element>
<element name="ENABLESSL" value="false"/>'),(N'<element name="Rownum" value="Row24"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="5678"/>
</element>
<element name="ENABLESSL" value="true"/>');
-- DDL and sample data population,end
;WITH rs AS
(
SELECT *,TRY_CAST(data AS XML) AS xmldata
FROM @tbl
)
SELECT rs.ID,xmldata.value('(element[@name="CONNECTIONTYPESECTION"]/@value)[1]','VARCHAR(10)') AS CONNECTIONTYPESECTION,xmldata.value('(element[@name="EchoData"]/element[@name="0007"]/@value)[1]','VARCHAR(10)') AS [EchoData.0007],xmldata.value('(element[@name="EchoData"]/element[@name="MessageType"]/@value)[1]','VARCHAR(10)') AS [EchoData.MessageType],xmldata.value('(element[@name="ENABLESSL"]/@value)[1]','VARCHAR(10)') AS [Data.ENABLESSL]
FROM rs
WHERE xmldata.value('(element[@name="Rownum"]/@value)[1]','VARCHAR(30)') = 'Row23'
AND xmldata.value('(element[@name="EchoData"]/element[@name="MessageType"]/@value)[1]','VARCHAR(10)') = '1234';
输出
+----+-----------------------+---------------+----------------------+----------------+
| ID | CONNECTIONTYPESECTION | EchoData.0007 | EchoData.MessageType | Data.ENABLESSL |
+----+-----------------------+---------------+----------------------+----------------+
| 1 | True | 0805193143 | 1234 | false |
+----+-----------------------+---------------+----------------------+----------------+