【问题标题】:How to make insert after insert and combine data with result ID's from first insert如何在插入后进行插入并将数据与第一次插入的结果 ID 组合
【发布时间】:2020-07-28 17:18:11
【问题描述】:
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。 我需要对另一个需要的表进行另一个插入:

MemberId, UserId, Name, Department

我不知道怎么写这个插入。

【问题讨论】:

  • 您是否尝试过使用事务?
  • 不,我不能解决这个问题吗?

标签: sql sql-server sql-server-2008


【解决方案1】:

您需要记录/跟踪在第一次插入时创建的 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 表插入到其他表中。因为您现在有IDENTITY 的记录。 (带有相应的名称)。

注意,如果“MyName”没有唯一约束,这可能会失败。

您“审核” INSERT 的原因是为了避免针对新 IDENTITY 访问 dbo.Member 表......(假设您在 dbo.Member 表中已经有 1,000,000 行......审核将阻止重新查看那张桌子)

https://granadacoder.wordpress.com/2008/12/10/sqlserver20052008-output-clause-in-insertupdatedelete-statements/

这是一个例子:

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 表。 #AUDIT 表只能包含来自您的 PARENT INSERT 的信息(您拥有的任何属性,当然还有新的 IDENTITY,这就是您所追求的)

这就是我认为你所追求的。 (使用小提琴)

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

【讨论】:

  • 我不知道在哪里插入成员表?
  • 用您的 dbo.Member 表替换“#MEMBERSREALTABLEMIMIC”。由于您没有为 dbo.Member 表发布 DDL,我不得不即兴发挥。 Aka,我用#MEMBERSREALTABLEMIMIC“模仿”了你的 dbo.Member 表。
  • 嗨我还是做错了我仍然想念如何在这里合并数据我创建了小提琴dbfiddle.uk/…,但名称有点不同,但它是一样的,你能帮我发现错误吗?
  • 从小提琴中你可以看到,当尝试插入#AUDIT 表时,我无法从@tmpTable 获取变量的引用
  • 我添加了一些额外的内容。但这是一个完全不同的 DDL。实际上是一个新问题。但我继续并附加了这个答案。但请在未来针对主要不同的 DDL 发布新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多