Click here to Skip to main content
15,888,610 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
i have a database in sql server called travel. In the database is a table called users. In the users table a column userid is mark as a primary key. I want to lock a record in the users table with the userid of 101. Am trying to do that with a trigger. But is not working.

What I have tried:

ALTER TRIGGER [dbo].[UserTrigger]
ON [dbo].[Users]
INSTEAD OF DELETE
AS
IF exists (Select UserId From Users Where UserId = 101)
BEGIN
RAISERROR ('Not Allowed to delete UserId : 1 as is a SUPER USER',16,1)
END
ELSE
BEGIN
Delete From Users Where UserId in (UserId)
END
Posted
Updated 18-Feb-20 5:10am

You're raising the error when someone tries to delete any user record, so long as the Users table contains the specified record.

You should only be raising the error if someone tries to delete the specified record.

But it's a good job your test fails; your Else block is set to delete all users! You're telling SQL to delete users whose UserId is equal to their UserId, which is obviously all of them.

Use the deleted virtual table to check which records are going to be deleted:
Use the inserted and deleted Tables - SQL Server | Microsoft Docs[^]
SQL
ALTER TRIGGER [dbo].[UserTrigger]
ON [dbo].[Users]
INSTEAD OF DELETE
AS
BEGIN
    SET NOCOUNT ON;
    
    If Exists(SELECT 1 FROM deleted WHERE UserId = 101)
    BEGIN
        RAISERROR('Not Allowed to delete UserId : 101 as is a SUPER USER', 16, 1);
        ROLLBACK TRANSACTION;
        Return;
    END;
    
    DELETE
    FROM
        Users
    WHERE
        UserId In (SELECT UserId FROM deleted)
    ;
END 
 
Share this answer
 
v2
Comments
MaximusDebois 18-Feb-20 10:42am    
thanks man it worked
I don't quite see the need to use instead of trigger. With that kind of trigger you need to re-implement all the logic. Wouldn't it be more convenient to use a normal trigger and to just check what has been deleted and is it acceptable.

Consider the following example
SQL
create table Users (
   UserId int,
   Name varchar(100)
);

insert into Users (UserId, Name) values 
(101, 'A'),
(102, 'B'),
(103, 'C');

create trigger UserTrigger on Users
after delete as
begin
  If Exists(SELECT 1 FROM deleted WHERE UserId = 101)
    BEGIN
        ROLLBACK TRANSACTION;
        RAISERROR('Not Allowed to delete UserId : 101 as is a SUPER USER', 16, 1);
    END;
end;

begin transaction;
delete from Users where UserId = 102; -- Successful

begin transaction;
delete from Users where UserId = 101; -- Raises error

begin transaction;
delete from Users;                    -- Raises error

Actually there is also a more 'declarative' way of doing this. You can also define a child table with a foreign key to Users table. After that you can add the desired user id's to this child table to prevent the deletion of those id's. This solution would require no T-SQL code and maintaining the list of 'permanent' users would be more dynamic.

Consider the following
SQL
create table Users2 (
   UserId int primary key,
   Name varchar(100)
);

insert into Users2 (UserId, Name) values 
(101, 'A'),
(102, 'B'),
(103, 'C');

create table Users2DeletePrevention (
   UserId int references Users2(UserId)
);

insert into Users2DeletePrevention (UserId) values (101);

begin transaction;
delete from Users2 where UserId = 102; -- Successful

begin transaction;
delete from Users2 where UserId = 101; -- Raises a foreign key error

begin transaction;
delete from Users2;                    -- Raises a foreign key error

You just need to ensure that no-one can remove the rows from the child table accidentally but that can be handled using table privileges.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900