sql-server - 将 XML 多个嵌套节点插入 SQL 表
问题描述
我有一个具有以下结构的 XML 文件:
<NIACList>
<NIAC>
<Number></Number>
<SubmissionDate></SubmissionDate>
<ExpirationDate />
<IssuerIDNO></IssuerIDNO>
<IssuerName></IssuerName>
<SuspensionPeriod/>
<Cessation>
<Basis />
<Date />
</Cessation>
<Merchant>
<IDNx></IDNx>
<Name></Name>
<Address>
<Region></Region>
<Locality></Locality>
<Street></Street>
<House></House>
<Block />
<Flat />
<Phone />
<Fax />
<Email />
</Address>
</Merchant>
<CommercialUnit>
<IDNx />
<Name />
<Type></Type>
<Area></Area>
<Location></Location>
<Address>
<Region></Region>
<Locality></Locality>
<Street></Street>
<House></House>
<Block />
<Flat />
</Address>
<Activities>
<Activity>
<Code></Code>
<Name></Name>
</Activity>
</Activities>
<Goods>
<Good>
<Name></Name>
</Good>
</Goods>
<WorkProgram />
<PublicSupplyUnit>
<Capacity />
<TerraceCapacity />
</PublicSupplyUnit>
<TradingAlcohol />
<TradingBeer />
<TradingTobaccoProducts />
<AmbulatoryTrading />
<MobileUnitTrading></MobileUnitTrading>
<MobileUnit>
<Type />
<Length />
<Width />
<Height />
</MobileUnit>
<CommercialApparatusTrading></CommercialApparatusTrading>
<CommercialApparatus>
<Count />
<Length />
<Width />
<Height />
</CommercialApparatus>
</CommercialUnit>
<Modifications />
</NIAC>
</NIACList>
基于这个 XML 结构,我在 MS SQL 中创建了一个带有以下表脚本的数据库:
create table NIAC (
IDNIAC int identity primary key,
Number nvarchar(80) null,
SubmissionDate datetime2 null,
ExpirationDate datetime2 null,
IssuerIDNO nvarchar(max) null,
IssuerName nvarchar(60) null,
SuspensionPeriod datetime2 null,
Modifications nvarchar(60) null
);
create table Cessation (
IdCessation int identity primary key,
Basis nvarchar(60) null,
Date date null,
IDNIAC int
);
create table Merchant (
IdMerchant int identity primary key,
IDNX nvarchar(max) null,
Name nvarchar(max) null,
WorkProgram datetime2 null,
IdAddress int
);
create table Address (
IdAddress int identity primary key,
Region nvarchar(60) null,
Locality nvarchar(50) null,
Street nvarchar (60) null,
House nvarchar (10) null,
Block nvarchar (10) null,
Flat nvarchar(10) null,
Phone nvarchar(30) null,
Fax nvarchar(60) null,
Email nvarchar(60) null
);
create table CommercialUnit (
IDCommercialUt int identity primary key,
IDNx nvarchar(90) null,
Name nvarchar(90) null,
Type nvarchar(90) null,
Area int null,
Location nvarchar(max) null,
TerraceCapacity float null,
TradingAlcohol bit null,
TradingBeer bit null,
TradingTobaccoProducts bit null,
AmbulatoryTrading bit null,
MobileUnitTrading bit null,
CommercialApparatusTrading bit null,
IdAddress int,
IDActivities int ,
IDGoods int ,
IDMobileUnit int ,
IDCommercial int ,
IDPSU int
);
create table Activities (
IDActivities int identity primary key,
Code nvarchar (90) null,
Name nvarchar (90) null
);
create table Goods(
IDGoods int identity primary key,
Name nvarchar(60) null
);
create table MobileUnit(
IDMobileUnit int identity primary key,
Type numeric null,
Length numeric null,
Width numeric null,
Height numeric null
);
create table CommercialApparatus(
IDCommercial int identity primary key,
Count float null,
Length numeric null,
Width numeric null,
Height numeric null
);
create table PublicSupplyUnit(
IDPSU int identity primary key,
Capacity float,
TerraceCapacity float
);
create table NIACList(
ID int identity primary key,
IDNIAC int not null,
IDNIACList int
);
create table NIACToComponents(
IDNIACToComponents int identity primary key,
IDNIAC int,
IDAddressMerchant int,
IDAddressCU int,
IdCessation int,
IdMerchant int,
IDCommercialUt int,
IDActivities int,
IDGoods int,
IDMobileUnit int,
IDCommercial int,
IDPSU int,
);
drop table if exists NIAC;
drop table if exists NIACList;
drop table if exists Cessation;
drop table if exists Merchant;
drop table if exists Address;
drop table if exists CommercialApparatus;
drop table if exists CommercialUnit;
drop table if exists Goods;
drop table if exists MobileUnit;
drop table if exists PublicSupplyUnit;
drop table if exists Activities;
drop table if exists NIACToComponents;
alter table dbo.NIACList
add constraint FK_ID_NIAC
foreign key (IDNIAC) references dbo.NIAC(IDNIAC)
on delete cascade
on update cascade;
alter table dbo.Cessation
Add constraint FK_IDNIAC
foreign key(IDNIAC) references dbo.NIAC(IDNIAC)
on delete cascade
on update cascade;
alter table dbo.Merchant
add constraint FK_IdAdress
foreign key(IdAddress) references dbo.Address(IdAddress)
on delete cascade
on update cascade;
alter table dbo.CommercialUnit
add constraint FK_IdAddress
foreign key(IdAddress) references dbo.Address(IdAddress)
on delete cascade
on update cascade;
alter table dbo.CommercialUnit
add constraint FK_Activities
foreign key(IDActivities) references dbo.Activities(IDActivities)
on delete cascade
on update cascade;
alter table dbo.CommercialUnit
add constraint FK_IDGoods
foreign key(IDGoods) references dbo.Goods(IDGoods)
on delete cascade
on update cascade;
alter table dbo.CommercialUnit
add constraint FK_IDMobileUnit
foreign key(IDMobileUnit) references dbo.MobileUnit(IDMobileUnit)
on delete cascade
on update cascade;
alter table dbo.CommercialUnit
add constraint FK_IDCommercial
foreign key(IDCommercial) references dbo.CommercialApparatus(IDCommercial)
on delete cascade
on update cascade;
alter table dbo.CommercialUnit
add constraint FK_IDPSU
foreign key(IDPSU) references dbo.PublicSupplyUnit(IDPSU)
on delete cascade
on update cascade;
假设有很多NIAC
into NIACList
(50-100 个节点),我想从我的 XML 文件中插入数据。我INSERT
只对一个进行了操作NIAC
,使用 3 个过程(2 个用于插入表,1 个用于调用两个过程并将插入数据的表的所有 ID 插入另一个表,因此所有数据都将被链接给 NIAC)。
将数据插入表的脚本如下: 1 个过程:
ALTER procedure [dbo].[InsertXMLMultipleTables]
(
@idAddress1 int out,
@idAddress2 int out,
@idactivities int out,
@idgoods int out,
@idmobileunit int out,
@idcommercial int out,
@idcommercialut int out,
@idpsu int out,
@idmerchant int out,
@xml xml
)
as
set @xml = *
begin
set nocount on
INSERT INTO Activities(Code,Name)
SELECT
Code=c.value('Code[1]','nvarchar(90)') ,
Name=c.value('Name[1]','nvarchar(90)')
FROM @xml.nodes('/NIACList/NIAC/CommercialUnit/Activities/Activity') Activities(c)
set @IDActivities=SCOPE_IDENTITY();
end;
begin
INSERT INTO Address(Region,Locality,Street,House,Block,Flat,Phone,Fax,Email)
SELECT
Region=c.value('Region[1],','nvarchar(60)'),
Locality=c.value('Locality[1],','nvarchar(50)') ,
Street=c.value('Street[1],','nvarchar(60)') ,
House=c.value('House[1],','nvarchar(10)') ,
Block=c.value('Block[1],','nvarchar(10)') ,
Flat=c.value('Flat[1],','nvarchar(10)') ,
Phone=c.value('Phone[1],','nvarchar(30)') ,
Fax=c.value('Fax[1],','nvarchar(60)') ,
Email=c.value('Email[1],','nvarchar(60)')
FROM @xml.nodes('NIACList/NIAC/Merchant/Address') Address(c)
set @idAddress1=SCOPE_IDENTITY();
end;
begin
INSERT INTO Merchant(IDNX,Name,WorkProgram,IdAddress)
SELECT
Region=c.value('IDNx[1],','nvarchar(max)'),
Locality=c.value('Name[1],','nvarchar(max)') ,
Street=c.value('WorkProgram[1],','datetime2') ,
@idAddress1
FROM @xml.nodes('NIACList/NIAC/Merchant') Merchant(c)
set @idmerchant=SCOPE_IDENTITY();
end;
begin
INSERT INTO Address(Region,Locality,Street,House,Block,Flat,Phone,Fax,Email)
SELECT
Region=c.value('Region[1],','nvarchar(60)'),
Locality=c.value('Locality[1],','nvarchar(50)') ,
Street=c.value('Street[1],','nvarchar(60)') ,
House=c.value('House[1],','nvarchar(10)') ,
Block=c.value('Block[1],','nvarchar(10)') ,
Flat=c.value('Flat[1],','nvarchar(10)') ,
Phone=c.value('Phone[1],','nvarchar(30)') ,
Fax=c.value('Fax[1],','nvarchar(60)') ,
Email=c.value('Email[1],','nvarchar(60)')
FROM @xml.nodes('NIACList/NIAC/CommercialUnit/Address') Address(c)
set @idAddress2=SCOPE_IDENTITY();
set @idcommercialut=SCOPE_IDENTITY();
end;
begin
INSERT INTO CommercialApparatus(Count,Length,Width,Height )
SELECT
Count =c.value('Type[1]','int') ,
Length=c.value('Length[1]','int') ,
Width=c.value('Width[1]','int') ,
Height=c.value('Height[1]','int')
FROM @xml.nodes('/NIACList/NIAC/CommercialUnit/CommercialApparatus') CommercialApparatus(c)
set @idcommercial=SCOPE_IDENTITY();
end;
begin
INSERT INTO Goods(Name)
SELECT
Name=c.value('Name[1]','nvarchar(60)')
FROM @xml.nodes('/NIACList/NIAC/CommercialUnit/Goods/Good') Goods(c)
set @idgoods=SCOPE_IDENTITY();
end;
begin
INSERT INTO MobileUnit(Type,Length,Width,Height )
SELECT
Type =c.value('Type[1]','int') ,
Length=c.value('Length[1]','int') ,
Width=c.value('Width[1]','int') ,
Height=c.value('Height[1]','int')
FROM @xml.nodes('/NIACList/NIAC/CommercialUnit/MobileUnit') MobileUnit(c)
set @idmobileunit=SCOPE_IDENTITY();
end;
begin
INSERT INTO PublicSupplyUnit(Capacity,TerraceCapacity)
SELECT
Capacity=c.value('Capacity[1]','int') ,
TerraceCapacity=c.value('TerraceCapacity[1]','int')
FROM @xml.nodes('/NIACList/NIAC/CommercialUnit/PublicSupplyUnit') PublicSupplyUnit(c)
set @idpsu=SCOPE_IDENTITY();
end;
begin
INSERT INTO CommercialUnit(IDNX,Name,Type,Area,Location,TerraceCapacity,TradingAlcohol,TradingBeer,TradingTobaccoProducts,AmbulatoryTrading,MobileUnitTrading,CommercialApparatusTrading,IDActivities,IdAddress,IDCommercial,IDGoods,IDMobileUnit,IDPSU)
SELECT
IDNx=c.value('IDNx[1],','nvarchar(90)'),
Name=c.value('Name[1],','nvarchar(90)') ,
Type=c.value('Type[1],','nvarchar(90)') ,
Area=c.value('Area[1],','int') ,
Location=c.value('Location[1],','nvarchar(max)'),
TerraceCapacity=c.value('TerraceCapacity[1],','float') ,
TradingAlcohol=c.value('TradingAlcohol[1],','bit') ,
TradingBeer=c.value('TradingBeer[1],','bit') ,
TradingTobaccoProducts=c.value('TradingTobaccoProducts[1],','bit'),
AmbulatoryTrading=c.value('AmbulatoryTrading[1],','bit') ,
MobileUnitTrading=c.value('MobileUnitTrading[1],','bit') ,
CommercialApparatusTrading=c.value('CommercialApparatusTrading[1],','bit') ,
@idactivities,@idAddress2,@idcommercial,@idgoods,@idmobileunit,@idpsu
FROM @xml.nodes('NIACList/NIAC/CommercialUnit') CommercialUnit(c)
end;
2程序:
ALTER procedure [dbo].[InsertXMLNIAC]
(
@xml xml,
@idNIAC int output,
@idCessation int output
)
as
set @xml=*
begin
set nocount on
INSERT INTO NIAC(Number,SubmissionDate,ExpirationDate,IssuerIDNO,IssuerName,SuspensionPeriod,Modifications)
SELECT
Number=c.value('Number[1],','nvarchar(80)'),
SubmissionDate=c.value('SubmissionDate[1],','datetime2') ,
ExpirationDate=c.value('ExpirationDate[1],','datetime2') ,
IssuerIDNO=c.value('IssuerIDNO[1],','nvarchar(max)') ,
IssuerName=c.value('IssuerName[1],','nvarchar(60)') ,
SuspensionPeriod=c.value('SuspensionPeriod[1],','datetime2') ,
Modifications=c.value('Modifications[1],','nvarchar(60)')
FROM @xml.nodes('NIACList/NIAC') NIAC(c)
set @idNIAC=SCOPE_IDENTITY();
end;
begin
INSERT INTO Cessation(Basis,Date,IDNIAC)
SELECT
Basis=c.value('Basis[1],','nvarchar(60)'),
Date=c.value('Date[1],','date') ,
@idNIAC
FROM @xml.nodes('NIACList/NIAC/Cessation') Cessation(c)
set @idCessation=SCOPE_IDENTITY();
end;
3程序:
ALTER PROCEDURE [dbo].[NIACFORCOMPONENTS]
@xml1 xml
AS
BEGIN
DECLARE
@idAddress1 int,
@idAddress2 int,
@idactivities int,
@idgoods int,
@idmobileunit int,
@idcommercial int,
@idcommercialut int,
@idpsu int,
@idmerchant int,
@idNIAC int,
@idCessation int
SET NOCOUNT ON;
declare @trancount int;
set @trancount=@@TRANCOUNT;
BEGIN TRANSACTION
EXEC [dbo].[InsertXMLMultipleTables]
@idAddress1 = @idAddress1 OUTPUT,
@idAddress2 = @idAddress2 OUTPUT,
@IDActivities = @idactivities OUTPUT,
@idgoods = @idgoods OUTPUT,
@idmobileunit = @idmobileunit OUTPUT,
@idcommercial = @idcommercial OUTPUT,
@idcommercialut = @idcommercialut OUTPUT,
@idpsu = @idpsu OUTPUT,
@idmerchant = @idmerchant OUTPUT,
@xml = @xml1
EXEC [dbo].[InsertXMLNIAC]
@idNIAC = @idNIAC OUTPUT,
@idCessation = @idCessation OUTPUT,
@xml=@xml1
begin try
if @trancount = 0
begin transaction
else
save transaction NIACFORCOMPONENTS;
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(),
@message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction NIACFORCOMPONENTS;
raiserror ('NIACFORCOMPONENTS: %d: %s', 16, 1, @error, @message) ;
return;
end catch
Begin
INSERT INTO NIACToComponents(IDNIAC,IdCessation,IdMerchant,IDAddressMerchant,IDAddressCU,IDCommercialUt,IDActivities,IDGoods,IDMobileUnit,IDCommercial,IDPSU)
SELECT
@idNIAC as N'@idNIAC',
@idCessation as N'@idCessation',
@idmerchant as N'@idmerchant',
@idAddress1 as N'@idAddress1',
@idAddress2 as N'@idAddress2',
@idcommercialut as N'@idcommercialut',
@idactivities as N'@idactivities',
@idgoods as N'@idgoods',
@idmobileunit as N'@idmobileunit',
@idcommercial as N'@idcommercial',
@idpsu as N'@idpsu'
COMMIT
END
END
基于这些脚本,插入非常适用于一个,表中的每个 ID 都链接到它,但我想对内部的所有节点NIAC
进行这样的插入,知道每个节点的位置。NIAC
NIACList
解决方案
您可以根据需要使用以下概念示例。
您可以INSERT
通过遍历父 XML 元素将数据存入数据库表。您将需要两个 INSERT 语句。在它们中的第一个之后,您需要像今天已经在做的那样保留一个 IDENTITY 值,以便在第二个 INSERT 中用于子 XML 片段和相应的行。
SQL
DECLARE @INPUTXML XML = '<Lineitems>
<Lineitem>
<Ticker>TER</Ticker>
<ID>0</ID>
<LineItem>Net Revenue</LineItem>
<XFundCode>TRIN</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
<Lineitem>
<Ticker>TER</Ticker>
<ID>0</ID>
<LineItem>Cost of Revenue</LineItem>
<XFundCode>XXP</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
</Lineitems>';
DECLARE @Ticker AS VARCHAR(MAX)
, @ID AS INT
, @Lineitem AS VARCHAR(MAX)
, @XFundCode AS VARCHAR(MAX)
, @UserID AS VARCHAR(MAX);
-- count total number of items
DECLARE @i INT
, @cnt INT = @INPUTXML.value('count(/Lineitems/Lineitem)', 'INT');
SELECT @cnt;
-- loop XML item by item
SET @i = 1;
WHILE @i <= @cnt BEGIN
SELECT @Ticker = col.value('(Ticker/text())[1]','VARCHAR(MAX)')
, @ID = col.value('(ID/text())[1]','INT')
, @Lineitem = col.value('(LineItem/text())[1]','VARCHAR(MAX)')
, @XFundCode = col.value('(XFundCode/text())[1]','VARCHAR(MAX)')
, @UserID = col.value('(UserID/text())[1]','VARCHAR(MAX)')
FROM @INPUTXML.nodes('/Lineitems/Lineitem[position() = sql:variable("@i")]') AS tab(col)
-- do whatever needed in the loop here
SET @i += 1;
END
推荐阅读
- javascript - 防止数组在文本输入上循环并从该数组中提取值 | Vue
- jquery - 我想将“id”发送到coldfusion变量以执行一些查询
- c# - 在 asp.net mvc 应用程序中在哪里编写“处理代码”?
- python - 按字典中键的值组合两个字典列表
- common-lisp - 由两个管道包围的关键字符号
- javascript - for 循环和事件
- javascript - Api PUT 请求显示为“已取消”并显示错误消息“TypeError: failed to fetch”
- cuda - 如何让 malloc 出现在 nvprof 的统计分析器中?
- java - 我无法弄清楚我的代码、队列和 java 中的某些部分
- java - 如何在 Java 中设置截止日期而不对值进行硬编码