您遇到的问题是由于 XML 中的模式规范造成的。如果 XML 文档中的节点是模式的一部分,则必须在查询该节点时指定该模式。或者,您可以为架构规范使用通配符。但是指定没有模式的节点名称不起作用(正如您所经历的那样)。
所以让我们看一个例子:
SQL小提琴
MS SQL Server 2008 架构设置:
CREATE TABLE dbo.Tbl(id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, dict XML);
INSERT INTO dbo.Tbl(dict)
VALUES('<ArrayOfKeyValueOfstringanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<KeyValueOfstringanyType>
<Key>code</Key><Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">WFR 052</Value>
</KeyValueOfstringanyType>
<KeyValueOfstringanyType>
<Key>type</Key><Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">Newsletter</Value>
</KeyValueOfstringanyType>
</ArrayOfKeyValueOfstringanyType>');
该表dbo.Tbl
仅使用两列创建,一个标识id
列和一个dict
用于 XML 的列。
要使您的第一个查询正常工作,请为每个节点使用通配符指定架构:
查询 1:
SELECT dict.value('/*:ArrayOfKeyValueOfstringanyType[1]/*:KeyValueOfstringanyType[1]/*:Key[1]','NVARCHAR(MAX)')
FROM dbo.Tbl;
这导致第一个Key
被返回:
结果:
| COLUMN_0 |
|----------|
| code |
现在,您要返回 Key = 'code' 的所有键值对的值节点。您可以在 xquery 中进行过滤,但我通常更喜欢在 SQL 中进行过滤。为此,我们首先需要取回所有对。XML 节点函数让我们更进一步:
查询 2:
SELECT id,key_value.query('.')
FROM dbo.Tbl
CROSS APPLY dict.nodes('/*:ArrayOfKeyValueOfstringanyType/*:KeyValueOfstringanyType') AS N(key_value);
KeyValueOfstringanyType
每个节点返回一行:
结果:
| ID | COLUMN_1 |
|----|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 | <p1:KeyValueOfstringanyType xmlns:p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><p1:Key>code</p1:Key><p1:Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="d3p1:string">WFR 052</p1:Value></p1:KeyValueOfstringanyType> |
| 1 | <p1:KeyValueOfstringanyType xmlns:p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><p1:Key>type</p1:Key><p1:Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="d3p1:string">Newsletter</p1:Value></p1:KeyValueOfstringanyType> |
Key
使用它,我们可以Value
使用 XML.value 函数:
查询 3:
SELECT id,
key_value.value('./*:Key[1]','NVARCHAR(MAX)') AS [key],
key_value.value('./*:Value[1]','NVARCHAR(MAX)') AS [value]
FROM dbo.Tbl
CROSS APPLY dict.nodes('/*:ArrayOfKeyValueOfstringanyType/*:KeyValueOfstringanyType') AS N(key_value);
现在我们每个键值对都有一行,键和值在不同的列中:
结果:
| ID | KEY | VALUE |
|----|------|------------|
| 1 | code | WFR 052 |
| 1 | type | Newsletter |
从那里很容易在WHERE
子句中应用其他过滤器:
问题 4:
WITH KeyValues AS(
SELECT id,
key_value.value('./*:Key[1]','NVARCHAR(MAX)') AS [key],
key_value.value('./*:Value[1]','NVARCHAR(MAX)') AS [value]
FROM dbo.Tbl
CROSS APPLY dict.nodes('/*:ArrayOfKeyValueOfstringanyType/*:KeyValueOfstringanyType') AS N(key_value)
)
SELECT *
FROM KeyValues
WHERE [Key] = 'code';
结果:
| ID | KEY | VALUE |
|----|------|---------|
| 1 | code | WFR 052 |