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.
Related
I have created a service broker that stores id's in the queue table. But the problem is when i want to get the id back in the stored procedure it's now formatted as xml. Because the service broker message is XML.
How can i just get the last Id each time because the trigger is fired after an update of a row.
Below my code =>
/****** Object: Trigger [dba].[TriggerCall] Script Date: 6/16/2015 2:55:57 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dba].[TriggerCall] ON [dba].[CallID] FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #MessageBody XML
DECLARE #ID varchar(50)
-- Insert statements for trigger here
--get relevant information from inserted/deleted and convert to xml message
SET #MessageBody = (SELECT Id FROM inserted
FOR XML AUTO)
If (#MessageBody IS NOT NULL)
BEGIN
DECLARE #Handle UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION #Handle
FROM SERVICE [TestServiceInitiator]
TO SERVICE 'TestServiceTarget'
ON CONTRACT [TestContract]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION #Handle
MESSAGE TYPE [TestMessage](#MessageBody);
END
END
/****** Object: StoredProcedure [dbo].[usp_GetCall] Script Date: 6/16/2015 2:44:27 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_GetCall]
AS
BEGIN
DECLARE #message_type varchar(100)
DECLARE #dialog uniqueidentifier, #message_body XML;
Declare #Object as Int;
Declare #URL as varchar(255)
Declare #ResponseText as Varchar(8000);
Declare #ID as Varchar(38);
WHILE (1 = 1)
BEGIN -- Receive the next available message from the queue
WAITFOR (
RECEIVE TOP(1) #message_type = message_type_name,
#message_body = CAST(message_body AS XML),
#dialog = conversation_handle
FROM dbo.TestQueue ), TIMEOUT 500 if (##ROWCOUNT = 0 OR #message_body IS NULL)
BEGIN
BREAK
END
ELSE
BEGIN
INSERT INTO [dbo].[testtabel]
([id]
,[callid],
[test])
VALUES
('111', '111', #message_body)
END
END CONVERSATION #dialog
END
END
If I understand your question correctly, you're just looking to rehydrate the ID into an int. If that's the case, the following should do:
use tempdb;
create table inserted (id int);
insert into inserted values (1);
declare #message_body xml;
set #message_body= (select * from inserted for xml auto);
select #message_body.value('(/inserted/#id)[1]', 'int');
The magic is the last line (the rest was just setup for me to test).
I'll take this opportunity to clear up a misconception that you seem to have, though. Triggers in SQL server aren't fired per row, but per batch. So, if you run an update against your table and it updates 50 rows, the trigger gets fired once and the inserted (and deleted) table will have 50 rows in it. Just something to take into account.
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
I'm quite new at SQL Server 2012, and I'm having a strange problem.
I've developed an AFTER UPDATE trigger on a table in my database. I created the trigger in our development environment which is an express edition of SQL Server 2012, no problem.
Now I have to create the same trigger in our production environment which is SQL Server 2012 Enterprise edition, and the creation script never stops executing, and the trigger is not created.
Any ideas on what I need to do to create the trigger?
The script :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter TRIGGER [dbo].[til_aks_ved_betaling]
ON [dbo].[betalingsOplysningerbo]
AFTER UPDATE
AS
BEGIN
declare #snr uniqueidentifier
declare ##status varchar(1024)
SET NOCOUNT ON;
select
#snr = indmeldelse_snr
from
inserted
if UPDATE(betalingsDato)
begin
set ##status = 'Kalder med snr = ' + convert(varchar(38), #snr)
exec xp_logevent 60000, ##status , informational
exec overfoer_betalingsdato #snr
end
END
Try something like this....
ALTER TRIGGER [dbo].[til_aks_ved_betaling]
ON [dbo].[betalingsOplysningerbo]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
declare #snr VARCHAR(1000);
declare #status varchar(1024);
DECLARE #Temp TABLE (indmeldelse_snr uniqueidentifier , [Status] varchar(1024))
INSERT INTO #Temp (indmeldelse_snr , [Status])
SELECT i.indmeldelse_snr , i.[Status]
FROM inserted i INNER JOIN deleted d
ON i.Snr = d.Snr AND i.betalingsDato <> d.betalingsDato
WHILE EXISTS(SELECT * FROM #Temp)
BEGIN
SELECT TOP 1 #snr = 'Kalder med snr = ' + convert(varchar(38),indmeldelse_snr )
,#status = [Status]
FROM #Temp
exec xp_logevent 60000, #status , informational
exec overfoer_betalingsdato #snr
DELETE FROM #Temp WHERE indmeldelse_snr = #snr
END
END
2 things here, common for new people, an UPDATE is a DELETE and an INSERT so make sure you have both before you assume it is an update. Second, these special tables will return all the rows affect by a single sql call. For example, Update Table SET This = 'That' will update every record in the table leaving INSERTED with MANY records.
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.
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