简体   繁体   English

如何从 SQL Server 中的多个 XML 文件中读取数据?

[英]How to read data from multiple XML files in SQL Server?

Background :背景 :

I want to obtain data from multiple XML files (stored in database) and fetch them into one result set.我想从多个 XML 文件(存储在数据库中)获取数据并将它们提取到一个结果集中。 The basic working solution, with single XML file looks similar to this one :具有单个 XML 文件的基本工作解决方案与此类似:

DECLARE @xml xml
SET @xml = 
(SELECT TOP 1 convert(varchar(max), convert(varbinary(max), [XML_FILE]))
  FROM [SOME_TABLE])
SELECT
    b.value('(./SomeNode/text())[1]','nvarchar(100)')) as [Some_Text],
    b.value('(./SomeOtherNode/@VAL)[1]','int')) as [Some_Val]
FROM @xml.nodes('Example/File') as a(b)

Obviously this won't work with SELECT that returns many rows (many XML files).显然,这不适用于返回许多行(许多 XML 文件)的 SELECT。 Sub-optimal solution could be achieved using cursor (iterating over collection -> pushing data into temporary table -> SELECT (*) FROM temporary_table) however, I believe thats not necessary and more straightforward solution can be achieved.使用游标可以实现次优解决方案(迭代集合 -> 将数据推入临时表 -> SELECT (*) FROM temporal_table)但是,我相信这不是必需的,可以实现更直接的解决方案。

Question :题 :

How to fetch data from multiple XML files, obtained via SELECT query, into a single result-set, without using cursor?如何在不使用游标的情况下从通过 SELECT 查询获得的多个 XML 文件中获取数据到单个结果集中?

FILE_NAME ||   Value 1   ||   Value 2  || ...
----------------------------------------------
XML_FILE_1 || Node1Value || Node2Value || ...
XML_FILE_2 || Node1Value || Node2Value || ...

I've found solution thanks to @Shnugo answer.感谢@Shnugo 的回答,我找到了解决方案。

If the type of xml-container column is different then XML MS-SQL dedicated one, then double CROSS APPLY should be performed.如果 xml-container 列的类型与 XML MS-SQL 专用列不同,则应执行双 CROSS APPLY。 Example below :下面的例子:

DECLARE @mockup TABLE(ID INT IDENTITY, [XML_DATA] VARBINARY(MAX));
INSERT INTO @mockup VALUES('<Example><File><SomeNode>blah</SomeNode><SomeOtherNode VAL="1"/></File></Example>')
                         ,('<Example><File><SomeNode>blub</SomeNode><SomeOtherNode VAL="2"/></File></Example>')

SELECT
    ID,
    b.value('(SomeNode/text())[1]','nvarchar(100)') as [Some_Text],
    b.value('(SomeOtherNode/@VAL)[1]','int') as [Some_Val]
FROM @mockup
CROSS APPLY (SELECT CAST(convert(varbinary(max), [XML_DATA]) as XML)) as RAW_XML(xml_field)
CROSS APPLY RAW_XML.xml_field.nodes('Example/File') as a(b) 

For sure the CURSOR approach is not needed and would be wrong entirely...当然不需要CURSOR方法,而且完全是错误的......

The general approach should be something like this:一般方法应该是这样的:

SELECT
    b.value('(./SomeNode/text())[1]','nvarchar(100)') as [Some_Text],
    b.value('(./SomeOtherNode/@VAL)[1]','int') as [Some_Val]
FROM [SOME_TABLE]
CROSS APPLY [XML_FILE].nodes('Example/File') as a(b);

But there are questions open:但还有一些问题没有解决:

  • Speaking about xml files is a bit bewildering... I hope to get this correctly, that all these XMLs are living in a table's column.谈到xml 文件有点令人困惑……我希望能正确理解,所有这些 XML 都存在于表的列中。
  • If the first is true: Are all these XMLs of the same structure?如果第一个是真的:所有这些 XML 都具有相同的结构吗? if not you will need some kind of filtering.如果不是,您将需要某种过滤。
  • is the XML in your table's column a native XML-type already?表列中的 XML 是否已经是原生 XML 类型? Your example uses CONVERT extensivly... You will need a native XML in order to use .nodes()您的示例广泛使用CONVERT ......您需要一个本机 XML 才能使用.nodes()
  • If there's no native XML: Do you have to deal with invalid / uncastable data?如果没有原生 XML:您是否必须处理无效/不可转换的数据?
  • Are there rows with no data but you want to see them anyway?是否有没有数据但您仍想查看它们的行? In this case you can try OUTER APPLY instead of CROSS APPLY .在这种情况下,您可以尝试OUTER APPLY而不是CROSS APPLY

For demonstration a running stand-alone mockup:为了演示正在运行的独立模型:

DECLARE @mockup TABLE(ID INT IDENTITY, [XML_FILE] XML);
INSERT INTO @mockup VALUES('<Example><File><SomeNode>blah</SomeNode><SomeOtherNode VAL="1"/></File></Example>')
                         ,('<Example><File><SomeNode>blub</SomeNode><SomeOtherNode VAL="2"/></File></Example>')

SELECT
    ID,
    b.value('(SomeNode/text())[1]','nvarchar(100)') as [Some_Text],
    b.value('(SomeOtherNode/@VAL)[1]','int') as [Some_Val]
FROM @mockup
CROSS APPLY [XML_FILE].nodes('Example/File') as a(b)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM