使用 T-SQL 将表转换为 XML
Posted
技术标签:
【中文标题】使用 T-SQL 将表转换为 XML【英文标题】:Convert Tables into XML using T-SQL 【发布时间】:2014-07-12 02:08:01 【问题描述】:如果发现了几个关于如何将表(或查询)转换为 XML 的问题,但没有一个显示如何从一个主表开始并连接多个 one:many 附属表,并从中生成表示层次结构的 XML的数据。所以我想既然我已经弄清楚了,我会分享这个解决方案。如果其他人有其他方法,请发布另一个答案。
鉴于这些人为的数据:
create table #recipe (id int, name varchar(10))
create table #ingredient (recipe_id int, name varchar(30), quantity varchar(20), sort int)
create table #instruction (recipe_id int, task varchar(32), sort int)
insert into #recipe values (1, 'pizza'), (2, 'omelet')
insert into #ingredient values (1, 'pizza dough', '1 package', 1),
(1, 'tomato sauce', '1 can', 2),
(1, 'favorite toppings', 'you choose', 3),
(2, 'eggs', 'three', 1),
(2, 'a bunch of other ingredients', 'you choose', 2)
insert into #instruction values (1, 'pre-bake pizza dough', 1),
(1, 'add tomato sauce', 2),
(1, 'add toppings', 3),
(1, 'bake a little longer', 4),
(2, 'break eggs into mixing bowl', 1),
(2, 'beat yolks and whites together', 2),
(2, 'pour into large sauce pan', 3),
(2, 'add other ingredients', 4),
(2, 'fold in half', 5),
(2, 'cook until done', 6)
.
表格形式如下:
#recipe
id name
----------- ----------
1 pizza
2 omelet
.
#ingredient
recipe_id name quantity sort
----------- ------------------------------ -------------------- -----------
1 pizza dough 1 package 1
1 tomato sauce 1 can 2
1 favorite toppings you choose 3
2 eggs three 1
2 a bunch of other ingredients you choose 2
.
#instruction
recipe_id task sort
----------- -------------------------------- -----------
1 pre-bake pizza dough 1
1 add tomato sauce 2
1 add toppings 3
1 bake a little longer 4
2 break eggs into mixing bowl 1
2 beat yolks and whites together 2
2 pour into large sauce pan 3
2 add other ingredients 4
2 fold in half 5
2 cook until done 6
.
我想创建一个 XML 文档,其中每个食谱都有一个记录,并且在每个食谱元素中,我想要一组成分和另一组指令,如下所示:
<recipes>
<recipe id="2" name="omelet">
<ingredients>
<ingredient name="eggs" quantity="three" />
<ingredient name="a bunch of other ingredients" quantity="you choose" />
</ingredients>
<instructions>
<instruction task="break eggs into mixing bowl" />
<instruction task="beat yolks and whites together" />
<instruction task="pour into large sauce pan" />
<instruction task="add other ingredients" />
<instruction task="fold in half" />
<instruction task="cook until done" />
</instructions>
</recipe>
<recipe id="1" name="pizza">
<ingredients>
<ingredient name="pizza dough" quantity="1 package" />
<ingredient name="tomato sauce" quantity="1 can" />
<ingredient name="favorite toppings" quantity="you choose" />
</ingredients>
<instructions>
<instruction task="pre-bake pizza dough" />
<instruction task="add tomato sauce" />
<instruction task="add toppings" />
<instruction task="bake a little longer" />
</instructions>
</recipe>
</recipes>
【问题讨论】:
【参考方案1】:此 SQL 逐字创建所需的 XML:
select recipe.*,
(
select ingredient.name, ingredient.quantity
from #ingredient ingredient
where recipe.id = ingredient.recipe_id
order by ingredient.sort
for xml auto, root('ingredients'), type
),
(
select instruction.task
from #instruction instruction
where recipe.id = instruction.recipe_id
order by instruction.sort
for xml auto, root('instructions'), type
)
from #recipe as recipe
order by recipe.name
for xml auto, root('recipes'), type
我为临时表名称起了别名,因为在临时表上使用 for xml auto
会创建名称不佳的 XML 元素。看起来是这样的:
<recipes>
<recipe id="2" name="omelet">
<ingredients>
<ingredient name="eggs" quantity="three" />
<ingredient name="a bunch of other ingredients" quantity="you choose" />
</ingredients>
<instructions>
<instruction task="break eggs into mixing bowl" />
<instruction task="beat yolks and whites together" />
<instruction task="pour into large sauce pan" />
<instruction task="add other ingredients" />
<instruction task="fold in half" />
<instruction task="cook until done" />
</instructions>
</recipe>
<recipe id="1" name="pizza">
<ingredients>
<ingredient name="pizza dough" quantity="1 package" />
<ingredient name="tomato sauce" quantity="1 can" />
<ingredient name="favorite toppings" quantity="you choose" />
</ingredients>
<instructions>
<instruction task="pre-bake pizza dough" />
<instruction task="add tomato sauce" />
<instruction task="add toppings" />
<instruction task="bake a little longer" />
</instructions>
</recipe>
</recipes>
.
此 SQL 创建 XML 的另一个版本,其中所有数据都作为值而不是属性,但具有相同的基本层次结构:
select recipe.*,
(
select ingredient.name, ingredient.quantity
from #ingredient ingredient
where recipe.id = ingredient.recipe_id
order by ingredient.sort
for xml path('ingredient'), root('ingredients'), type
),
(
select instruction.task
from #instruction instruction
where recipe.id = instruction.recipe_id
order by instruction.sort
for xml path('instruction'), root('instructions'), type
)
from #recipe as recipe
order by recipe.name
for xml path('recipe'), root('recipes'), type
.
看起来是这样的:
<recipes>
<recipe>
<id>2</id>
<name>omelet</name>
<ingredients>
<ingredient>
<name>eggs</name>
<quantity>three</quantity>
</ingredient>
<ingredient>
<name>a bunch of other ingredients</name>
<quantity>you choose</quantity>
</ingredient>
</ingredients>
<instructions>
<instruction>
<task>break eggs into mixing bowl</task>
</instruction>
<instruction>
<task>beat yolks and whites together</task>
</instruction>
<instruction>
<task>pour into large sauce pan</task>
</instruction>
<instruction>
<task>add other ingredients</task>
</instruction>
<instruction>
<task>fold in half</task>
</instruction>
<instruction>
<task>cook until done</task>
</instruction>
</instructions>
</recipe>
<recipe>
<id>1</id>
<name>pizza</name>
<ingredients>
<ingredient>
<name>pizza dough</name>
<quantity>1 package</quantity>
</ingredient>
<ingredient>
<name>tomato sauce</name>
<quantity>1 can</quantity>
</ingredient>
<ingredient>
<name>favorite toppings</name>
<quantity>you choose</quantity>
</ingredient>
</ingredients>
<instructions>
<instruction>
<task>pre-bake pizza dough</task>
</instruction>
<instruction>
<task>add tomato sauce</task>
</instruction>
<instruction>
<task>add toppings</task>
</instruction>
<instruction>
<task>bake a little longer</task>
</instruction>
</instructions>
</recipe>
</recipes>
最初我尝试将配料和说明放在主查询的from
子句中,并在配方表中添加inner join
。但是说明都嵌套在成分中,成分嵌套在配方中。当我将它们移到查询的 select
部分时,它理顺了 XML。
【讨论】:
我怀疑这个例子对其他人有任何用处。以上是关于使用 T-SQL 将表转换为 XML的主要内容,如果未能解决你的问题,请参考以下文章
T-SQL谜题:将表的每一行作为内联函数的输入传递,并使用UNION ALL开发新的堆栈数据集