sql - 将 XML 节点附加到 SQL 中的现有树
问题描述
我有一个将结果生成为 XML 列类型的 SQL 查询。我想更改该查询,以便通过将其附加到标题/开头来生成以下输出:
预期输出:
<Root>
<Header>
<MessageID>044</MessageID>
<TotalNumberOfTransactionsDeclared>1047</TotalNumberOfTransactionsDeclared>
<TotalAmountWithoutVAT>25771.79</TotalAmountWithoutVAT>
</Header>
<Entities>
<Entity>
<CustomerVATID>100050301900003</CustomerVATID>
<Leases>
<Lease>
<LeaseIdentifier>4374</LeaseIdentifier>
<Invoices>
<Invoice>
...
</Invoice>
</Invoices>
</Lease>
</Leases>
</Entity>
</Entities>
</Root>
现在无论发票之后的节点如何,我都能得到结果。<Invoices>
但是,我无法在标记之前添加根节点。我怎样才能做到这一点?
解决方案
如果您想完全控制您的 XML 输出,那么您可以使用显式和元素选项。这是很多工作,但您可以定义每个标签和值。
如何EXPLICIT
和ELEMENT
工作
样本数据
create table MyCustomers
(
CustomerId int,
Name nvarchar(10)
);
insert into MyCustomers (CustomerId, Name) values
(1, 'Alfred'),
(2, 'Batman');
create table MyInvoices
(
CustomerId int,
OrderId int,
Amount money
);
insert into MyInvoices (CustomerId, OrderId, Amount) values
(1, 101, 12.34),
(1, 102, 56.78),
(2, 201, 90.12);
解决方案
即使对于这个简单的示例,这很快也会变得很长。
-- customer 1 invoice XML
declare @CustomerId int = 1;
--root
select 1 as Tag,
0 as Parent,
null as [Root!1],
null as [Header!2],
null as [Customer!3!Id],
null as [Customer!3!Name!ELEMENT],
null as [Customer!3!InvoiceCount!ELEMENT],
null as [Invoices!4],
null as [Invoice!5!OrderId!ELEMENT],
null as [Invoice!5!Amount!ELEMENT]
union all
--root/header
select 2,
1,
null,
null,
null,
null,
null,
null,
null,
null
union all
--root/header/customer
select 3,
2,
null,
null,
mc.CustomerId,
mc.Name,
count(1) as InvoiceCount,
null,
null,
null
from MyCustomers mc
left join MyInvoices mi
on mi.CustomerId = mc.CustomerId
where mc.CustomerId = @CustomerId
group by mc.CustomerId, mc.Name
union all
--root/invoices
select 4,
1,
null,
null,
null,
null,
null,
null,
null,
null
union all
--root/invoices/invoice
select 5,
4,
null,
null,
mi.CustomerId,
null,
null,
null,
mi.OrderId,
mi.Amount
from MyInvoices mi
where mi.CustomerId = @CustomerId
for xml explicit;
结果
<Root><Header><Customer Id="1"><Name>Alfred</Name><InvoiceCount>2</InvoiceCount></Customer></Header><Invoices><Invoice><OrderId>101</OrderId><Amount>12.3400</Amount></Invoice><Invoice><OrderId>102</OrderId><Amount>56.7800</Amount></Invoice></Invoices></Root>
或者使用一些格式
<Root>
<Header>
<Customer Id="1">
<Name>Alfred</Name>
<InvoiceCount>2</InvoiceCount>
</Customer>
</Header>
<Invoices>
<Invoice>
<OrderId>101</OrderId>
<Amount>12.3400</Amount>
</Invoice>
<Invoice>
<OrderId>102</OrderId>
<Amount>56.7800</Amount>
</Invoice>
</Invoices>
</Root>
在行动中看到它:小提琴。
构建预期结果
解决方案
此解决方案示例重现了您的大部分预期输出。我使用所有常量值来保持简单。还有其他注释可以突出显示结构。
--root
select 1 as Tag, -- 1 = root
0 as Parent,
null as [Root!1], -- 1
null as [Header!2!MessageId!ELEMENT],
null as [Header!2!TotalNumberOfTransactionsDeclared!ELEMENT],
null as [Entities!3],
null as [Entity!4!CustomerVATId!ELEMENT],
null as [Leases!5],
null as [Lease!6!LeaseIdentifier!ELEMENT],
null as [Invoices!7],
null as [Invoice!8!OrderId!ELEMENT]
union all
--root/header
select 2, -- 2 = header
1,
null,
'044', -- 2!MessageID
'1047', -- 2!TotalNumberOfTransactionsDeclared
null, null, null, null, null, null
union all
--root/entities
select 3, -- 3 = entities
1,
null, null, null,
null, -- 3
null, null, null, null, null
union all
--root/entities/entity
select 4, -- 4 = entity
3,
null, null, null, null,
'100050301900003', -- 4!CustomerVATId
null, null, null, null
union all
--root/entities/entity/leases
select 5, -- 5 = leases
4,
null, null, null, null, null,
null, -- 5
null, null, null
union all
--root/entities/entity/leases/lease
select 6, -- 6 = lease
5,
null, null, null, null, null, null,
'4374', -- 6!LeaseIdentifier
null, null
union all
--root/entities/entity/leases/invoices
select 7, -- 7 = invoices
6,
null, null, null, null, null, null, null,
null, -- 7
null
union all
--root/entities/entity/leases/invoices/invoice
select 8, -- 8 = invoices
7,
null, null, null, null, null, null, null, null,
'INV0001' -- 8!OrderId
for xml explicit;
结果
<Root><Header><MessageId>044</MessageId><TotalNumberOfTransactionsDeclared>1047</TotalNumberOfTransactionsDeclared></Header><Entities><Entity><CustomerVATId>100050301900003</CustomerVATId><Leases><Lease><LeaseIdentifier>4374</LeaseIdentifier><Invoices><Invoice><OrderId>INV0001</OrderId></Invoice></Invoices></Lease></Leases></Entity></Entities></Root>
格式化后:
<Root>
<Header>
<MessageId>044</MessageId>
<TotalNumberOfTransactionsDeclared>1047</TotalNumberOfTransactionsDeclared>
</Header>
<Entities>
<Entity>
<CustomerVATId>100050301900003</CustomerVATId>
<Leases>
<Lease>
<LeaseIdentifier>4374</LeaseIdentifier>
<Invoices>
<Invoice>
<OrderId>INV0001</OrderId>
</Invoice>
</Invoices>
</Lease>
</Leases>
</Entity>
</Entities>
</Root>
推荐阅读
- javascript - 如何使用 Redux 只更新组件的一个实例?
- python - 如何将多个时间序列列转换为横截面数据?
- stripe-payments - 使用 SetupIntent 和 PaymentIntent 时,是否有等效于默认来源的方法?
- c# - 如何在 QnAMakerDialogbase 中获取 qna 响应:QnAMakerDialog
- python - 如何通过 Python 上的 Bitmex Websocket Api 接收实时数据?
- keycloak - Red Hat SSO 7.3.0.GA 的 Keycloak API 调用依赖项
- http - 戈朗。如何自动授权我的应用访问 spotify API?
- java - Intellij 中的 AWSToolkit,环境变量不起作用
- javascript - 使用 Jest 对仅在函数存在时调用函数的 JavaScript 进行单元测试
- python - 无法摆脱使用 asyncio 时出现的一些错误页面