将1对n XML列转换为表格数据

时间:2016-05-04 15:01:55

标签: sql-server xml

我在MS SQL服务器上有一个表,其中包含有关XML格式的报告的信息。该表由两个字段组成:第一个包含业务键,第二个包含XML格式的整个报表。

这些报告各包含几张图片。 XML保存有关这些图片的信息,例如文件名,截取日期等。我想将这些信息提取到一个表中,其中每个记录都包含有关一张照片的信息。我已经找到了非常接近的方法,但是我遇到的问题是我需要在这个表中为源表中的每个记录创建几条记录。我怎样才能做到这一点?

业务密钥也需要在决赛桌中。此业务密钥可以在XML数据中找到,但在源表中也有一个单独的字段(如前所述),可以在其中找到它。 XML列的内容可能类似于:

<Report>
  <ReportKey>0000001</ReportKey>
  [...]
  <Photos>
    <Photo>
      <Filename>1.jpg</Filename>
      <Date>01-01-2015</Date>
    </Photo>
    <Photo>
      <Filename>2.jpg</Filename>
      <Date>01-01-2016</Date>
    </Photo>
    [...]
  </Photos>
  [...]
</Report>

我希望决赛桌看起来像这样:

+---------+----------+------------+
|   Key   | Filename |    Date    |
+---------+----------+------------+
| 0000001 | 1.jpg    | 01-01-2015 |
| 0000001 | 2.jpg    | 01-01-2016 |
+---------+----------+------------+

3 个答案:

答案 0 :(得分:2)

这是的答案,但重要的是不要以评论结束:

对日期格式要非常小心。我不知道您的XML是如何生成的,但 XML中的日期应该是ISO 8601(yyyy-mm-ddyyyy-mm-ddThh:mm:ss)。

您的格式取决于文化!!!

试试这个:

set language french;
declare @xml as xml ='<x><Date>08-03-2015</Date></x>';
select @xml.value('(/x/Date)[1]','datetime');

set language english;
select @xml.value('(/x/Date)[1]','datetime');

你看,结果有所不同吗?

现在尝试将日期设置为3月13日。甚至还有转换异常!

答案 1 :(得分:1)

也许我误解了这个问题。不过,试试这个。

create table t (
    [Key]      int,
    [Filename] nvarchar(max),
    [Date]     date
)


declare @xml as xml = '<Report>
  <ReportKey>0000001</ReportKey>
  <Photos>
    <Photo>
      <Filename>1.jpg</Filename>
      <Date>01-01-2015</Date>
    </Photo>
    <Photo>
      <Filename>2.jpg</Filename>
      <Date>01-01-2016</Date>
    </Photo>
  </Photos>
</Report>'

insert into t ([Key], [Filename], [Date])
select n.value('ReportKey[1]', 'int')
     , x.value('Filename[1]',  'nvarchar(max)')
     , x.value('Date[1]',      'date')   
from @xml.nodes('Report') as r(n)
cross apply r.n.nodes('Photos/Photo') as t(x)

select * from t

答案 2 :(得分:1)

根据评论,OP需要一种方法从表行数据中获取此信息并且现有答案不够解决。

你可以试试这个:

CREATE TABLE #YourTable(BusinessKey VARCHAR(10),ReportData XML);
INSERT INTO #YourTable VALUES
 ('0000001','<Report>
              <ReportKey>0000001</ReportKey>
              <Photos>
                <Photo>
                  <Filename>1.jpg</Filename>
                  <Date>2015-01-01</Date>
                </Photo>
                <Photo>
                  <Filename>2.jpg</Filename>
                  <Date>2016-05-13</Date>
                </Photo>
              </Photos>
            </Report>')
,('0000002','<Report>
              <ReportKey>0000002</ReportKey>
              <Photos>
                <Photo>
                  <Filename>3.jpg</Filename>
                  <Date>2015-04-19</Date>
                </Photo>
                <Photo>
                  <Filename>4.jpg</Filename>
                  <Date>2016-12-10</Date>
                </Photo>
              </Photos>
            </Report>');

SELECT BusinessKey AS Table_Key 
      ,ReportData.value('(/Report/ReportKey)[1]','varchar(10)') AS XML_Key
      ,Photo.value('Filename[1]','varchar(max)') AS Photo_Filename
      ,Photo.value('Date[1]','date') AS Photo_Date
FROM #YourTable
CROSS APPLY ReportData.nodes('/Report/Photos/Photo') AS A(Photo);
GO

DROP TABLE #YourTable;