Trigger not firing in production but does in non-production - sql-server

I have a trigger that is firing with out issue in non-production but the same exact code is failing to fire in production. I've confirmed it's not disabled and I've done a trace to see that it is not even executing in production.. I've checked the relevant OBJECTPROPERTY elements and they are the same. I've confirm the code is the same. I've confirmed the same inserts are coming from the application. Below is the code for this trigger:
/******
Object: Trigger [dbo].[tr_trigger_ins]
Script Date: 06/02/2012 16:51:51
******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE TRIGGER [dbo].[tr_trigger_ins] ON [dbo].[table_1]
FOR INSERT
AS
BEGIN
UPDATE table_2
SET col_1 =
CASE
WHEN i.col_2 = '0' THEN 0 ELSE 1
END
FROM INSERTED i
INNER JOIN table_3 pa
ON i.col_3 = pa.col_3 AND pa.col_4 = 'ispublic'
INNER JOIN table_4 pp
ON i.col_5 = pp.col_5
INNER JOIN table_2 cs
ON pp.col_6 = cs.col_6
END
GO
Below is a trigger that is an instead of insert on the same table that is executing in both environments:
/******
Object: Trigger [dbo].[tr_trigger_before_ins]
Script Date: 06/02/2012 16:55:52
******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE TRIGGER [dbo].[tr_trigger_before_ins] ON [dbo].[table_1]
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO table_1
SELECT * FROM INSERTED
WHERE col_3 in (73, 199)
END
GO
Any help is greatly appreciated.

First make sure the trigger hasn't been disabled:
ENABLE Trigger tr_trigger_ins ON dbo.table_1;
GO

Ultimately it came down to the issue of replication. Transactions flowed over in a different order than expected. Once we accommodated for this in the trigger logic it worked well.

Related

Copy Trigger stops row being inserted

I am trying to create a trigger that copies newly inserted data from one table and inserts it into another table in a linked server.
However, when the trigger is created it stops the data appearing in the original table until the trigger is deleted and also does not even copy it over to the other table in the linked server either.
Here is my trigger
GO /****** Object: Trigger [dbo].[CopyTMSINFO] Script Date: 12/07/2022 12:53:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[CopyTMSINFO]
ON [dbo].[d_iface_att]
After INSERT
AS DECLARE #EmpID nvarchar(MAX),
#datetime datetime
SELECT #EmpID = ins.emp_id FROM INSERTED ins;
SELECT #datetime = ins.date_and_time FROM INSERTED ins;
INSERT INTO [MAL-HQ-SQL01].[MallaghanApp].[dbo].[EmployeeClockIn] (Id,Employee,TASDateTimeStart,TMSDateTime,JobType)
VALUES ( NEWID(),#EmpID,0,#datetime, 'TMS')
Any help would be greatly appreciated as i dont know much about this stuff and i am really confused.
There are two issues with your trigger:
You need to use SET NOCOUNT ON to prevent the "rows done" messing up exepcted resultsets in some client drivers.
You need to take into account multiple (or zero) rows in the inserted table.
CREATE OR ALTER TRIGGER [dbo].[CopyTMSINFO]
ON [dbo].[d_iface_att]
AFTER INSERT
AS
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM inserted)
RETURN;
INSERT INTO [MAL-HQ-SQL01].MallaghanApp.dbo.EmployeeClockIn
(Id, Employee, TASDateTimeStart, TMSDateTime, JobType)
SELECT
NEWID(),
ins.emp_id,
0,
ins.date_and_time,
'TMS'
FROM inserted ins;
However, inserting into a linked server using a trigger is very bad form anyway. What happens if the remote server is offline?
You should instead use other replication methods, such as the remote server pulling data from this server using an Agent Job.

Update trigger causing SQL error "Cannot find the object "XXX" because it does not exist or you do not have permissions."

I am running into what seems to be a permission issue.
I have a database table that I created with a trigger that runs after a row update. These are the commands I used to create the trigger:
CREATE TRIGGER [dbo].[my_table_u]
ON [dbo].[my_table]
after UPDATE
AS
BEGIN
SET nocount ON;
UPDATE my_table
SET
last_updated_by = ( Host_name() + Suser_name() ),
last_updated_dt = Getdate()
FROM my_table
INNER JOIN inserted ON my_table.id = inserted.id
END
ALTER TABLE [dbo].[my_table] ENABLE TRIGGER [my_table_u]
GO
I am able to insert and delete rows from my_table, but whenever I go to update my_table, I get the following SQL error:
Msg 1088, Level 16, State 13, Procedure my_table_u, Line 16
[Batch Start Line 0] Cannot find the object "my_table"
because it does not exist or you do not have permissions.
However, if I drop and recreate the trigger without the last ENABLE TRIGGER command, like so:
CREATE TRIGGER [dbo].[my_table_u]
ON [dbo].[my_table]
after UPDATE
AS
BEGIN
SET nocount ON;
UPDATE my_table
SET
last_updated_by = ( Host_name() + Suser_name() ),
last_updated_dt = Getdate()
FROM my_table
INNER JOIN inserted ON my_table.id = inserted.id
END
/*** NO ENABLE TRIGGER COMMAND HERE ***/
GO
Then I am able to update rows without error.
Would anyone have any ideas what is happening here? Maybe some tips where I can start investigating?
Answering my own question.
The issue was that the ALTER TABLE [dbo].[my_table] ENABLE TRIGGER [my_table_u] line in the original CREATE TIGGER command ended up being part of the update trigger. That is, whenever this trigger ran, it also tried to run ALTER TABLE...ENABLE TRIGGER as well, and my user didn't have ALTER permissions granted.
This was confirmed when I granted the user ALTER permissions on my_table, and the problem went away.
The "correct" solution, as pointed out by Dale K in the comments, is to leave out the ENABLE TRIGGER command completely, or, alternatively, make sure it comes after the GO statement that creates the trigger.

