Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 将1-to-n XML列转换为表格数据_Sql Server_Xml - Fatal编程技术网

Sql server 将1-to-n XML列转换为表格数据

Sql server 将1-to-n XML列转换为表格数据,sql-server,xml,Sql Server,Xml,我在MS SQL server上有一个表,它以XML格式保存有关报表的信息。该表由两个字段组成:第一个字段包含业务键,第二个字段包含XML格式的整个报表 这些报告每个都包括几张图片。XML保存有关这些图片的信息,例如它们的文件名、拍摄日期等。我想将这些信息提取到一个表中,其中每个记录只保存一张照片的信息。我已经找到了实现这一点的方法,但我一直遇到的问题是,我需要在这个表中为源表中的每条记录创建多条记录。我怎样才能做到这一点 业务密钥也需要在最终的表中。这个业务密钥可以在XML数据中找到,但在源表

我在MS SQL server上有一个表,它以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>

也许我误解了这个问题。但是,试试这个

create table t (
    [Key]      int,
    [Filename] nvarchar(max),
    [Date]     date
)
这不是一个答案,但足够重要,不会以评论结束:

对日期格式要非常小心。我不知道XML是如何生成的,但XML中的日期应该是ISO 8601 yyyy mm dd或yyyy 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日。甚至还有一个转换异常

根据评论,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;

回答得很好,我这边+1。一些小提示:您不需要。/,只需要.value'ReportKey[1],'int'就足够了,而且——如果我理解正确的话——有一个包含许多记录的表,不需要将结果存储在持久表中。也许你想在你的答案中反映这一点……谢谢你的回答,但我已经尝试过这种类型的解决方案,事后看来,我应该说明这一点。问题在于,我希望代码在整个源表上运行,并且对于源表中的每个记录,在查询结果中创建几个记录。您在这里编写的代码将只在一个XML文件上运行,而不是在多个XML文件上运行。我考虑过的一些解决方案是连接所有xml文件,尽管这将意味着巨大的性能损失,或者从查询结果中设置@xml变量。不过,我不太确定如何做到这一点。我已经检查了XML文件,它们是您提到的ISO格式。我编写的示例代码不考虑日期格式。尽管如此,感谢您的回复,我知道日期格式很重要,但并不是您给我的所有细节!多亏了你的最后一个解决方案,我今天才得以工作。我一定要投赞成票,把问题标为已解决。谢谢你的帮助,你太棒了!
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');
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;