我想使用FOR XML将此输出复制为从数据库到XML的可伸缩查询

<root>
<Gear id='1'>
  <materials>
    <material>
      <id>2</id>
      <material_name> Leather </material_name>
    </material>
    <material>
      <id>1</id>
      <material_name> Bar</material_name>
    </material>
  </materials>

  <category>
    <id>1</id>
    <name>Warriors Weapon</name>
  </category>

  <equipment>
    <id> 1</id>
    <equipment_name> Claymore </equipment_name>
    <category> 1</category>
  </equipment>

  <recipes>
    <recipe>
      <equipment_id>1</equipment_id>
      <material_id>1</material_id>
      <material_quantity>12</material_quantity>
    </recipe>
    <recipe>
      <equipment_id> 1 </equipment_id>
      <material_id>2</material_id>
      <material_quantity>20</material_quantity>
    </recipe>
  </recipes>
</Gear>
<Gear id='2'>
    <materials>
      <material>
        <id>3</id>
        <material_name> Plank </material_name>
      </material>
    </materials>

    <category>
      <id>2</id>
      <name>Hunter Weapons</name>
    </category>

    <equipment>
      <id> 2</id>
      <equipment_name> Bow </equipment_name>
      <category> 2</category>
    </equipment>

    <recipes>
      <recipe>
        <equipment_id> 2 </equipment_id>
        <material_id>3</material_id>
        <material_quantity>36</material_quantity>
      </recipe>
    </recipes>
  </Gear>
<Gear id='3'>
    <materials>
      <material>
        <id>1</id>
        <material_name> Bar </material_name>
      </material>
    </materials>

    <category>
      <id>4</id>
      <name>Warrior Armour</name>
    </category>

    <equipment>
      <id> 4</id>
      <equipment_name> Knight Amor </equipment_name>
      <category> 4</category>
    </equipment>

    <recipes>
      <recipe>
        <equipment_id> 4 </equipment_id>
        <material_id>1</material_id>
        <material_quantity>16</material_quantity>
      </recipe>
    </recipes>
  </Gear>
</root>

这是我的实际数据库:

-- DDL and sample data population, start
USE tempdb;
GO

DROP TABLE IF EXISTS [dbo].[Categories];
DROP TABLE IF EXISTS [dbo].[Equipment];
DROP TABLE IF EXISTS [dbo].[Materials];
DROP TABLE IF EXISTS [dbo].[Recipe];

CREATE TABLE [dbo].[Categories](
    [id] [int] NULL,
    [name] [nvarchar](150) NULL
);
CREATE TABLE [dbo].[Equipment](
    [id] [int] NULL,
    [equipment_name] [nvarchar](50) NULL,
    [category_id] [int] NULL
);
CREATE TABLE [dbo].[Materials](
    [id] [int] NULL,
    [material_name] [nvarchar](50) NULL
);
CREATE TABLE [dbo].[Recipe](
    [equipment_id] [int] NULL,
    [material_id] [int] NULL,
    [material_quantity] [int] NULL
);

INSERT [dbo].[Categories] ([id], [name]) VALUES 
(1, N'Warrior Weapons'),
(2, N'Hunter Weapons'),
(3, N'Mage Weapons'),
(4, N'Warrior Armours');

INSERT [dbo].[Equipment] ([id], [equipment_name], [category_id]) VALUES 
(1, N'Claymore', 1),
(2, N'Bow', 2),
(3, N'Fire Staff', 3),
(4, N'Knight Armor', 4);

INSERT [dbo].[Materials] ([id], [material_name]) VALUES 
(1, N'Bar'),
(2, N'Leather'),
(3, N'Plank'),
(4, N'Cloth');

INSERT [dbo].[Recipe] ([equipment_id], [material_id], [material_quantity]) VALUES 
(1, 1, 20),
(1, 2, 12),
(2, 3, 32),
(3, 3, 16),
(3, 1, 8),
(4, 1, 16);
-- DDL and sample data population, end

因此,正如您所看到的,它就像一个名为Gear的类,包含一个material 数组、一个类别对象、一个设备对象和一个配方array.

如果添加了守护者护甲的新配方,我希望查询将其复制为具有上述 struct 的装备实例.

这样地:

<root>
[...]
<Gear id='4'>
  <materials>
      <material>
        <id>1</id>
        <material_name> Bar </material_name>
      </material>
    </materials>

    <category>
      <id>4</id>
      <name>Warrior Armour</name>
    </category>

    <equipment>
      <id> 5</id>
      <equipment_name> Guardian Amor </equipment_name>
      <category> 4</category>
    </equipment>

    <recipes>
      <recipe>
        <equipment_id> 5 </equipment_id>
        <material_id>1</material_id>
        <material_quantity>16</material_quantity>
      </recipe>
    </recipes>
  </Gear>
