[英]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);
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.