SQL Server create Triggers on INSERT and Update - sql-server

I have created a table with the following columns: ObservationId, FirstCreatedDate, description, ... ... and LastUpdatedDate in SQL Server 2008 R2. The ObservationId is an identity with increment by 1.
I need to create two triggers, one for INSERT and the other for UPDATE. On new record inserted, the INSERT trigger will update FirstCreatedDate column by getting the current datetime; while on existing record updated, the UPDATE trigger will update LastUpdatedDate colunm by getting the current datetime.
I have failed in doing this as I am guessing the identify might be the problem.
Could anyone give me a hand? Thanks!
Cheers,
Alex
ALTER TRIGGER [dbo].[T_InsertNewObservation] ON [dbo].[GCUR_OBSERVATION]
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
UPDATE GCUR_OBSERVATION SET GCUR_OBSERVATION.FirstCreatedDate = getdate()
FROM GCUR_OBSERVATION a INNER JOIN INSERTED ins ON a.ObservationId = ins.ObservationId
END

I think you are mostly correct but are not accessing the INSERTED or DELETED tables correctly.
ALTER TRIGGER [dbo].[T_InsertNewObservation] ON [dbo].[GCUR_OBSERVATION]
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- get the last id value of the record inserted or updated
DECLARE #id INT
SELECT #id = [ObservationId]
FROM INSERTED
-- Insert statements for trigger here
UPDATE GCUR_OBSERVATION
SET GCUR_OBSERVATION.FirstCreatedDate = GETDATE()
WHERE [ObservationId] = #id
END
PS. Hopefully this works as I wrote it in notepad and haven't tested it.

The code below is for AFTER UPDATE to modify last changed date column.
Please advice if you see any issue with it. Thanks!
ALTER TRIGGER [dbo].[T_UpdateObservation] ON [dbo].[GCUR_OBSERVATION]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- get the last id value of the record inserted or updated
DECLARE #id INT
SELECT #id = [ObservationId]
FROM DELETED
-- Insert statements for trigger here
UPDATE GCUR_OBSERVATION
SET GCUR_OBSERVATION.LastUpdatedDate = getdate()
WHERE [ObservationId] = #id
END

Create TRIGGER [dbo].[TrigerName] ON [dbo].[TableCreateTriger] FOR INSERT AS
INSERT INTO TableInsertDate SELECT * FROM TableCreateTriger

Related

Fire SQL Trigger When Column Value Changes

