简体   繁体   English

使用T-SQL将表转换为XML

[英]Convert Tables into XML using T-SQL

If found several questions about how to convert a table (or query) into XML, but none that showed how to start with one main table and join several one:many satellite tables, and from that generate XML that represents the hierarchical structure of the data. 如果找到有关如何将表(或查询)转换为XML的几个问题,但没有一个问题表明如何从一个主表开始并连接几个一个:许多附属表,并从中生成代表数据层次结构的XML 。 So I thought I'd share this solution now that I've figured it out. 所以我想我已经解决了,现在就分享这个解决方案。 If someone else has another way of doing this, please post another answer. 如果其他人还有其他方法,请发表其他答案。

Given this contrived data: 鉴于此人为设计的数据:

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)

.

Which looks like this in tabular form: 表格形式如下所示:

#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

.

I want to create an XML document that has one record for each recipe, and within each recipe element, I want a group of ingredients and another group of instructions, like this: 我想创建一个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>

This SQL creates the desired XML verbatim: 此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

I aliased the temp table names because using for xml auto on temp tables creates poorly named XML elements. 我对临时表名称起了别名,因为在临时表上使用for xml auto会创建名称不正确的XML元素。 This is how it looks: 它是这样的:

<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>

.

This SQL creates another version of the XML with all data as values instead of attributes, but in the same basic hierarchical structure: 此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

.

This is how it looks: 它是这样的:

<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>

Originally I tried placing the ingredients and instructions in the main query's from clause with an inner join to the recipe table. 最初,我尝试将配料和说明放置在主查询的from子句中,并将其inner join到配方表。 But the instructions were all nested within the ingredients, which were nested within the recipe. 但是说明全部嵌套在配料中,而配料嵌套在配方中。 When I moved them up to the select part of the query it straightened out the XML. 当我将它们移到查询的select部分时,它理顺了XML。

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

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