【问题标题】:How to convert XML data into row column data in SQL Server如何在 SQL Server 中将 XML 数据转换为行列数据
【发布时间】:2014-04-15 23:49:07
【问题描述】:

我有一个需求,我在数据库中有 XML 数据,我需要从数据库中以行和列的形式提取这些数据。我的 XML 就像

<Equipment>
<EquipmentRecord>
<EquipmentType>E</EquipmentType><MfgName>APPLE iPH564WHT</MfgName><Model>885909600205</Model><ActDate>10/26/2012</ActDate><CancelDate />
</EquipmentRecord>
<EquipmentRecord>
<EquipmentType>E</EquipmentType><MfgName>SAMSUNG D710 HANDSET KIT</MfgName><Model>SPHD710KIT</Model><ActDate>09/04/2012</ActDate><CancelDate>10/01/2012</CancelDate>
</EquipmentRecord>
<EquipmentRecord>
<EquipmentType>E</EquipmentType><MfgName>BLACKBERRY 9670 PURPLE</MfgName><Model>SPRIM9670P</Model><ActDate>08/22/2012</ActDate><CancelDate>08/25/2012</CancelDate>
</EquipmentRecord>
</Equipment>

我希望像

一样提取数据
EquipmentType   MfgName                 Model           ActDate     CancelDate
E             APPLE iPH564WHT           885909600205    10/26/2012  
E             SAMSUNG D710 HANDSET KIT  SPHD710KIT      09/04/2012  10/01/2012
E             BLACKBERRY 9670 PURPLE    SPRIM9670P      08/22/2012  08/25/2012

在 SQL Server 中有什么简单的方法吗?

我试过了,效果很好

DECLARE @doc XML
SET @doc = 'above XML'  

CREATE TABLE #EquipmentType (ID INT IDENTITY(1,1), EquipmentType varchar(100))
INSERT INTO #EquipmentType(EquipmentType)
SELECT EquipmentDetails.value('.','varchar(100)') as EquipmentType
FROM @doc.nodes('/Equipment/EquipmentRecord/EquipmentType/.') Equipment(EquipmentDetails)

CREATE TABLE #MfgName (ID INT IDENTITY(1,1), MfgName varchar(500))
INSERT INTO #MfgName(MfgName)
SELECT EquipmentDetails.value('.','varchar(500)') as MfgName
FROM @doc.nodes('/Equipment/EquipmentRecord/MfgName/.') Equipment(EquipmentDetails)

CREATE TABLE #Model (ID INT IDENTITY(1,1), Model varchar(500))
INSERT INTO #Model(Model)
SELECT EquipmentDetails.value('.','varchar(500)') as Model
FROM @doc.nodes('/Equipment/EquipmentRecord/Model/.') Equipment(EquipmentDetails)

CREATE TABLE #ActDate (ID INT IDENTITY(1,1), ActDate varchar(500))
INSERT INTO #ActDate(ActDate)
SELECT EquipmentDetails.value('.','varchar(500)') as ActDate
FROM @doc.nodes('/Equipment/EquipmentRecord/ActDate/.') Equipment(EquipmentDetails)

CREATE TABLE #CancelDate (ID INT IDENTITY(1,1), CancelDate varchar(500))
INSERT INTO #CancelDate(CancelDate)
SELECT EquipmentDetails.value('.','varchar(500)') as CancelDate
FROM @doc.nodes('/Equipment/EquipmentRecord/CancelDate/.') Equipment(EquipmentDetails)

SELECT EquipmentType,MfgName,Model,ActDate,CancelDate 
FROM #EquipmentType ET
Inner Join #MfgName MN ON (ET.ID = MN.ID)
Inner Join #Model MO ON (MN.ID = MO.ID)
Inner Join #ActDate AD ON (MO.ID = AD.ID)
Inner Join #CancelDate CD ON (AD.ID = CD.ID)

DROP TABLE #EquipmentType
DROP TABLE #MfgName
DROP TABLE #Model
DROP TABLE #ActDate
DROP TABLE #CancelDate

