Sheetal
Sheetal

Reputation: 873

Insert Trigger not working properly

I have created the following trigger for insert in the deleted user table the corresponding record has to be deleted from the userlogin table.

The trigger involves the following statements:

CREATE TRIGGER trgInsert_ToDeleteFromUserLogin on DELETEDUSER
FOR INSERT
AS

BEGIN

DECLARE
@UserName nvarchar(50),
@UserType nvarchar(30),
@Reason nvarchar(max)

SELECT @UserName = USERNAME, @UserType = UserType, @Reason = Reason FROM INSERTED 
INSERT INTO DELETEDUSER (USERNAME,USERTYPE,REASON) VALUES(@USERNAME,@USERTYPE,@REASON)
DELETE FROM USERLOGIN WHERE USERNAME = @UserName

end

But when I insert a record in the deleteduser table the corresponding record is deleted from the userlogin table but it is not inserted to the deleteduser table.

The above trigger does not generate any error, however when I try to insert a record in the Deleted User Table I notice that the record is deleted from the UserLogin table but the same is not been inserted in the DeletedUser table.

For your reference I am including the table structure for both the deleteduser and userlogin is as follows:

Deleted User

CREATE TABLE DELETEDUSER
(
DeletedUserID int identity(1,1),
UserName nvarchar(max),
UserType nvarchar(30),
Reason nvarchar(max)
)

--ALTERING DELETEDUSER TABLE TO SPECIFY THE SIZE OF USERNAME COLUMN FOR IMPOSING FOREIGN KEY CONSTRAINT

ALTER TABLE DELETEDUSER ALTER COLUMN UserName nvarchar(50)

--ALTERING DELETEDUSER TABLE TO ADD FOREIGN KEY CONSTRAINT

ALTER TABLE DELETEDUSER ADD CONSTRAINT fk_UserName Foreign key (UserName) references UserLogin(UserName) on delete cascade


USERLOGIN TABLE:

CREATE TABLE USERLOGIN
(
UserID int identity(1,1) not null,
UserName nvarchar(50) not null,
Password nvarchar(50) not null
)

--ALTER TABLE USERREGISTRATION TO ADD PRIMARYKEY

ALTER TABLE USERLOGIN ADD CONSTRAINT pk_UserName primary key(UserName)

Please help me with the changes I should make to insert the row in the deleteduser table and remove (delete) it from userlogin table.

Thanks in advance!

Upvotes: 0

Views: 1335

Answers (3)

GilaMonster
GilaMonster

Reputation: 1768

Your trigger is written assuming that there will only be one row in the inserted table. SQL does not have row triggers (like Oracle does), its triggers fire once for a statement and the inserted/deleted tables will have all the rows affected by the statement

SELECT @UserName = USERNAME, @UserType = UserType, @Reason = Reason FROM INSERTED

What's going to happen here if 4 rows are inserted in a single statement?

In addition to the problems noticed by the earlier replies, you need to code the trigger so that it can handle any number of rows in the inserted table.

For a good introduction to triggers in SQL, please read this: http://www.sqlservercentral.com/articles/Triggers/64214/

Upvotes: 0

richardtallent
richardtallent

Reputation: 35363

Your trigger is an "AFTER" trigger (the default) rather than "INSTEAD OF". With an AFTER trigger, the "deed has been done" already--i.e., the insert into DeletedUser has already occurred, so you do not need the INSERT statement.

The foreign key relationship between DeletedUser and UserLogin is just all wrong. These tables are, from what you have described, mutually exclusive: having a user in DeletedUser means they should no longer be in UserLogin, and having the user in UserLogin means they wouldn't also be a DeletedUser.

So, remove the foreign key relationship, and try this:

CREATE TRIGGER trgInsert_ToDeleteFromUserLogin on DELETEDUSER FOR INSERT AS
BEGIN
  DELETE FROM UserLogin WHERE EXISTS (SELECT NULL FROM INSERTED WHERE
    INSERTED.USERNAME = UserLogin.USERNAME)
END

Edit: As Shannon mentioned below, this code will properly handle situations where multiple records are inserted at the same time, in contrast to the single-row assumption of the original code. The use case (disabling a user) suggested only a single insert at a time, but it's better (and easier) to built triggers to operate against the entire set of records in the inserted/deleted metatables.

As an aside, your database design could be simplified by using views. Example:

ALTER TABLE UserLogin ADD DeletedReason varchar(255) NULL

CREATE VIEW ActiveUser AS SELECT * FROM UserLogin WHERE DeletedReason IS NULL

Upvotes: 2

MartW
MartW

Reputation: 12538

Why are you INSERTing into DeletedUser in your INSERT trigger on DeletedUser? This is already happening as that's what fired the trigger in the first place. Remove that part and it should be fine.

Upvotes: 0

Related Questions