将 XML 格式数据存储在 SQL 服务器 table

Store XML format data in SQL Server table

我的查询是:

Declare @xml1 xml='

<Root>
  <Dir Name="Test">
    <Dir Name="Test1">
      <File>File1<Size>375</Size></File>
      <File>File2<Size>375</Size></File>
      <File>File3<Size>375</Size></File>
      <File>File4<Size>375</Size></File>
      <File>File5<Size>375</Size></File>
      <File>File6<Size>375</Size></File>
    </Dir>
    <Dir Name="Test2" />
  </Dir>
</Root>'

Declare @t table (xmld xml)
Insert into @t values (@xml1)

select * from @t

我想将 XML 数据存储在 SQL 服务器 table 中。

我的预期输出是:

FolderPath  FileName    FileSize    
--------------------------------
Test        -       -       
Test\Test1      File1       375     
Test\Test1      File2       375     
Test\Test1      File3       375     
Test\Test1      File4       375     
Test\Test1      File5       375
Test\Test2      -       -       

我按照thislink参考了,但没看懂。

有人可以帮我解决这个问题吗?

我提议更好的 XML 结构,不使用名称空间作为目录名称。甚至 <File> 标签在原始 XML.

中也不那么干净

SQL

DECLARE @xml xml=
N'<Root>
    <Dir name="Test">
        <Dir name="Test1">
            <File name="File1" Size="375"/>
            <File name="File2" Size="375"/>
            <File name="File3" Size="375"/>
        </Dir>
        <Dir name="Test2">
            <File name="File1" Size="575"/>
            <File name="File2" Size="75"/>
            <File name="File3" Size="75"/>
        </Dir>
        <Dir name="Test3"/>
    </Dir>
</Root>';

SELECT dir.c.value('@name','VARCHAR(100)') + '\' +
     subdir.c.value('@name','VARCHAR(100)') AS folderPath
    , fil.c.value('@name','VARCHAR(100)') AS [fileName]
    , fil.c.value('@Size','VARCHAR(100)') AS [fileSize]
FROM @xml.nodes('/Root/Dir') AS dir(c)
    CROSS APPLY dir.c.nodes('Dir') AS subdir(c)
    OUTER APPLY subdir.c.nodes('File') AS fil(c)
ORDER BY folderPath, [fileName];

Output

+------------+----------+----------+
| folderPath | fileName | fileSize |
+------------+----------+----------+
| Test\Test1 | File1    | 375      |
| Test\Test1 | File2    | 375      |
| Test\Test1 | File3    | 375      |
| Test\Test2 | File1    | 575      |
| Test\Test2 | File2    | 75       |
| Test\Test2 | File3    | 75       |
| Test\Test3 | NULL     | NULL     |
+------------+----------+----------+
Declare @xml1 xml='
<Root>
  <Dir xmlns="Test">
    <Dir xmlns="Test1">
      <File>File1<Size>175</Size></File>
      <File>File2<Size>275</Size></File>
      <File>File3<Size>375</Size></File>
      <File>File4<Size>475</Size></File>
      <File>File5<Size>575</Size></File>
      <File>File6<Size>675</Size></File>
    </Dir>
    <Dir xmlns="Test2" />
  </Dir>
</Root>';


select 
    dr.d.value('namespace-uri(.)', 'nvarchar(100)') as thedir,
    fl.f.value('text()[1]', 'nvarchar(100)') as thefile,    
    fl.f.value('*:Size[1]', 'nvarchar(100)') as thesize 
from @xml1.nodes('//*:Dir') as dr(d)
outer apply dr.d.nodes('./*:File') as fl(f);


Declare @xml2 xml='
<Root>
  <Dir Name="Test">
    <Dir Name="Test1">
      <File>File1<Size>101375</Size></File>
      <File>File2<Size>102375</Size></File>
      <File>File3<Size>103375</Size></File>
      <File>File4<Size>104375</Size></File>
      <File>File5<Size>105375</Size></File>
      <File>File6<Size>106375</Size></File>
    </Dir>
    <Dir Name="Test2" />
  </Dir>
</Root>';


select  
    dr.d.value('@Name[1]', 'nvarchar(100)') as thedir,
    fl.f.value('text()[1]', 'nvarchar(100)') as thefile,    
    fl.f.value('*:Size[1]', 'nvarchar(100)') as thesize 
from @xml2.nodes('//Dir') as dr(d)
outer apply dr.d.nodes('./File') as fl(f);