但我想要一个简单的方法来做到这一点?

【问题讨论】:

    标签: sql-server xml types row calculated-columns


    【解决方案1】:

    以下查询应该有效:

    declare @X xml = 'your xml';
    
    select  x.r.value('(EquipmentType)[1]', 'varchar(100)') as [EquipmentType],
        x.r.value('(MfgName)[1]', 'varchar(500)') as [MfgName],
        x.r.value('(Model)[1]', 'varchar(500)') as [Model],
        x.r.value('(ActDate)[1]', 'varchar(500)') as [ActDate],
        x.r.value('(CancelDate)[1]', 'varchar(500)') as [CancelDate]
    from    @X.nodes('/Equipment/EquipmentRecord') as x(r);
    

    【讨论】:

      【解决方案2】:

      使用 OPENXML;请务必删除文档引用(sp_xml_removedocument)以避免内存泄漏:

      DECLARE @X XML = '<Equipment>
      <EquipmentRecord>
      <EquipmentType>E</EquipmentType><MfgName>APPLE iPH564WHT</MfgName><Model>885909600205</Model><ActDate>10/26/2012</ActDate><CancelDate />
      </EquipmentRecord>
      <EquipmentRecord>
      <EquipmentType>E</EquipmentType><MfgName>SAMSUNG D710 HANDSET KIT</MfgName><Model>SPHD710KIT</Model><ActDate>09/04/2012</ActDate><CancelDate>10/01/2012</CancelDate>
      </EquipmentRecord>
      <EquipmentRecord>
      <EquipmentType>E</EquipmentType><MfgName>BLACKBERRY 9670 PURPLE</MfgName><Model>SPRIM9670P</Model><ActDate>08/22/2012</ActDate><CancelDate>08/25/2012</CancelDate>
      </EquipmentRecord>
      </Equipment>'
      
      
      DECLARE @iX INT
      EXEC sp_xml_preparedocument @ix output, @x
      
      
      SELECT EquipmentType, MfgName, Model, ActDate, CancelDate = NULLIF(CancelDate, '1900-01-01')
      FROM OPENXML(@iX, '//EquipmentRecord', 2) 
      WITH (EquipmentType varchar(10),
              MfgName VARCHAR(100),
              Model VARCHAR(100),
              ActDate DATE,
              CancelDate date)
      
      EXEC sp_xml_removedocument @iX
      

      【讨论】:

      • 这很有效,谢谢。试图更多地了解 OPENXML。感谢您的知识。
      【解决方案3】:

      今天我有机会处理相同的要求。以下查询应该可以工作:

                      DECLARE @xmlData xml = '<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><row><EmpId>13</EmpId><EmpName>3372</EmpName></row></root> */';
                  DECLARE @allCols AS NVARCHAR(MAX),
                          @finalQry  AS NVARCHAR(MAX)
      
                  --Create temp table
                  CREATE table #tempTable
                      ([Value] varchar(50), [ColumnName] varchar(50));
      
                  --Get data from xml tag and insert data in temp table object 
                  Insert into #tempTable SELECT 
                  x.y.value('.', 'VARCHAR(MAX)') ColumnValue,
                      x.y.value('local-name(.)', 'VARCHAR(MAX)') ColumnName
                      FROM @xmlData.nodes('//*[text()]') AS x(y)
      
                  --Prepare rows into columns 
                  select @allCols = STUFF((SELECT ',' + QUOTENAME(ColumnName) 
                                      from #tempTable
                                      group by ColumnName
      
                              FOR XML PATH(''), TYPE
                              ).value('.', 'NVARCHAR(MAX)') 
                          ,1,1,'')
      
                  set @finalQry = N'SELECT ' + @allCols + N' from 
                               (
                                  select value, ColumnName
                                  from #tempTable
                              ) x
                              pivot 
                              (
                                  max(value)
                                  for ColumnName in (' + @allCols + N')
                              ) p '
      
                  exec sp_executesql @finalQry;
      
                  drop table #tempTable
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-09
        • 2021-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多