SQL Server 2005 - Trigger not firing - sql-server

I have two tables User & User Log . User log table basically logs all the changes(insert/update/delete) made to user table.
I have a trigger on User table which is as below:
ALTER TRIGGER [dbo].[TRG_UserLog]
ON [dbo].[Users]
FOR INSERT,UPDATE,DELETE
AS
-- Declare variables here
DECLARE #UserName VARCHAR(50)
DECLARE #FirstName VARCHAR(50)
DECLARE #LastName VARCHAR(50)
DECLARE #Email VARCHAR(50)
DECLARE #RoleID INT
DECLARE #UpdatedBy VARCHAR(50)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
IF ##ROWCOUNT = 0
BEGIN
RETURN
END
IF EXISTS(SELECT * FROM INSERTED)
--INSERTED / UPDATED
BEGIN
SET #UserName = ( SELECT UserName FROM INSERTED)
SET #FirstName = ( SELECT FirstName FROM INSERTED)
SET #LastName = ( SELECT LastName FROM INSERTED)
SET #Email = ( SELECT Email FROM INSERTED)
SET #RoleID = ( SELECT RoleID FROM INSERTED)
SET #UpdatedBy = ( SELECT ModifiedBy FROM INSERTED)
INSERT INTO UserLog(UserName,FirstName,LastName,Email,RoleID,[DateTime],UpdatedBy)
VALUES (#UserName,#FirstName,#LastName,#Email,#RoleID,GETDATE(),#UpdatedBy)
END
ELSE
-- DELETED
BEGIN
SET #UserName = ( SELECT UserName FROM DELETED)
SET #FirstName = ( SELECT FirstName FROM DELETED)
SET #LastName = ( SELECT LastName FROM DELETED)
SET #Email = ( SELECT Email FROM DELETED)
SET #RoleID = ( SELECT RoleID FROM DELETED)
SET #UpdatedBy = ( SELECT ModifiedBy FROM DELETED)
INSERT INTO UserLog(UserName,FirstName,LastName,Email,RoleID,[DateTime],UpdatedBy)
VALUES (#UserName,#FirstName,#LastName,#Email,#RoleID,GETDATE(),#UpdatedBy)
END
END
The above triigger is not inserting data in userlog table when insert/update or delete is made to user table. Is there anything wrong with the code?

You should not be setting variables from INSERTED and DELETED. These "tables" could potentially hold more than 1 row in them and using set is going to lose data. Do this instead (on both the INSERT and DELETE blocks):
INSERT INTO UserLog(UserName, FirstName, LastName, Email, RoleID, [DateTime], UpdatedBy)
SELECT UserName, FirstName, LastName, Email, RoleID, getdate(), ModifiedBy
FROM INSERTED
If you make that change, you don't even need the IF/ELSE blocks, since it'll only INSERT/DELETE based on whether or not there are rows in those tables.
Also, the check on ##ROWCOUNT is unnecessary. You should be able to remove that completely.

This will always be true:
SET NOCOUNT ON; -- this sets ##ROWCOUNT to 0
IF ##ROWCOUNT = 0
BEGIN
RETURN
END
because calling SET NOCOUNT ON; affects ##ROWCOUNT, and since no rows are affected by that statement, it's set to 0. So the rest of the code never runs. At the very least, you would run that code before SET NOCOUNT ON; (or store ##ROWCOUNT in a variable for later use), but as indicated by the other answer, it's completely unnecessary anyway.

Related

Trigger to handle multiple row inserts and updates

I am using the following trigger to track inserts and updates on multiple tables and log it in a log table.
CREATE TRIGGER tr_TestTable1]
ON [TestTable_1]
AFTER INSERT, UPDATE
AS
DECLARE #keyid int, #tn nvarchar(50), #recEditMode nvarchar(50), #trstat nvarchar(50)
BEGIN
SET NOCOUNT ON;
SET #tn = 'TestTable_1'
IF EXISTS(SELECT 1 FROM INSERTED)
BEGIN
SET #recEditMode = (Select REC_EDIT_MODE FROM inserted)
SET #trstat = 'PENDING'
SET #keyid = (Select prkeyId FROM inserted)
IF (#recEditMode = 'MANUAL')
BEGIN
IF NOT EXISTS (SELECT * FROM [logTable_1] WHERE SourceKeyId = #keyid AND TrStatus = 'PENDING' AND SourceTableName = #tn)
BEGIN
INSERT INTO [logTable_1](SourceKeyId,SourceTableName,TrStatus)
VALUES (#keyid, #tn, #trstat)
END
END
END
END
This works fine on single row insert and single row update. I am unable to optimize this code to handle multi row inserts and updates. Looking for some help in handling this.
Thanks.
I modified the trigger as below and it seems to be working fine now...
CREATE TRIGGER tr_TestTable1]
ON [TestTable_1]
AFTER INSERT, UPDATE
AS
DECLARE #keyid int, #tn nvarchar(50), #trstat nvarchar(50)
BEGIN
IF ##ROWCOUNT = 0
RETURN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM INSERTED)
BEGIN
SET #tn = 'TestTable_1'
SET #trstat = 'PENDING'
BEGIN
INSERT INTO LogTable_1 (SourceKeyId, SourceTableName, TrStatus)
SELECT I.prKeyId, #tn, #trStat FROM INSERTED AS I
WHERE (I.REC_EDIT_MODE = 'MANUAL' AND NOT EXISTS(SELECT * FROM LogTable_1 WHERE SourceKeyId = I.prKeyId AND SourceTableName = #tn AND TrStatus = 'PENDING'))
END
END
END

Getting rows affected in stored procedure INSERT statement with NOCOUNT OFF

I have a stored procedure in SQL Server 2014 where I first delete data from a table and execute another stored procedure as shown below. I don't care about rows affected on this code so I use SET NOCOUNT ON. I then perform an Insert statement first setting SET NOCOUNT OFF. I would expect the stored procedure to return the rows affected automatically from the INSERT but that has not proven to be the case. I searched SO and found the ##ROWCOUNT and that is working. However, is that really required? Why wouldn't the INSERT statement in the code below return the records affected?
ALTER PROCEDURE [dbo].[SaveTextSetting]
#UserId INT ,
#SettingType INT = 0 ,
#SettingValue NVARCHAR(MAX)
AS
BEGIN
BEGIN
SET NOCOUNT ON;
DELETE FROM Settings
WHERE UserId = #UserId
AND SettingType = #SettingType;
EXEC dbo.PurgeExpiredSettings;
END;
BEGIN
SET NOCOUNT OFF;
INSERT INTO dbo.Settings
( UserId ,
SettingsText ,
SettingType
)
VALUES ( #UserId ,
#SettingValue ,
#SettingType
);
RETURN ##ROWCOUNT; --without this we don't get the rows affected
END;
END;
Are you sure?
CREATE PROCEDURE spTest AS RETURN
GO
ALTER PROCEDURE spTest
AS
BEGIN
SET NOCOUNT OFF
DECLARE #rt int
CREATE TABLE #t (
v int NOT NULL
)
INSERT INTO #t (v)
SELECT v FROM (VALUES (1), (1), (2)) AS t (v)
SET #rt = ##ROWCOUNT
DROP TABLE #t
RETURN #rt
END
GO
DECLARE #rt int
EXEC #rt = spTest
SELECT #rt
GO
DROP PROCEDURE spTest
GO
I would use an output param something like.....
ALTER PROCEDURE [dbo].[SaveTextSetting]
#UserId INT ,
#SettingType INT = 0 ,
#SettingValue NVARCHAR(MAX),
#RowCount INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM Settings
WHERE UserId = #UserId
AND SettingType = #SettingType;
EXEC dbo.PurgeExpiredSettings;
INSERT INTO dbo.Settings( UserId ,SettingsText ,SettingType)
VALUES ( #UserId ,#SettingValue ,#SettingType);
SET #RowCount= ##ROWCOUNT;
END

Instead of insert trigger SQL

I am trying to create an 'instead of insert trigger' that will not let the name 'john' insert anything into a table. My problem is that even if i change the name to something else, the query is successful but the values arent added.
Any help would be appreciated, thanks in advance.
CREATE TRIGGER InsteadOfTrigger
ON Question4
INSTEAD OF INSERT
AS
Declare #name varchar(50)
Declare #question varchar(50)
Declare #Answer char
Set #name = 'John'
IF (select Username from inserted) = #name
BEGIN
RAISERROR ('You have not paid up your fee', 10,1)
ROLLBACK TRANSACTION
END
ELSE
BEGIN
INSERT INTO question4
values (#name, #question, #Answer)
END
Ok So I have removed your BEGIN and END statements between your IF ELSE statement and wrapped the trigger logic within a BEGIN END
As mentioned in the comments below you dont need the ROLLBACK TRANSACTION
Also you will need to populate #question and #Answer for those to be of any use.
CREATE TRIGGER InsteadOfTrigger
ON Question4
INSTEAD OF INSERT
AS
BEGIN
Declare #name varchar(50)
Declare #question varchar(50)
Declare #Answer char
Set #name = 'John'
IF (select Username from inserted) = #name
RAISERROR ('You have not paid up your fee', 10,1)
--ROLLBACK TRANSACTION
ELSE
INSERT INTO question4
values (#name, #question, #Answer)
END
Hmm, I notice you have declared, but not actually set a value for your variables in your else statement this may have caused SQL to not insert what you expected.
Strangely enough I'm required to do the same in an assignment at the moment, Here's my solution:
CREATE TRIGGER instead_of_insert
ON Question4
INSTEAD OF INSERT AS
Declare #Username varchar(25)
Declare #Question varchar(6)
Declare #Answer char(1)
Set #Username ='John'
IF (Select UserName from inserted) = #UserName
Begin
RAISERROR ('You have not paid up your fee', 10,1)
End
Else
Begin
Set #Username = (Select UserName from inserted)
Set #Question = (Select Question_ID from inserted)
Set #Answer = (Select Answer from inserted)
Insert into User_Responses
Values
(#username, #Question, #Answer)
End

Insert update delete trigger

Dear all I´m having trouble with my trigger.
Am I doing this at all right, right now it only works for Insert. I think I´m pretty close tho please help me if you have the time. I´m trying to store all the inserts, updates and deletes into the table customers_changelog via trigger. There is something wrong with the code I cant delete or update customers I can only insert new ones. Please help my I have been spending plenty of hours on this and just cant get this to work! :)
create table customers (
customerid int identity primary key,
name varchar(100) not null,
address varchar(100)
)
go
create table customers_changelog (
customerid int,
name varchar(100) not null,
address varchar(100),
change_user varchar(32),
change_time datetime,
change_action char(1) default 'I',
check (change_action = 'I' or change_action = 'D')
)
go
CREATE TRIGGER log_changes
ON customers
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
--
-- Check if this is an INSERT, UPDATE or DELETE Action.
--
DECLARE #customerid1 as int;
DEClARE #name1 as varchar(32);
DECLARE #address1 as varchar(100);
DECLARE #change_action1 as char(1);
DECLARE #change_time1 as datetime;
DECLARE #change_user1 as varchar(32);
select #customerid1 = c.customerid, #name1 = c.name, #address1 = c.address
from customers c, inserted i
where c.customerid = i.customerid
SET #change_time1 = CURRENT_TIMESTAMP;
SET #change_user1 = CURRENT_USER;
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'I',#change_time1,#change_user1)
IF EXISTS(SELECT * FROM DELETED)
BEGIN
IF EXISTS(SELECT * FROM INSERTED)
INSERT INTO customers_changelog VALUES(#customerid1,#name1,#address1,'U',#change_time1,#change_user1)
ELSE
INSERT INTO customers_changelog VALUES(#customerid1,#name1,#address1,'D',#change_time1,#change_user1)
END
ELSE
IF NOT EXISTS(SELECT * FROM INSERTED) RETURN;
END
Assuming MS-SQL from syntax - So couple issues here:
1. Need to specify column lists in the "update" and "delete" inserts because the column order in the table doesn't match your inserts.
2. Can't use "inserted" data for delete insert
ALTER TRIGGER [dbo].[log_changes] ON [dbo].[customers] AFTER INSERT, UPDATE, DELETE AS
BEGIN
SET NOCOUNT ON;
DECLARE #customerid1 as int;
DEClARE #name1 as varchar(32);
DECLARE #address1 as varchar(100);
DECLARE #change_action1 as char(1);
DECLARE #change_time1 as datetime;
DECLARE #change_user1 as varchar(32);
select #customerid1 = c.customerid, #name1 = c.name, #address1 = c.address
from customers c, inserted i
where c.customerid = i.customerid
SET #change_time1 = CURRENT_TIMESTAMP;
SET #change_user1 = CURRENT_USER;
IF EXISTS(SELECT * FROM DELETED)
BEGIN
IF EXISTS(SELECT * FROM INSERTED)
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'U',#change_time1,#change_user1)
ELSE
BEGIN
select #customerid1 = d.customerid, #name1 = d.name, #address1 = d.address
from deleted d
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'D',#change_time1,#change_user1)
END
END
ELSE
BEGIN
IF NOT EXISTS(SELECT * FROM INSERTED) RETURN;
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'I',#change_time1,#change_user1)
END
END

Stored procedure is not working

I have created a stored procedure to retrieve some details based on the certain values passed to a parameter. THis requires switching between the SQLs to be executed by stored procedure. Following is the code:
USE [DFS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[DAFS]
#EmailID Nvarchar(128),
#clientID int,
#userType Varchar(50),
#Success numeric output,
#msg varchar(100) output
AS
BEGIN
if #userType='Normal User'
IF EXISTS (SELECT 1 FROM dbo.Allcdn
WHERE EmailID = #EmailID AND ClientID = #clientID)
begin
set #Success=0
set #msg='Carry on ....'
end
else
begin
set #Success=6
set #msg='Not allowed ...'
END
end
else
Begin
IF EXISTS (SELECT 1 FROM dbo.Alcon
WHERE EmailID = #EmailID AND ClientID = #clientID)
BEGIN
set #Success=0
set #msg='Carry on...'
END
END
End
end
END
The entire processing is based on the variable #userType. Not sure why the stored procedure is not compiling.
Formatting is your friend, just with a quick glance, it appears you have too many ENDs -- See SQL Fiddle with working Demo:
CREATE PROCEDURE [dbo].[DAFS]
#EmailID Nvarchar(128),
#clientID int,
#userType Varchar(50),
#Success numeric output,
#msg varchar(100) output
AS
BEGIN
if #userType='Normal User'
IF EXISTS (SELECT 1 FROM dbo.Allcdn
WHERE EmailID = #EmailID AND ClientID = #clientID)
begin
set #Success=0
set #msg='Carry on ....'
end
else
begin
set #Success=6
set #msg='Not allowed ...'
END
else
Begin
IF EXISTS (SELECT 1 FROM dbo.Alcon
WHERE EmailID = #EmailID AND ClientID = #clientID)
BEGIN
set #Success=0
set #msg='Carry on...'
END
END
end

Resources