I\'ve been banging my head against a wall for the better part of a week. I\'ve been studying SQL (T-SQL) for a few weeks now, and I\'ve hit a snag.
I\'m building a datab
Here is answer to your question "Getting Identity values to use as FK in an INSTEAD OF trigger"
https://dba.stackexchange.com/questions/34258/getting-identity-values-to-use-as-fk-in-an-instead-of-trigger
You can do this by using a table variable to hold the newly inserted IDs and all of the data that you're going to insert into the other tables. You need to do this because there's no way from just the first INSERT
s data to join back to inserted
in such a manner that you can match up the IDENTITY
values with the rows that caused them to be generated.
We also have to abuse MERGE
since INSERT
doesn't let you include anything other than the target table in its OUTPUT
clause.
I'm doing this on a toy example but hopefully you can see how to write it for your full table structures.
First, some tables:
create table dbo.Core (
ID int IDENTITY(-71,3) not null,
A varchar(10) not null,
constraint PK_Core PRIMARY KEY (ID)
)
go
create table dbo.Child1 (
ID int IDENTITY(-42,19) not null,
ParentID int not null,
B varchar(10) not null,
constraint PK_Child1 PRIMARY KEY (ID),
constraint FK_Child1_Core FOREIGN KEY (ParentID) references Core(ID)
)
go
create table dbo.Child2 (
ID int IDENTITY(-42,19) not null,
ParentID int not null,
C varchar(10) not null,
constraint PK_Child2 PRIMARY KEY (ID),
constraint FK_Child2_Core FOREIGN KEY (ParentID) references Core(ID)
)
go
And the view:
create view dbo.Together
with schemabinding
as
select
c.ID,
c.A,
c1.B,
c2.C
from
dbo.Core c
inner join
dbo.Child1 c1
on
c.ID = c1.ParentID
inner join
dbo.Child2 c2
on
c.ID = c2.ParentID
go
And finally the trigger:
create trigger Together_T_I
on dbo.Together
instead of insert
as
set nocount on
declare @tmp table (ID int not null, B varchar(10) not null, C varchar(10) not null);
merge into dbo.Core c
using inserted i
on
c.ID = i.ID
when not matched then insert (A) values (i.A)
output
inserted.ID /* NB - This is the output clauses inserted,
not the trigger's inserted so this is now populated */
,i.B,
i.C
into @tmp;
insert into dbo.Child1(ParentID,B)
select ID,B
from @tmp
insert into dbo.Child2(ParentID,C)
select ID,C
from @tmp
(And I would keep something like that comment in there since statements inside triggers that include OUTPUT
clauses tend to be quite confusing since there are two inserted
tables in play)
(It's also noteworthy that it doesn't really matter what you put in the ON
clause of the MERGE
, so long as you're sure that it will fail to make a match. You may prefer to have, say, just 1=0
if you think it makes it clearer. I just went cute on the fact that the trigger's inserted.ID
will be NULL
)
And now we do our insert:
insert into dbo.Together(A,B,C) values ('aaa','bbb','ccc')
go
select * from dbo.Together
And get the result:
ID A B C
----------- ---------- ---------- ----------
-71 aaa bbb ccc