查询 XML 列 - 返回关系数据
Querying an XML column - returning relational data
我有一个问题,我必须 return 包含在 XML 列中的 SQL 查询中的数据。我有一些初步的结果,但很难快速取得进展。到目前为止我有这个:
XML(一行示例):
<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>
SQL:
select ItemID,
boolean = CASE WHEN CF.exist('/root/property/Name[text() = "Boolean"]') = 1
THEN CF.value('(/root/property/Value)[1]', 'varchar(32)') END,
[integer] = CASE WHEN CF.exist('/root/property/Name[text() = "Integer"]') = 1
THEN CF.value('(/root/property/Value)[2]', 'varchar(32)') END
from
[TTS].[dbo].[tblInItem]
结果数据是这样的:
您可以看到第 4 行填充了一个布尔值,其中应该是一个整数。这是因为该行的 XML 是:
<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Another Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>
那么,如何用 return 节点位置的东西替换 CF.value('(/root/property/Value)[2]', 'varchar(32)')
中的单例 [2]
?
我也认识到可能有许多更优雅的解决方案,并且对其中任何一个都持开放态度。
跳过 case 语句并将谓词放在 xPath 表达式中的 属性 name 上,您可以从中获取值。
MS SQL Server 2008 架构设置:
create table T(ItemID int identity primary key, CF xml);
insert into T(CF) values('<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>');
insert into T(CF) values('<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Another Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>');
查询 1:
select T.ItemID,
T.CF.value('(/root/property[Name/text() = "Boolean"]/Value/text())[1]', 'varchar(32)') as Boolean,
T.CF.value('(/root/property[Name/text() = "Integer"]/Value/text())[1]', 'varchar(32)') as Integer
from T
| ItemID | Boolean | Integer |
|--------|---------|---------|
| 1 | True | 0 |
| 2 | True | 0 |
我有一个问题,我必须 return 包含在 XML 列中的 SQL 查询中的数据。我有一些初步的结果,但很难快速取得进展。到目前为止我有这个:
XML(一行示例):
<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>
SQL:
select ItemID,
boolean = CASE WHEN CF.exist('/root/property/Name[text() = "Boolean"]') = 1
THEN CF.value('(/root/property/Value)[1]', 'varchar(32)') END,
[integer] = CASE WHEN CF.exist('/root/property/Name[text() = "Integer"]') = 1
THEN CF.value('(/root/property/Value)[2]', 'varchar(32)') END
from
[TTS].[dbo].[tblInItem]
结果数据是这样的:
您可以看到第 4 行填充了一个布尔值,其中应该是一个整数。这是因为该行的 XML 是:
<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Another Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>
那么,如何用 return 节点位置的东西替换 CF.value('(/root/property/Value)[2]', 'varchar(32)')
中的单例 [2]
?
我也认识到可能有许多更优雅的解决方案,并且对其中任何一个都持开放态度。
跳过 case 语句并将谓词放在 xPath 表达式中的 属性 name 上,您可以从中获取值。
MS SQL Server 2008 架构设置:
create table T(ItemID int identity primary key, CF xml);
insert into T(CF) values('<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>');
insert into T(CF) values('<root>
<property>
<Name>Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Another Boolean</Name>
<Value>True</Value>
</property>
<property>
<Name>Integer</Name>
<Value>0</Value>
</property>
</root>');
查询 1:
select T.ItemID,
T.CF.value('(/root/property[Name/text() = "Boolean"]/Value/text())[1]', 'varchar(32)') as Boolean,
T.CF.value('(/root/property[Name/text() = "Integer"]/Value/text())[1]', 'varchar(32)') as Integer
from T
| ItemID | Boolean | Integer |
|--------|---------|---------|
| 1 | True | 0 |
| 2 | True | 0 |