0

使用 SQLServer2008R2

我目前在 XML 标签内(不在它们之间)有带有数据的 XML 标签,例如:

<zooid="1"><animals key="all" zebras="22" dogs="0" birds="4" /><animals key="all" workers="yes" vacation="occasion" /> ... *(more)*</zooid>
<zooid="2"><animals key="house" zebras="0" dogs="1" birds="2" /><animals key="house" workers="no" vacation="no" /> ... *(more)*</zoodid>

如果我查询 XML 或对它使用 value 函数,它会返回空白值,因为它试图在标签之间读取 - 其中不存在任何值。我需要它来读取标签内部,将等号之前的值解析为列,将引号之间的值解析为这些列中的值(当然,我可以创建一个可以执行此操作的函数,但这会非常细致,我很好奇这样的东西是否已经存在)。在列中应该是这样的:

Key | Zebras | Dogs | Birds | Key | Workers | Vacation | ... *(more)*

...这在数据行中

all   | 22 | 0 | 4 | all   | yes | occasion | ... *(more)*
house | 0  | 1 | 2 | house | no  | no       | ... *(more)*

所以最终的输出(现在只使用从头开始的两个 XML 行),看起来像下面的表格形式的数据:

Key   | Zebras | Dogs | Birds | Key    | Workers | Vacation | ... *(more)*
================================================================
all   | 22     | 0    | 4     | all   | yes     | occasion | ... *(more)*
house | 0      | 1    | 2     | house | no      | no       | ... *(more)*

除了查询 XML、使用该.query工具甚至尝试该.node工具(使用CROSS APPLY见此线程)之外,我无法生成它。

4

2 回答 2

1

您的 xml 似乎无效。你怎么能指定这样的元素:?一般xml结构是<(elementName) (Attribute)="(Value)"/>。除非我弄错了,如果您以这种方式将文本转换为 xml,它将失败。说我可以在一个将在 SQL 管理 Studio 中按原样运行的自提取示例中展示一个正确 xml 的工作示例。

declare @text1 varchar(max) = '<zooid="1"><animals="all" zebras="22" dogs="0" birds="4" /><animals="all" workers="yes" vacation="occasion" /></zooid>'
,   @text2 varchar(max) = '<a zooid="1"><b animals="all" zebras="22" dogs="0" birds="4" /><b animals="all" workers="yes" vacation="occasion" /></a>'
,   @xml xml
;

begin try 
    set @xml = cast(@text1 as xml)
end try
begin catch
    set @xml = '<ElementName Attribute="BadData Elements are not named" />'
end catch 

select @xml

begin try 
    set @xml = cast(@text2 as xml)
end try
begin catch
    set @xml = '<ElementName Attribute="BadData" />'
end catch 

select  
    @xml.value('(/a/b/@animals)[1]', 'varchar(20)') as AnimalsValue
,   @xml.value('(/a/b/@zebras)[1]', 'int') as ZebrasValue
,   @xml.value('(/a/b/@dogs)[1]', 'int') as DogsValue
,   @xml.value('(/a/b/@birds)[1]', 'int') as BirdsValue
,   @xml.value('(/a/b/@workers)[1]', 'varchar(16)') as Workers
,   @xml.value('(/a/b/@vacation)[1]', 'varchar(16)') as Vacation

'.value' 方法是一种用于在 SQL 中查询 xml 的语法。我基本上是在找到元素(我做了包含 b 的 a 的泛型)。然后在我想要的级别上,“@animals”代表“名称动物的属性”。[1] 是一个位置,因为我一次只能返回一个东西,所以我选择了第一个位置。然后它需要一个数据类型来返回。文本是 varchar,数字是整数。

XML 查询方法:http: //msdn.microsoft.com/en-us/library/ms190798.aspx

于 2013-04-23T16:02:10.640 回答
1

试试这个——

DECLARE @YourXML NVARCHAR(MAX)
SELECT @YourXML = '
    <zooid="1">
        <animals key="all" zebras="22" dogs="0" birds="4" />
        <animals key="all" workers="yes" vacation="occasion" />
    </zooid>
    <zooid="2">
        <animals key="house" zebras="0" dogs="1" birds="2" />
        <animals key="house" workers="no" vacation="no" />
    </zoodid>'

DECLARE @XML XML
SELECT @XML = 
    REPLACE(
          REPLACE(@YourXML, 'zooid=', 'zooid id=')
        , '</zoodid>'
        , '</zooid>')

SELECT 
      d.[Key]
    , Dogs = MAX(d.Dogs)
    , Zebras = MAX(d.Zebras)
    , Birds = MAX(d.Birds)
    , Workers = MAX(d.Workers)
    , Vacation = MAX(d.Vacation)
FROM (
    SELECT 
          [Key] = t.p.value('./@key', 'NVARCHAR(50)')
        , Zebras = t.p.value('./@zebras', 'INT')
        , Dogs = t.p.value('./@dogs', 'INT')
        , Birds = t.p.value('./@birds', 'INT')
        , Workers = t.p.value('./@workers', 'NVARCHAR(20)')
        , Vacation = t.p.value('./@vacation', 'NVARCHAR(20)')
    FROM @XML.nodes('/zooid/animals') t(p)
) d
GROUP BY d.[Key]
于 2013-04-24T05:50:46.160 回答