</root>

gear ID只是一个参考,所以我认为附加到真实属性(如category\u ID)并不重要.

推荐答案

请try 以下解决方案.

通过WHERE ...子句创建与父级的嵌套XML片段关系.

dbo.Equipment表是顶级父表.它用于组成<Gear id="N">个XML元素.

SQL

-- DDL and sample data population, start
USE tempdb;
GO

DROP TABLE IF EXISTS dbo.Categories;
DROP TABLE IF EXISTS dbo.Equipment;
DROP TABLE IF EXISTS dbo.Materials;
DROP TABLE IF EXISTS dbo.Recipe;

CREATE TABLE dbo.Categories(
    id int NULL,
    name nvarchar(150) NULL
);
CREATE TABLE dbo.Equipment(
    id int NULL,
    equipment_name nvarchar(50) NULL,
    category_id int NULL
);
CREATE TABLE dbo.Materials(
    id int NULL,
    material_name nvarchar(50) NULL
);
CREATE TABLE dbo.Recipe(
    equipment_id int NULL,
    material_id int NULL,
    material_quantity int NULL
);

INSERT dbo.Categories (id, name) VALUES 
(1, N'Warrior Weapons'),
(2, N'Hunter Weapons'),
(3, N'Mage Weapons'),
(4, N'Warrior Armours');

INSERT dbo.Equipment (id, equipment_name, category_id) VALUES 
(1, N'Claymore', 1),
(2, N'Bow', 2),
(3, N'Fire Staff', 3),
(4, N'Knight Armor', 4);

INSERT dbo.Materials (id, material_name) VALUES 
(1, N'Bar'),
(2, N'Leather'),
(3, N'Plank'),
(4, N'Cloth');

INSERT dbo.Recipe (equipment_id, material_id, material_quantity) VALUES 
(1, 1, 20),
(1, 2, 12),
(2, 3, 32),
(3, 3, 16),
(3, 1, 8),
(4, 1, 16);
-- DDL and sample data population, end

SELECT id AS [@id]
, (
    SELECT m.* 
    FROM dbo.Materials AS m 
        INNER JOIN dbo.Recipe AS r ON m.id = r.material_id
    WHERE r.equipment_id = e.id
    FOR XML PATH('material'), TYPE, ROOT('materials')
)
, (
    SELECT * 
    FROM dbo.Categories AS c
    WHERE c.id = e.category_id
    FOR XML PATH('category'), TYPE
)
, (
    SELECT id, equipment_name, category_id AS category
    FROM dbo.Equipment AS c
    WHERE c.id = e.id
    FOR XML PATH('equipment'), TYPE
)
, (
    SELECT *
    FROM dbo.Recipe AS r
    WHERE r.equipment_id = e.id
    FOR XML PATH('recipe'), TYPE, ROOT('recipes')
)
FROM dbo.Equipment AS e
FOR XML PATH('Gear'), TYPE, ROOT('root');

db<>fiddle

Csharp相关问答推荐

更新数据库中的对象失败,原因是:Microsoft. EntityFrame Core. GbUpdateConcurrencyResponse'

IComponition.获取IReadOnlyCollection的返回默认属性值

如何修改中间件或其注册以正确使用作用域服务?

为什么总输出就像12.3没有一分一样?

如何删除文件的基础上嵌入的时间戳嵌入文件名

具有以接口为其类型的属性的接口;类指定接口的实现,但无效

如何在我的C#应用程序中设置带有reactjs前端的SignalR服务器?

如何在CSharp中将json字符串转换为DataTable?

如何防止Visual Studio断点以红色突出显示到整行?

使用System.Text.Json进行序列化时发生StackOverflow异常

如何使用用于VS代码的.NET Maui扩展在我的iOS/Android设备或模拟器上进行调试?

Blazor Server.NET 8中的Blazore.FluentValidation问题

使用动态键从请求体反序列化JSON

为什么C#/MSBuild会自发地为不同的项目使用不同的输出路径?

Xamarin.Forms中具有类似AspectFill的图像zoom 的水平滚动视图

除非首先访问使用的终结点,否则本地API上的终结点不起作用

我什么时候不应该在Dispose中调用EgSuppressFinalize(This)?

无法创建工具窗口(用于VBIDE、VBA的COM加载项扩展)

为什么使用User.IsInRole()总是返回FALSE?

现在是否有一个.NET SDK等效于AsyncEx的AsyncLock?