I am adding the date to a column in SQL when the 'workstatus' is 'completed', but my problem is, when I open and save the same job again in the software, it runs the trigger and changes the date again to a new value which I don't want.
I want the trigger to run only if the 'workstatus' value is something else than 'completed'.
GO
/****** Object: Trigger [dbo].[TRJCD_JOBREQUEST] Script Date: 06/25/2021 15:49:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRJCD_JOBREQUEST] ON [dbo].[TBL_JOBREQUEST]
AFTER UPDATE,INSERT
AS
if (Update (workstatus))
begin
DECLARE #Jobcompletiondate datetime
DECLARE #workstatus VARCHAR(15)
DECLARE #jobid int
select #workstatus = workstatus from inserted
select #jobid = jobid from inserted
select #Jobcompletiondate = GETDATE()
begin
if #workstatus='Completed'
update TBL_JOBREQUEST set JobCompDate=#Jobcompletiondate where jobid = #jobid
end
end
The following is how you should construct your trigger.
There is no need to assign any values to variables, triggers fire once per batch and always operate on the set of updated rows.
If you update a status to Completed you need to check it's not currently Completed, also if you want to retain the first JobCompDate even if the status is amended afterwards simply use a case expression to only update the column where it's currently NULL.
create or alter trigger [dbo].[TRJCD_JOBREQUEST] on [dbo].[TBL_JOBREQUEST]
after update,insert
as
if ##RowCount=0 return
set nocount on
if Update (workstatus)
begin
update t set
t.JobCompDate=case when t.JobCompDate is null then GetDate() else t.JobCompDate end
from inserted i join TBL_JOBREQUEST t on t.jobid=i.jobid
where i.workstatus='Completed'
and not exists (
select * from deleted d
where d.jobid=i.jobid and d.workstatus=i.workstatus
)
end
Please note that I do not have your data set, so I'm unable to test the trigger, however, based on what you provided in your question, I believe this is the answer you are seeking:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRJCD_JOBREQUEST] ON [dbo].[TBL_JOBREQUEST]
AFTER UPDATE,INSERT
AS
if (Update (workstatus))
begin
DECLARE #Jobcompletiondate datetime
DECLARE #currentworkstatus VARCHAR(15)
DECLARE #oldworkstatus VARCHAR(15)
DECLARE #jobid int
select #oldworkstatus = workstatus from deleted
select #currentworkstatus = workstatus from inserted
select #jobid = jobid from inserted
select #Jobcompletiondate = GETDATE()
begin
if #currentworkstatus='Completed' and #oldworkstatus <> 'Completed'
update TBL_JOBREQUEST set JobCompDate=#Jobcompletiondate where jobid = #jobid
end
end
You needed to check if the deleted workstatus does not equal Completed and only then should the trigger fire.

Oracle to Sql Server conversion trigger

I am new sql server I need to convert a trigger in sql server which i have in oracle, please help i tried it but failed.
Create or replace
Trigger AD_JOB_SCHEDULE BEFORE
INSERT ON JOB_SCHEDULE FOR EACH row BEGIN
if :new.ACCOUNT_SYSTEM_CODE is null
Then
:new.BATCH_TYPE:='POLICY_NIGHT';
ELSEif :new.ACCOUNT_SYSTEM_CODE is not null then
:new.BATCH_TYPE:='ACCOUNT_NIGHT';
END if;
END;
The above is my trigger.
BELOW is my attempt
CREATE TRIGGER AD_JOB_SCHEDULE
ON JOB_SCHEDULE
AFTER INSERT,UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
declare #value varchar(200)
select #value=ACCOUNT_SYSTEM_CODE from inserted
if #value is not null
begin
update JOB_SCHEDULE
set BATCH_TYPE='ACCOUNT_NIGHT'
where ACCOUNT_SYSTEM_CODE is not null
end
else
begin
update JOB_SCHEDULE
set BATCH_TYPE='POLICY_NIGHT'
where ACCOUNT_SYSTEM_CODE is null
end
END
GO
This is my complete code actually I just want to know that whether it will work or not as I don't have the scenario with me, I just have to write the code and deliver.

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

Dynamically Build UPDATE statement within INSERT/UPDATE/DELETE trigger

basically i am looking for logic to generate insert or update statement in string variable from trigger. suppose when people just update 'N' of fields like update statement....then my trigger will fire and from that trigger i want build what update statement was issued by user and store in string variable
the same way i want to build insert statement from trigger too but i am not getting logic. so if anyone has any idea or sample code then please share with me to achieve my goal.
ALTER TRIGGER WSContent AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
DECLARE #Action VARCHAR(10)
DECLARE #PKValue INT
DECLARE #TableName VARCHAR(50)
SET #TableName='website_content'
IF EXISTS(SELECT * FROM INSERTED)
BEGIN
IF EXISTS(SELECT * FROM DELETED)
BEGIN
SET #Action ='U';
SELECT #PKValue=ContentNumber from DELETED
END
ELSE
BEGIN
SET #Action ='I';
SELECT #PKValue=ContentNumber from INSERTED
END
END
ELSE
BEGIN
SET #Action = 'D';
SELECT #PKValue=ContentNumber from DELETED
END;
INSERT INTO [ContentChangeLog]([PkValue],[TableName],[Action],ActionDate)
VALUES(#PKValue,#TableName,#Action,GetDate())
SET NOCOUNT OFF;
Like many people, you misunderstand how a trigger works. When you insert, update or delete multiple records, the trigger is called once and the tables deleted/inserted can contain multiple records, not 1 for each record effected. You need to rewrite this assuming you have multiple records in those tables.
INSERT INTO [ContentChangeLog]([PkValue],[TableName],[Action],ActionDate)
SELECT ContentNumber, #TableName, 'I', GETDATE()
FROM INSERTED i
WHERE not exists(SELECT TOP 1 1 FROM DELETED WHERE ContentNumber = i.ContentNumber)
Here is an example of the Inserted records only, you will want to do something similar for your updates and deletes.

MS SQL trigger instead of update ELSE possible to execute original query?

Here is my trigger
Create TRIGGER [dbo].[tri_before_update]
ON [dbo].[test]
instead of update
AS
BEGIN
SET NOCOUNT ON;
if update (test_a)
begin
*.. my update & insert query*
end
END
create TRIGGER [dbo].[tri_before_update_price]
ON [dbo].[co_ticket]
instead of update
AS
BEGIN
SET NOCOUNT ON;
if update (t_price)
begin
insert into old_price_log (t_id,insert_time,process_id,old_t_price)
select i.t_id,getdate(),2,t_price
from Inserted i,co_ticket t where i.t_id = t.t_id
update t set t_price = i.t_price
from co_ticket t, inserted i
where t.t_id = i.t_id
end
else
begin
-- if update other then (t_price) then the update comand not execute.
-- example when i update t_cancel_flag or t_quantity and etc. end
END
This trigger execute perfectly when i update on column "test_a". HOWEVER, when i update other than column "test_a" it won't be execute. I know i can put "else" command, but i got a lot of column. sometimes will update two other column , sometimes three or four column. I don't wish to update all column everytime. Is it possible ELSE "then execute original query"?
I tried a lot different way but still can't work. :( Please HELP!
create TRIGGER [dbo].[tri_on_update_price]
ON [dbo].[co_ticket]
AS
BEGIN
SET NOCOUNT ON;
if update (t_price)
begin
insert into old_price_log (t_id,insert_time,process_id,old_t_price)
select d.t_id, getutcdate(),2,d.price
from deleted d
END
end
An ordinary after trigger will do just what you want: insert a log of the price change, if the price was updated. No need for INSTEAD OF. You need to look into the deleted pseudo-table to get the old price. Never store local times in a database.

Resources