0

I'm trying to create a trigger that initialises a record over multiple tables when a master record is inserted to a master table. The code below gives the error "Object reference not set to an instance of an object."

Appraisal is the table the trigger exists for and every table concerned has an AppraisalID foreign key.

BEGIN TRANSACTION
    DECLARE @appraisalid int
    SET @appraisalid = (SELECT AppraisalID FROM inserted)
    INSERT INTO dbo.AppraisalCPD (AppraisalID)
    VALUES (@appraisalid)
COMMIT;

The code below works, but I would rather use a variable to assign the value as I need to add rows to a fair few tables.

BEGIN
    INSERT INTO dbo.AppraisalCPD
    (AppraisalID)
    SELECT AppraisalID
    FROM inserted;
END;

If anyone can suggest a way to set an appraisalid variable using the inserted row in the Appraisal table to insert rows into every other table I need to, that'd be very helpful.

2
  • 1
    You cannot use a single variables, since the trigger will fire once per statement and can have multiple rows in the Inserted pseudo table. You cannot assign multiple values to a single variable.... Commented Feb 1, 2014 at 21:44
  • 1
    SQL Server is not raising that error - that seems like .NET code causing that problem. Can you show the code you are using to generate and execute the insert statement that eventually invokes this trigger? Commented Feb 1, 2014 at 21:53

1 Answer 1

1

I am assuming you are talking about home appraisal.

The [appraisal] table is the parent and the [owners]/[location] are the children.

Here is a play schema in tempdb.

-- just playing
use tempdb;
go

-- drop table
if object_id('appraisal') > 0
drop table appraisal
go

-- create table - home appraisal 
create table appraisal
(
app_id int identity (1,1),
app_request datetime,
app_employee_id int
);


-- drop table
if object_id('owners') > 0
drop table owners
go

-- create table - the owners
create table owners
(
own_id int identity (1,1) primary key,
own_first_nm varchar(64),
own_last_nm varchar(64), 
app_id int
);


-- drop table
if object_id('location') > 0
drop table location
go

-- the location
create table location
(
loc_id int identity (1,1) primary key,
loc_street varchar(64),
loc_city varchar(64),
loc_state varchar(2), 
loc_zip varchar(9),
app_id int
);
go

When creating empty child records via a trigger, you either have to define default values or supply them in the trigger.

Also, I leave setting up foreign keys for you to handle.

The code for the trigger could look like the following.

-- The trigger
CREATE TRIGGER DBO.make_empty_children on dbo.appraisal
for insert, update, delete
as
BEGIN

-- nothing to do?
IF (@@rowcount = 0) RETURN;

-- do not count rows
SET NOCOUNT ON;

-- delete
IF NOT EXISTS (SELECT * FROM inserted) 
  BEGIN
    RETURN;
  END

-- insert
ELSE IF NOT EXISTS (SELECT * FROM deleted) 
  BEGIN

-- dummy record for owners
insert into owners
    (
      own_first_nm,
      own_last_nm, 
      app_id
    )
select
  'enter first name',
  'enter last name',
  app_id
from
  inserted;

-- dummy record for location
insert into location
    (
      loc_street,
      loc_city,
      loc_state, 
      loc_zip,
      app_id
    )
select
  'enter street',
  'enter city',
  'ri',
  '00000',
  app_id
from
  inserted;

    RETURN;
  END

  -- update
  ELSE
  BEGIN
      RETURN;
  END

END
GO

I left place holders for DELETE and UPDATE operations.

1 - Do you want to reject updates to the id (key) in the appraisal table. Probably not. This can also be taken care (prevented) of by a Foreign Key (FK).

2 - Do you want to cascade deletes? This also can be handled by a FK or in code in the trigger.

Lets see no records in the tables.

select * from appraisal;
select * from owners;
select * from location;

enter image description here

Like Marc / Aaron said, the inserted / deleted tables are record sets. Not a single row.

Order is not guaranteed. Use an order by if you want the records inserted by app id order.

-- Insert 2 records
insert into appraisal
(
app_request,
app_employee_id 
)
values
(getdate(), 7),
(dateadd(d, 1, getdate()), 7);

-- Lets see the data
select * from appraisal;
select * from owners;
select * from location;

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.