如何在SQL Server中选择XML列的顶级属性?

26

我在SQL Server中有一个XML列,它的等效形式为:

<Test foo="bar">
  <Otherstuff baz="belch" />
</Test>

我想要将Test元素(根元素)的foo属性值作为varchar获取。我的目标是类似于以下代码:

SELECT CAST('<Test foo="bar"><Otherstuff baz="belch" /></Test>' AS xml).value('@foo', 'varchar(20)') AS Foo

但是当我运行上面的查询时,我收到以下错误:

Msg 2390,级别 16,状态 1,第 1 行 XQuery [value()]: 不支持顶级属性节点

3个回答

46

约翰·桑德斯几乎说对了 :-)

declare @Data XML
set @Data = '<Test foo="bar"><Otherstuff baz="belch" /></Test>'

select @Data.value('(/Test/@foo)[1]','varchar(20)') as Foo

这对我有用(适用于SQL Server 2005和2008)

Marc


如果你不知道根元素是什么怎么办???在这种情况下,我们知道它是“Test”,但我有一个XML字段,它根据另一个字段的值而有不同的XML。所以它可以是<book>或<something_else>...是否有默认的根元素名称可以使用...??? - Ads
2
@Ads使用通配符,例如//Element[@foo]或者如果您了解结构,则为/*/Elements/Element[@foo] - StuartLC
将查询语句用括号括起来。天哪,我永远也猜不到。在TSQL中进行XML查询非常好,但是语法太难了。 - dudeNumber4

7

如果您不知道根元素:

select @Data.value('(/*/@foo)[1]','varchar(20)') as Foo

0

为什么.value('@foo', 'varchar(20)')会生成错误信息“不支持顶级属性节点”?

当您查询xml数据类型时,上下文是文档节点,它是一个隐式节点,包含XML文档的根元素。文档节点没有名称和属性。

如何获取根元素上属性的值?

在您的XQuery表达式中,包括到第一个根元素的路径:

DECLARE @Data xml = '<Customer ID="123"><Order ID="ABC" /></Customer>'

SELECT @Data.value('Customer[1]/@ID', 'varchar(20)')
-- Result: 123

如果您不知道(或不想指定)根元素的名称,则只需使用*匹配任何元素:

SELECT @Data.value('*[1]/@ID', 'varchar(20)')
-- Result: 123

由于查询上下文是文档节点,因此您不需要在XQuery表达式前加上斜杠(其他答案不必要地这样做)。

为什么我必须包含[1]

您传递给value()的XQuery表达式必须保证返回单例。表达式Customer/@ID不满足此要求,因为它匹配以下示例中的ID="123"ID="456"

DECLARE @Data xml = '<Customer ID="123" /><Customer ID="456" />'

请记住,xml数据类型表示的是XML文档片段而不是XML文档,因此可以包含多个根元素。

Customer[1]/@ID(Customer/@ID)[1]之间有什么区别?

表达式Customer[1]/@ID检索第一个<Customer>元素的ID属性。

表达式(Customer/@ID)[1]检索所有<Customer>元素的ID属性,并从该属性列表中选择第一个。

以下示例演示了差异:

DECLARE @Data xml = '<Customer /><Customer ID="123" /><Customer ID="456" />'

SELECT @Data.value('Customer[1]/@ID', 'varchar(20)')
-- Result: NULL (because the first Customer element doesn't have an ID attribute)

SELECT @Data.value('(Customer/@ID)[1]', 'varchar(20)')
-- Result: 123

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接