动态读取SQL Server中的xml数据

时间:2014-04-24 11:18:45

标签: sql sql-server xml

我有一个像下面这样的xml数据模式。我只需要读取xml数据并将其存储在临时表中。列是动态的(下面的列只是样本),但属性是常量。我期待下面的结果。

BandCode BandDescription BandName Code     Country Currency Pay1_11  Pay1_12  Pay1_13  Pay1_14  Pay1_15
123440   Band-A          Band1    1234567  Germany  US      10000.00 10000.00 10000.00 10000.00 10000.00  
123441   Band-B          Band2    1234567  Germany  US      10000.00 10000.00 10000.00 10000.00 10000.00 

示例xml数据

<CookedData>
   <row RowNumber="1">
     <Column DestinationColumnCode="BandCode" DataType="VARCHAR(3000)" Value="123440"/>
     <Column DestinationColumnCode="BandDescription" DataType="VARCHAR(3000)" Value="Band-A"/>
     <Column DestinationColumnCode="BandName" DataType="VARCHAR(3000)" Value="Band1"/>
     <Column DestinationColumnCode="Code" DataType="VARCHAR(3000)" Value="1234567"/>
     <Column DestinationColumnCode="Country" DataType="VARCHAR(3000)" Value="Germany"/>
     <Column DestinationColumnCode="Currency" DataType="MONEY" Value="US"/>
     <Column DestinationColumnCode="Pay1_11" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_12" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_13" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_14" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_15" DataType="MONEY" Value="10000.00"/>
   </row>
   <row RowNumber="2">
     <Column DestinationColumnCode="BandCode" DataType="VARCHAR(3000)" Value="123441"/>
     <Column DestinationColumnCode="BandDescription" DataType="VARCHAR(3000)" Value="Band-B"/>
     <Column DestinationColumnCode="BandName" DataType="VARCHAR(3000)" Value="Band2"/>
     <Column DestinationColumnCode="Code" DataType="VARCHAR(3000)" Value="1234567"/>
     <Column DestinationColumnCode="Country" DataType="VARCHAR(3000)" Value="Germany"/>
     <Column DestinationColumnCode="Currency" DataType="MONEY" Value="US"/>
     <Column DestinationColumnCode="Pay1_11" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_12" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_13" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_14" DataType="MONEY" Value="10000.00"/>
     <Column DestinationColumnCode="Pay1_15" DataType="MONEY" Value="10000.00"/>
   </row>
</CookedData>

我已经研究过如何执行此操作,但我找到的示例代码仅适用于静态列。

1 个答案:

答案 0 :(得分:1)

您必须动态构建查询。

此代码使用第一行节点/CookedData/row[1]/Column中的信息来获取列名和数据类型。

这不适用于您的XML,因为您已将money指定为列Currency的数据类型。您需要将其更改为其他内容。

declare @SQL nvarchar(max) =
'select '+
  (
  select ',T.X.value(''Column[@DestinationColumnCode = "'+T.ColName+'"][1]/@Value'','''+T.DataType+''') as '+quotename(T.ColName)
  from (
       select T.X.value('@DestinationColumnCode', 'nvarchar(128)') as ColName,
              T.X.value('@DataType', 'nvarchar(128)') as DataType
       from @XML.nodes('/CookedData/row[1]/Column') as T(X)
       ) as T
  for xml path(''), type
  ).value('substring(text()[1], 2)', 'nvarchar(max)')+' '+
'from @XML.nodes(''/CookedData/row'') as T(X)';

exec sp_executesql @SQL, N'@XML xml', @XML;

SQL Fiddle

动态构建的查询如下所示:

select T.X.value('Column[@DestinationColumnCode = "BandCode"][1]/@Value','VARCHAR(3000)') as [BandCode],
       T.X.value('Column[@DestinationColumnCode = "BandDescription"][1]/@Value','VARCHAR(3000)') as [BandDescription],
       T.X.value('Column[@DestinationColumnCode = "BandName"][1]/@Value','VARCHAR(3000)') as [BandName],
       T.X.value('Column[@DestinationColumnCode = "Code"][1]/@Value','VARCHAR(3000)') as [Code],
       T.X.value('Column[@DestinationColumnCode = "Country"][1]/@Value','VARCHAR(3000)') as [Country],
       T.X.value('Column[@DestinationColumnCode = "Currency"][1]/@Value','CHAR(2)') as [Currency],
       T.X.value('Column[@DestinationColumnCode = "Pay1_11"][1]/@Value','MONEY') as [Pay1_11],
       T.X.value('Column[@DestinationColumnCode = "Pay1_12"][1]/@Value','MONEY') as [Pay1_12],
       T.X.value('Column[@DestinationColumnCode = "Pay1_13"][1]/@Value','MONEY') as [Pay1_13],
       T.X.value('Column[@DestinationColumnCode = "Pay1_14"][1]/@Value','MONEY') as [Pay1_14],
       T.X.value('Column[@DestinationColumnCode = "Pay1_15"][1]/@Value','MONEY') as [Pay1_15] 
from @XML.nodes('/CookedData/row') as T(X)