【问题标题】:How to Insert Different XML Field values as rows in a table如何将不同的 XML 字段值作为行插入表中
【发布时间】:2014-10-31 14:03:52
【问题描述】:

我有一个如下所述的 xml,

 declare  @Message as xml

 set @Message='<message>

        <body>
        <ID>1</ID>
        <setup_time>10</setup_time>
        <prod_cycle_time>10</prod_cycle_time>
        <unit>cas</unit>
        <Flag>NULL</Flag>
        <FillingPO>NULL</FillingPO>
        <PackAtCAN1>NULL</PackAtCAN1>
        </body>
        </message>'

从上面的 xml 结构中需要插入几个字段数据,格式如下所述

    ID     Desc              Value
     1      setup_time        10
     1      prod_cycle_time   10
     1      unit              Case
     1      Flag              NULL

【问题讨论】:

    标签: sql xml sql-server-2008


    【解决方案1】:

    您也可以使用 XQuery 来首先转换您的 XML:

    declare @transform xml
    
    set @transform = @message.query('
        let $capture := ("setup_time","prod_cycle_time","unit","Flag")
    
        for $item in /message/body/*
        let $id := $item/../ID
        where $capture = local-name($item)
        return <Row>
                <ID>{$id/text()}</ID>
                <Desc>{local-name($item)}</Desc>
                <Value>{$item/text()}</Value>
            </Row>
    ')
    
    SELECT  x.value('ID[1]','int') AS ID,
            x.value('Desc[1]','varchar(max)') AS [Desc],
            x.value('Value[1]','varchar(max)') AS Value
    FROM    @transform.nodes('/Row') tmp(x)
    

    【讨论】:

    • +1 我喜欢看到这样的示例(以及 XML-DML),因为我知道有趣和有用的事情可以通过 FLWOR 完成,但不要使用它/XML 足以了解所有的可能性。这确实是 SQL Server 内置的未充分利用和未得到重视的功能,它增加了在数据库中存储 XML(在合理范围内)的合法性,与那些喊“你永远不应该将非结构化数据存储在单个字段中”的人相反 :)。
    【解决方案2】:

    看起来您想从 XML 中获取值,然后进行反透视。

    使用value() 函数从XML 中提取值,您可以使用union all 进行反透视。

    declare  @Message as xml
    
    set @Message='
    <message>
      <body>
        <ID>1</ID>
        <setup_time>10</setup_time>
        <prod_cycle_time>10</prod_cycle_time>
        <unit>cas</unit>
        <Flag>NULL</Flag>
        <FillingPO>NULL</FillingPO>
        <PackAtCAN1>NULL</PackAtCAN1>
      </body>
    </message>'
    
    declare @ID int 
    set @ID = @Message.value('(/message/body/ID/text())[1]', 'int') 
    
    select @ID as ID, 
           'setup_time' as [Desc], 
           @Message.value('(/message/body/setup_time/text())[1]', 'nvarchar(50)') as Value 
    union all
    select @ID, 
           'prod_cycle_time', 
           @Message.value('(/message/body/prod_cycle_time/text())[1]', 'nvarchar(50)') 
    union all
    select @ID, 
           'unit', 
           @Message.value('(/message/body/unit/text())[1]', 'nvarchar(50)')  
    union all
    select @ID, 
           'Flag', 
           @Message.value('(/message/body/Flag/text())[1]', 'nvarchar(50)')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多