在SQL Server中将XML标记存储在表中以获取不同的XML大小

我在SQL Server中有代码,该代码从XML提取标记并将它们存储在临时表(#result)中。现在,假设所有XML的结构都相同,则游标针对每个XML循环运行。下面的示例:

XML1 : <Root><Tag1>val1</Tag1><Tag2>val2</Tag2><Tag3>val3</Tag3></Root>

结果表:

Tag1    |   Tag2    |   Tag3
--------|-----------|--------
val1    |   val2    |   val3

但是现在我们有了一些XML,这些XML可以包含更少的标签。下面的示例:

XML1 : <Root><Tag1>val1</Tag1><Tag2>val2</Tag2><Tag3>val3</Tag3></Root>
XML2 : <Root><Tag1>val1</Tag1><Tag2>val2</Tag2><Tag3>val3</Tag3><Tag4>val4</Tag4></Root>
XML3 : <Root><Tag1>val1</Tag1><Tag2>val2</Tag2></Root>

结果表:

Tag1    |   Tag2    |   Tag3    |   Tag4
--------|-----------|-----------|--------
val1    |   val2    |   val3    |       
--------|-----------|-----------|--------
val1    |   val2    |   val3    |   val4    
--------|-----------|-----------|--------
val1    |   val2    |           |       

下面是我现有的光标代码。

Open C_XML
Fetch next from C_XML into @input_xml
    while @@FETCH_STATUS = 0
    Begin
     Create Table #MyTempTable (
       name varchar(max),value varchar(max)
    );
    insert into #MyTempTable
    SELECT
    bar.value('local-name(.)','VARCHAR(max)') as name,bar.value('./.','VARCHAR(max)')  as value
    FROM
    @input_xml.nodes('/Root/*') AS input_xml(bar)
    DeclARE @name NVARCHAR(MAX) = ''
    DeclARE @val NVARCHAR(MAX) = ''
    Declare @Query NVARCHAR(MAX) = ''
    SELECT  @name +=   QUOTENAME(name)+ ','
    FROM
    (
        SELECT name
        FROM #MyTempTable
    ) AS ColName
    -- remvoing last comma
    SET @name = LEFT(@name,LEN(@name)-1)
    SET @Query =
    'SELECT * INTO ##temp2 FROM
    (SELECT
        name,value
    FROM
        #MyTempTable
    )
    AS TempTable
    PIVOT(
        max(value)
        FOR name IN (' + @name +')
    ) AS SPivotTable'

    EXECUTE sp_executesql @Query
    drop table #MyTempTable
    select * from ##temp2
    if (@count = 1 )
    begin
        select * into #result from ##temp2
    end
    else 
    begin
        insert into #result     
            select * from ##temp2
    end
    drop table ##temp2

    Set @count = @count + 1

Fetch next from C_XML  into @input_xml
END   
CLOSE C_XML;  
DEALLOCATE C_XML;

请建议我如何增强此代码,以使其对于所有类型的XML都是动态的,如上面的示例所述。当前它给出的错误:

  

#result表定义不正确。

daxiguatao 回答:在SQL Server中将XML标记存储在表中以获取不同的XML大小

如果我正确理解了这一点,则必须首先分析每种XML,以找到任何现有的元素名称。使用此名称列表,您必须通用地构建一个SELECT,覆盖表中任何位置的任何元素名称...

我认为这是错误的方法...

此外,很少有实际需要CURSOR的情况。在几乎任何情况下,如果您认为需要游标,都应​​该重新考虑您的方法。

我建议首先创建一个经典的EAV列表作为登台表:

-一个样机来模拟您的问题

DECLARE @YourTable TABLE(ID INT IDENTITY,YourXml XML);
INSERT INTO @YourTable VALUES ('<Root><Tag1>val1</Tag1><Tag2>val2</Tag2><Tag3>val3</Tag3></Root>'),('<Root><Tag1>val1</Tag1><Tag2>val2</Tag2><Tag3>val3</Tag3><Tag4>val4</Tag4></Root>'),('<Root><Tag1>val1</Tag1><Tag2>val2</Tag2></Root>');

-一种基于集合的方法,无需游标即可获取每个值

SELECT t.ID,A.AnyNode.value('local-name(.)','nvarchar(max)') AS ElementName,A.AnyNode.value('text()[1]','nvarchar(max)') AS ElementValue
FROM @YourTable t
CROSS APPLY t.YourXml.nodes('/Root/*') A(AnyNode);

使用此结果,您可以继续使用标准SQL。如果需要,您可以从此处创建动态SQL ...

本文链接:https://www.f2er.com/3162231.html

大家都在问