how to access a column of a table via foreign key?

I am new in SQL server and having trouble with this trigger code. Can you please tell me what is wrong with this line: set NazivFirme=(select NazivFirme from inserted)... This is where I get an error.
USE [BazaPreduzece]
GO
/****** Object: Trigger [dbo].[promenaNazivaFirme] Script Date: 2017-03-28 5:29:47 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER trigger [dbo].[promenaNazivaFirme]
on [dbo].[Firma]
AFTER UPDATE
as
declare #FirmaID int
select #FirmaID=FirmaID from inserted
if update (NazivFirme)
begin
alter table Vlasnik disable trigger zabranaAzuriranjaNazivaFirme
update [dbo].[Vlasnik]
set NazivFirme=(select NazivFirme from inserted)
where FirmaID=#FirmaID
alter table Vlasnik enable trigger zabranaAzuriranjaNazivaFirme
end
That's theFirma and the Vlasnik tables...

looking for procedure instead of trigger which we can schedule as a job

Instead of trigger i am planning to write a procedure which we can run using job which will work same way as TRIGGER
with these two tables in the same way.
how can i do that?
here are my tables with column names
1.tblcal
ID(int,not null)
UID(varchar(10),null)
Desc(varchar(200),null)
Date(datetime,null)
avbl(varchar(5),null)
2.tblEvent
ID(int,notnull)
UID(varchar(10),null)
Desc(varchar(200),null)
Date(datetime,null)
Down is my trigger on tblEvent..
ALTER TRIGGER [dbo].[trU] ON [dbo].[tblEvent]
FOR INSERT
AS
Declare #CuID char(6),
#CuDesc char(40),
#CuDate datetime
SET NOCOUNT ON
Select #CuID = i.UID , #CuDesc=i.Desc, #CuDate=i.Date From Inserted i
If(#CuDesc !='available')
Begin
Update tblCal set avbl='Out', Desc=#CurDesc where cadate=#CuDate and UID=#CuID
ENd
SET NOCOUNT OFF
I have another problem with Desc column.Desc which are going to be in and out Basically we need to update tblcal differently for different descriptions;in that case I don't think trigger is that reliable;Means for example for 10 Desc we need to update in and for other 10 we need to update out
Actually every thursday on the tblevent data is loaded once its loaded it fired a trigger and will update in tblcal.
but my client is looking for a procedure which we can schedule as a job after the tblevent entry done on Thursday.
How can i do with stored procedure?
Procedure
CREATE PROCEDURE dbo.usp_UpdateEventData
AS
BEGIN
SET NOCOUNT ON;
UPDATE C
SET c.avbl = 'Out'
,c.[Desc] = e.[Desc]
FROM [dbo].tblCal C
INNER JOIN [dbo].[tblEvent] e ON c.[UID] = e.[UID]
AND c.cadate = e.[Date] --<-- check if you only want
WHERE e.[Desc] <> 'available' -- to join on date not datetime
END -- CAST both columns to DATE
Also if you are keeping your Trigger as it is you will need to modify the trigger definition to handle multiple Inserts, You can use the same logic as in this procedure to update your trigger definition.
Trigger Fix
ALTER TRIGGER [dbo].[trU] ON [dbo].[tblEvent]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE C
SET c.avbl = 'Out'
,c.[Desc] = i.[Desc]
FROM [dbo].tblCal C
INNER JOIN inserted i ON c.[UID] = i.[UID]
AND c.cadate = i.[Date]
WHERE i.[Desc] <> 'available'
END

SQL Server 2008 Update Trigger

I need to create an update trigger on a table that it also updates the table if certain inserted values are present. Is this possible? I have tried and when the inserted value is present and fires the trigger the trigger does an update and fires itself again. Eventually - deadlock. Is there a way to accomplish this safely?
The Code:
CREATE TRIGGER dbo.trg_updateaddress on dbo.Customers
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #original_source varchar(50)
SELECT #original_source = address_source FROM deleted
IF EXISTS (SELECT * FROM inserted i
INNER JOIN deleted d
ON i.cust_id = d.cust_id
WHERE i.address_source IS NOT NULL
AND (i.[address] <> d.[address]
OR i.address2 <> d.address2
OR i.city <> d.city
OR i.[state] <> d.[state]
OR i.zip <> d.zip
OR i.country <> d.country
OR i.phone <> d.phone
OR i.cell <> d.cell
OR i.email <> d.email))
BEGIN
UPDATE customers
SET address_changed = GETDATE()
END
ELSE
BEGIN
UPDATE customers
SET address_source = #original_source
END
END
One thing that you can do is to disable trigger recursion in your database:
USE [master]
GO
ALTER DATABASE [yourDbName] SET RECURSIVE_TRIGGERS OFF WITH NO_WAIT
GO
This will prevent all triggers in the database from triggering themselves directly, while still allowing them to fire other triggers.
I normally recommend this setting anyway, as recursive triggers is not normally what you want, and a very specialized behavior.
You can prevent the trigger from firing on itself with NESTED_LEVEL
Put this after SET NOCOUNT ON;
IF trigger_nestlevel() < 2
This will prevent the trigger from firing on it's own update.
Note: trigger_nestlevel starts counting at 1 for the first update, so if you want the trigger to only fire once then set it to 2, if you want it to fire twice then set this to 3.

Resources