简体   繁体   English

为在SQL Server中没有子节点的每个XML节点创建一列

[英]Create a column for every XML node that has no child nodes in SQL Server

I am trying to query an xml file in SSMS to create a table that consists of the first row being the list of all xml nodes, and the next row containing all of its values. 我正在尝试在SSMS中查询xml文件,以创建一个表,该表由第一行(所有XML节点的列表)和第二行(包含其所有值)组成。 The xml data will have a repeating node that will create a new row for each repeating node with that name. xml数据将具有一个重复节点,该节点将为每个具有该名称的重复节点创建一个新行。 Here's an example of the xml data: 这是xml数据的示例:

<Tests>
<TestAnswers>
    <Question1>
        <Name>Example</Name>
        <Age>23</Age>
        <Question1B>
            <Title>Singer</Title>
        </Questions1B>
    </Question1>
    <Question2>
        <Car></Car>
        <Model>Model 1</Model>
        <Question2B>
            <Year>1986</Year>
            <Manufactured></Manufactured>
        </Questions2B>
    </Question2>
</TestAnswers>
<TestAnswers>
    <Question1>
        <Name>Santa</Name>
        <Age></Age>
        <Question1B>
            <Title>Writer</Title>
        </Questions1B>
    </Question1>
    <Question2>
        <Car>This car</Car>
        <Model>Model2</Model>
        <Question2B>
            <Year></Year>
            <Manufactured></Manufactured>
        </Questions2B>
    </Question2>
</TestAnswers>
</Tests>

The table I want to create in SQL Server should look something like: 我要在SQL Server中创建的表应如下所示:

   |    Name     | Age |    Title    |    Car    |    Model    |   Year   |    Manufactured    |
-------------------------------------------------------------------------------------------------
 1 | Example     | 23  | Singer      |           | Model 1     | 1986     |                    |
 2 | Santa       |     | Writer      | This Car  | Model2      |          |                    |

There would be more rows that get created, as the xml file gets bigger with more information. 随着xml文件变得更大并包含更多信息,将创建更多行。 I don't want to create columns for xml nodes that contain child nodes. 我不想为包含子节点的xml节点创建列。

How can a write a query to perform this task? 如何编写查询来执行此任务?

UPDATE UPDATE

New XML use case, where there there will be two columns made with duplicate nodes: 新的XML用例,其中有两列包含重复的节点:

<Tests>
<TestAnswers>
    <Question1>
        <Name>Example</Name>
        <Age>23</Age>
        <Other>Other Text</Other>
        <Question1B>
            <Title>Singer</Title>
            <Other></Other>
        </Question1B>
    </Question1>
    <Question2>
        <Car></Car>
        <Model>Model 1</Model>
        <Question2B>
            <Year>1986</Year>
            <Manufactured></Manufactured>
        </Question2B>
    </Question2>
</TestAnswers>
<TestAnswers>
    <Question1>
        <Name>Santa</Name>
        <Age></Age>
        <Other></Other>
        <Question1B>
            <Title>Writer</Title>
            <Other>Text</Other>
        </Question1B>
    </Question1>
    <Question2>
        <Car>This car</Car>
        <Model>Model2</Model>
        <Question2B>
            <Year></Year>
            <Manufactured></Manufactured>
        </Question2B>
    </Question2>
</TestAnswers>
</Tests>

Is this XML under your control? 此XML是否在您的控制之下?

Besides the fact, that it is invalid (the closing tags for your sub-elements <Question2B> are in plural <Questions2B> ) there are severe design flaws... 除此之外,它是无效的(子元素<Question2B>的结束标记为复数<Questions2B> )还有严重的设计缺陷...

Most obvious is the name numbering like <Question1> and <Question2> ... 最明显的是名称编号,例如<Question1><Question2> ...

And please provide some more details, if the content may vary too. 如果内容也可能有所不同,请提供更多详细信息。 You are writing would be more rows with more information . 您正在编写的行将包含更多信息 Do you mean more of the same or might there be other columns or even other structures too? 您是说更多相同的意思还是可能会有其他列甚至其他结构?

Besides all this here are some general approaches to show the principles: 除了所有这些,这里还有一些通用的方法来显示原理:

DECLARE @xml XML=
N'<Tests>
<TestAnswers>
    <Question1>
        <Name>Example</Name>
        <Age>23</Age>
        <Question1B>
            <Title>Singer</Title>
        </Question1B>
    </Question1>
    <Question2>
        <Car></Car>
        <Model>Model 1</Model>
        <Question2B>
            <Year>1986</Year>
            <Manufactured></Manufactured>
        </Question2B>
    </Question2>
</TestAnswers>
<TestAnswers>
    <Question1>
        <Name>Santa</Name>
        <Age></Age>
        <Question1B>
            <Title>Writer</Title>
        </Question1B>
    </Question1>
    <Question2>
        <Car>This car</Car>
        <Model>Model2</Model>
        <Question2B>
            <Year></Year>
            <Manufactured></Manufactured>
        </Question2B>
    </Question2>
</TestAnswers>
</Tests>';

--this will return all answers row-by-row -这将返回所有的答案一行接一行

SELECT a.query('.')
FROM @xml.nodes('/Tests/TestAnswers') A(a);

--this will return all questions row-by-row -这将返回所有问题一行一行地

SELECT q.query('.')
FROM @xml.nodes('/Tests/TestAnswers') A(a)
OUTER APPLY a.nodes('*') B(q);

--this will return all nodes with an own text row-by-row -这将返回所有节点有自己的文本行由行

SELECT nd.query('.')
FROM @xml.nodes('/Tests/TestAnswers') A(a)
OUTER APPLY a.nodes('*') B(q)
OUTER APPLY q.nodes('//*[text()]') C(nd);

UPDATE UPDATE

Try this to get a list, then use PIVOT per aInx to get your tabular format: 尝试此操作以获取列表,然后使用每个aInx使用PIVOT获得表格格式:

WITH Answers AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS aInx
          ,a.query('.') AS a
    FROM @xml.nodes('/Tests/TestAnswers') A(a)
)
,Questions AS
(
    SELECT aInx
          ,q.query('.') AS q
    FROM Answers
    OUTER APPLY a.nodes('*') B(q)
)
SELECT aInx
      ,nd.value('local-name(.)','nvarchar(max)') AS NodeName
      ,nd.value('text()[1]','nvarchar(max)') AS NodeValue
FROM Questions
OUTER APPLY q.nodes('//*[text()]') C(nd);

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

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