如何在插入后进行插入并将数据与第一次插入的结果 ID 组合
How to make insert after insert and combine data with result ID's from first insert
DECLARE @tmpTable TABLE (UserId INT, Name nvarchar(50), Department nvarchar(50))
DECLARE @xml XML=
N'<user><userId>1</userId><name>John</name><department>A</department></user>
<user><userId>2</userId><name>Jane</name><department>B</department></user>';
insert into @tmpTable
SELECT
a.b.value('(./userId)[1]', 'int') AS UserId,
a.b.value('(./name)[1]', 'nvarchar(50)') AS Name,
a.b.value('(./department)[1]', 'nvarchar(50)') AS Department
FROM @xml.nodes('/user') a(b)
INSERT INTO members (name)
OUTPUT Inserted.MemberId
SELECT Name FROM @tmpTable
现在输出新成员的 ID。
我需要对另一个 table 进行另一个插入,这需要:
MemberId, UserId, Name, Department
我不知道怎么写这个插页。
您需要 record/track 在第一次插入时创建的 IDENTITY ID。
但是您需要以基于 SET 的方式进行跟踪。 (我认为你只用“OUTPUT Inserted.MemberId”跟踪单个项目)
给你:
DECLARE @tmpTable TABLE (UserId INT, Name nvarchar(50), Department nvarchar(50))
DECLARE @xml XML=
N'<user><userId>1</userId><name>John</name><department>A</department></user>
<user><userId>2</userId><name>Jane</name><department>B</department></user>';
insert into @tmpTable
SELECT
a.b.value('(./userId)[1]', 'int') AS UserId,
a.b.value('(./name)[1]', 'nvarchar(50)') AS Name,
a.b.value('(./department)[1]', 'nvarchar(50)') AS Department
FROM @xml.nodes('/user') a(b)
create table #AUDIT ( EntityKey int not null default -1 , OldMyName varchar(128) null, NewMyName varchar(128) null , Tag varchar(64) );
CREATE TABLE #MEMBERSREALTABLEMIMIC (MyIdentity INT IDENTITY (3001, 3) , MyName varchar(128) )
/* replace my #MEMBERSREALTABLEMIMIC with your real dbo.Member table here..i had to fake it since I don't have the DDL to dbo.Member */
INSERT INTO #MEMBERSREALTABLEMIMIC (MyName)
output inserted.MyIdentity , null , inserted.MyName , 'Employee Inserted' into #AUDIT ( EntityKey , OldMyName , NewMyName , Tag)
SELECT Name FROM @tmpTable
Select * from #MEMBERSREALTABLEMIMIC
Select * from #AUDIT
DROP table #MEMBERSREALTABLEMIMIC
DROP table #AUDIT
您可以使用#AUDIT table 插入其他 tables.. 因为您现在有 IDENTITY 的记录。 (有相应的名字)。
请注意,如果“MyName”没有唯一约束,这可能会失败。
您“审核”INSERT 的原因是为了避免为新 IDENTITY 命中 dbo.Member table....(假设您在 dbo.Member table...审计将阻止重新查看 table)
见
这是一个例子:
create table PrimaryHolderTable ( i int identity (1001,2) not null primary key, j int not null unique )
create table #OutputResultsHolder ( i int not null, j int not null)
insert into PrimaryHolderTable (j)
output inserted.i, inserted.j into #OutputResultsHolder
select top 10 o.object_id from sys.objects as o order by o.object_id desc --<< from sys.objects is there just to provide some rows
select * from #OutputResultsHolder
drop table #OutputResultsHolder, PrimaryHolderTable;
go
create table dbo.EmployeeTable ( EmpKey int identity(1001,2) , EmpAge int not null );
create table dbo.AuditTable ( EntityKey int not null default -1 , OldValue int null, NewValue int null , Tag varchar(64) );
insert into dbo.EmployeeTable (EmpAge)
output inserted.EmpKey , null , inserted.EmpAge , 'Employee Inserted' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
values( 18 );
insert into dbo.EmployeeTable (EmpAge)
output inserted.EmpKey , null , inserted.EmpAge , 'Employee Inserted' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
values( 20 );
insert into dbo.EmployeeTable (EmpAge)
output inserted.EmpKey , null , inserted.EmpAge , 'Employee Inserted' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
values( 22 );
update dbo.EmployeeTable
set EmpAge = EmpAge + 1
output inserted.EmpKey , deleted.EmpAge, inserted.EmpAge , 'Employee Updated' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
where EmpAge <=20;
delete from dbo.EmployeeTable
output deleted.EmpKey , deleted.EmpAge, NULL , 'Employee Deleted' into dbo.AuditTable (EntityKey , OldValue , NewValue , Tag)
where EmpAge > 0; --Test multi rows
select * from dbo.EmployeeTable; --<<will be empty at this point
select * from dbo.AuditTable;
drop table dbo.EmployeeTable, dbo.AuditTable;
go
追加
请注意,您不能“跳过”#AUDIT Table。 #AUDIT Table 只能包含来自您的 PARENT INSERT 的信息片段(您拥有的任何属性,当然还有您想要的新 IDENTITY)
这就是我认为您想要的。 (使用 fiddle)
drop table tbl_tourSequence;
drop table tbl_tours;
create table tbl_tours (
tourId int NOT NULL IDENTITY (1001, 5) PRIMARY KEY,
timeFrom smalldatetime
);
create table tbl_tourSequence (
tourSequenceId int NOT NULL IDENTITY (2002, 3) PRIMARY KEY,
tour_fk int,
dispatchId int,
timeFrom smalldatetime,
timeTo smalldatetime
);
DECLARE @tmpTable TABLE (DispatchingId INT, TimeFrom smalldatetime, TimeTo smalldatetime)
DECLARE @xml XML=
N'<dispatch><dispatchingId>-1</dispatchingId><timeFrom>2020-07-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
<dispatch><dispatchingId>10</dispatchingId><timeFrom>2020-07-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
<dispatch><dispatchingId>-22</dispatchingId><timeFrom>2010-01-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
<dispatch><dispatchingId>220</dispatchingId><timeFrom>2010-01-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
';
insert into @tmpTable
SELECT
t.p.value('(./dispatchingId)[1]', 'int') AS DispatchingId,
t.p.value('(./timeFrom)[1]', 'smalldatetime') AS TimeFrom,
t.p.value('(./timeTo)[1]', 'smalldatetime') AS TimeTo
FROM @xml.nodes('/dispatch') t(p)
SELECT * FROM @tmpTable
create table #PARENTAUDIT ( EntityKey int not null default -1 , OldTimeFrom smalldatetime null, NewTimeFrom smalldatetime null , Tag varchar(64) );
INSERT INTO tbl_tours (TimeFrom)
output inserted.tourId , null , inserted.TimeFrom , 'TOUR Inserted' into #PARENTAUDIT ( EntityKey , OldTimeFrom , NewTimeFrom , Tag)
SELECT DISTINCT TimeFrom FROM @tmpTable
/* NOTE THE DISTINCT ABOVE, this solution depends on some unique contraint that maps the parents and the children. here we use TimeFrom */
SELECT '#PARENTAUDIT' , * from #PARENTAUDIT
INSERT INTO tbl_tourSequence ( tour_fk , dispatchId , timeFrom , timeTo )
SELECT pa.EntityKey , tt.DispatchingId , tt.TimeFrom , tt.TimeTo
FROM #PARENTAUDIT pa JOIN @tmpTable tt on pa.NewTimeFrom = tt.TimeFrom
DROP TABLE #PARENTAUDIT
Select * from tbl_tours
Select * from tbl_tourSequence
DECLARE @tmpTable TABLE (UserId INT, Name nvarchar(50), Department nvarchar(50))
DECLARE @xml XML=
N'<user><userId>1</userId><name>John</name><department>A</department></user>
<user><userId>2</userId><name>Jane</name><department>B</department></user>';
insert into @tmpTable
SELECT
a.b.value('(./userId)[1]', 'int') AS UserId,
a.b.value('(./name)[1]', 'nvarchar(50)') AS Name,
a.b.value('(./department)[1]', 'nvarchar(50)') AS Department
FROM @xml.nodes('/user') a(b)
INSERT INTO members (name)
OUTPUT Inserted.MemberId
SELECT Name FROM @tmpTable
现在输出新成员的 ID。 我需要对另一个 table 进行另一个插入,这需要:
MemberId, UserId, Name, Department
我不知道怎么写这个插页。
您需要 record/track 在第一次插入时创建的 IDENTITY ID。 但是您需要以基于 SET 的方式进行跟踪。 (我认为你只用“OUTPUT Inserted.MemberId”跟踪单个项目)
给你:
DECLARE @tmpTable TABLE (UserId INT, Name nvarchar(50), Department nvarchar(50))
DECLARE @xml XML=
N'<user><userId>1</userId><name>John</name><department>A</department></user>
<user><userId>2</userId><name>Jane</name><department>B</department></user>';
insert into @tmpTable
SELECT
a.b.value('(./userId)[1]', 'int') AS UserId,
a.b.value('(./name)[1]', 'nvarchar(50)') AS Name,
a.b.value('(./department)[1]', 'nvarchar(50)') AS Department
FROM @xml.nodes('/user') a(b)
create table #AUDIT ( EntityKey int not null default -1 , OldMyName varchar(128) null, NewMyName varchar(128) null , Tag varchar(64) );
CREATE TABLE #MEMBERSREALTABLEMIMIC (MyIdentity INT IDENTITY (3001, 3) , MyName varchar(128) )
/* replace my #MEMBERSREALTABLEMIMIC with your real dbo.Member table here..i had to fake it since I don't have the DDL to dbo.Member */
INSERT INTO #MEMBERSREALTABLEMIMIC (MyName)
output inserted.MyIdentity , null , inserted.MyName , 'Employee Inserted' into #AUDIT ( EntityKey , OldMyName , NewMyName , Tag)
SELECT Name FROM @tmpTable
Select * from #MEMBERSREALTABLEMIMIC
Select * from #AUDIT
DROP table #MEMBERSREALTABLEMIMIC
DROP table #AUDIT
您可以使用#AUDIT table 插入其他 tables.. 因为您现在有 IDENTITY 的记录。 (有相应的名字)。
请注意,如果“MyName”没有唯一约束,这可能会失败。
您“审核”INSERT 的原因是为了避免为新 IDENTITY 命中 dbo.Member table....(假设您在 dbo.Member table...审计将阻止重新查看 table)
见
这是一个例子:
create table PrimaryHolderTable ( i int identity (1001,2) not null primary key, j int not null unique )
create table #OutputResultsHolder ( i int not null, j int not null)
insert into PrimaryHolderTable (j)
output inserted.i, inserted.j into #OutputResultsHolder
select top 10 o.object_id from sys.objects as o order by o.object_id desc --<< from sys.objects is there just to provide some rows
select * from #OutputResultsHolder
drop table #OutputResultsHolder, PrimaryHolderTable;
go
create table dbo.EmployeeTable ( EmpKey int identity(1001,2) , EmpAge int not null );
create table dbo.AuditTable ( EntityKey int not null default -1 , OldValue int null, NewValue int null , Tag varchar(64) );
insert into dbo.EmployeeTable (EmpAge)
output inserted.EmpKey , null , inserted.EmpAge , 'Employee Inserted' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
values( 18 );
insert into dbo.EmployeeTable (EmpAge)
output inserted.EmpKey , null , inserted.EmpAge , 'Employee Inserted' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
values( 20 );
insert into dbo.EmployeeTable (EmpAge)
output inserted.EmpKey , null , inserted.EmpAge , 'Employee Inserted' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
values( 22 );
update dbo.EmployeeTable
set EmpAge = EmpAge + 1
output inserted.EmpKey , deleted.EmpAge, inserted.EmpAge , 'Employee Updated' into dbo.AuditTable ( EntityKey , OldValue , NewValue , Tag)
where EmpAge <=20;
delete from dbo.EmployeeTable
output deleted.EmpKey , deleted.EmpAge, NULL , 'Employee Deleted' into dbo.AuditTable (EntityKey , OldValue , NewValue , Tag)
where EmpAge > 0; --Test multi rows
select * from dbo.EmployeeTable; --<<will be empty at this point
select * from dbo.AuditTable;
drop table dbo.EmployeeTable, dbo.AuditTable;
go
追加
请注意,您不能“跳过”#AUDIT Table。 #AUDIT Table 只能包含来自您的 PARENT INSERT 的信息片段(您拥有的任何属性,当然还有您想要的新 IDENTITY)
这就是我认为您想要的。 (使用 fiddle)
drop table tbl_tourSequence;
drop table tbl_tours;
create table tbl_tours (
tourId int NOT NULL IDENTITY (1001, 5) PRIMARY KEY,
timeFrom smalldatetime
);
create table tbl_tourSequence (
tourSequenceId int NOT NULL IDENTITY (2002, 3) PRIMARY KEY,
tour_fk int,
dispatchId int,
timeFrom smalldatetime,
timeTo smalldatetime
);
DECLARE @tmpTable TABLE (DispatchingId INT, TimeFrom smalldatetime, TimeTo smalldatetime)
DECLARE @xml XML=
N'<dispatch><dispatchingId>-1</dispatchingId><timeFrom>2020-07-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
<dispatch><dispatchingId>10</dispatchingId><timeFrom>2020-07-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
<dispatch><dispatchingId>-22</dispatchingId><timeFrom>2010-01-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
<dispatch><dispatchingId>220</dispatchingId><timeFrom>2010-01-28T07:00:00.000Z</timeFrom><timeTo>2020-07-28T07:00:00.000Z</timeTo></dispatch>
';
insert into @tmpTable
SELECT
t.p.value('(./dispatchingId)[1]', 'int') AS DispatchingId,
t.p.value('(./timeFrom)[1]', 'smalldatetime') AS TimeFrom,
t.p.value('(./timeTo)[1]', 'smalldatetime') AS TimeTo
FROM @xml.nodes('/dispatch') t(p)
SELECT * FROM @tmpTable
create table #PARENTAUDIT ( EntityKey int not null default -1 , OldTimeFrom smalldatetime null, NewTimeFrom smalldatetime null , Tag varchar(64) );
INSERT INTO tbl_tours (TimeFrom)
output inserted.tourId , null , inserted.TimeFrom , 'TOUR Inserted' into #PARENTAUDIT ( EntityKey , OldTimeFrom , NewTimeFrom , Tag)
SELECT DISTINCT TimeFrom FROM @tmpTable
/* NOTE THE DISTINCT ABOVE, this solution depends on some unique contraint that maps the parents and the children. here we use TimeFrom */
SELECT '#PARENTAUDIT' , * from #PARENTAUDIT
INSERT INTO tbl_tourSequence ( tour_fk , dispatchId , timeFrom , timeTo )
SELECT pa.EntityKey , tt.DispatchingId , tt.TimeFrom , tt.TimeTo
FROM #PARENTAUDIT pa JOIN @tmpTable tt on pa.NewTimeFrom = tt.TimeFrom
DROP TABLE #PARENTAUDIT
Select * from tbl_tours
Select * from tbl_tourSequence