How to check column value on insert trigger like Update trigger - sql

I have a update trigger for update status column value change and update other table record and it is working fine. Here is my code
CREATE TRIGGER [dbo].[trgAfterUpdate] ON [dbo].[recharge_request]
FOR UPDATE
AS
DECLARE #status varchar(50);
SELECT #status=i.status FROM inserted i;
IF UPDATE (status)
BEGIN
IF #status='Failure'
--My Update Statement
ELSE IF #status='Success'
--My Update Statement
END
Now I'm want to create an insert trigger also for check status column value and perform other table operation. because in some case status column value will not been update to I need to perform some operation on insert if column value is 'Success' or 'Fail'. status column possible values are 'Success', 'Fail', 'Pending' and 'Process'. any help will be appreciated. Thanks in advance!

DECLARE #status varchar(50);
SELECT #status=i.status FROM inserted i;
you are not handling cases where multiple rows are being updated.
You need to treat the inserted and deleted as a table that may contains more than 1 row
IF UPDATE (status)
BEGIN
update t
set ....
from inserted i
inner join some_table t on i.somecol = t.anothercol
where t.status = 'Failure'
update t
set ....
from inserted i
inner join some_table t on i.somecol = t.anothercol
where t.status = 'Success'
. . . . . -- other status value
END

My Issue has been resolved here is solution:
CREATE TRIGGER [dbo].[trgAfterInsert] ON [dbo].[recharge_request]
AFTER INSERT
AS
BEGIN
DECLARE #status varchar(50);
SELECT #status=i.status FROM inserted i;
IF #status='Success'
BEGIN
--My Update statement
END
END

Related

Update on a table using inner join in a trigger

I have two tables in the database, they have a one-to-many relationship (Example: The table dbo.Tree [tree_id, tree_code] has many dbo.Fruits[id, name, father_tree_id, father_tree_code]) .
I'm trying to create a trigger for when the column codigo_arvore_pai of dbo.Frutos is updated or inserted into it, the column father_tree_code of dbo.Frutos is updated with the value corresponding to the tree_id of the dbo.Tree table. The condition for this is code_tree of dbo.Tree to be equal code_tree_father of dbo.Fruits.
CREATE TRIGGER [dbo].[tr_updateFruit] on [dbo].[Fruits]
AFTER INSERT, UPDATE
AS
IF (UPDATE(father_tree_code))
BEGIN
UPDATE dbo.Fruits
SET id_arvore_pai = A.id_arvore
FROM dbo.Fruits as obj
INNER JOIN dbo.Tree A ON obj.father_tree_code = A.tree_code
WHERE obj.Id IN (SELECT DISTINCT obj.Id FROM dbo.Fruits)
END;
What's wrong?
When the command to update the SQL server is executed, in fact, first the record is deleted and then the new record is inserted again with new changes, giving the illusion to the user that the editing has been done on the desired fields. But in fact, the update command is a two-step command that consists of a deletion and an insertion. First, you must specify the type of action or command executed. You can use the following code inside of the trigger for this reason:
DECLARE #WhatActionHappened as char(1);
SET #WhatActionHappened = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
AND EXISTS(SELECT * FROM DELETED)
THEN 'U' -- Set to Updated.
WHEN EXISTS(SELECT * FROM INSERTED)
THEN 'I' -- Set to Insert.
WHEN EXISTS(SELECT * FROM DELETED)
THEN 'D' -- Set to Deleted.
ELSE NULL -- Skip. It may have been a "failed delete".
END)
After that, you can use the trigger as follows to insert and edit.
CREATE TRIGGER [dbo].[tr_updateFruit] on [dbo].[Fruits]
AFTER INSERT, UPDATE
AS
BEGIN
DECLARE #WhatActionHappened as char(1);
SET #WhatActionHappened = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
AND EXISTS(SELECT * FROM DELETED)
THEN 'U' -- Set to Updated.
WHEN EXISTS(SELECT * FROM INSERTED)
THEN 'I' -- Set to Insert.
--WHEN EXISTS(SELECT * FROM DELETED)
--THEN 'D' -- Set to Deleted.
ELSE NULL -- Skip. It may have been a "failed delete".
END)
IF(#WhatActionHappened = 'U' OR #WhatActionHappened = 'I')
BEGIN
UPDATE dbo.Fruits
SET id_arvore_pai = A.id_arvore
FROM dbo.Fruits as obj
INNER JOIN dbo.Tree A ON obj.father_tree_code = A.tree_code
WHERE obj.Id IN (SELECT DISTINCT i.Id FROM Inserted i)
END
END

Update Trigger For Multiple Rows

I am trying to Insert data in a table named "Candidate_Post_Info_Table_ChangeLogs" whenever a record is updated in another table named "Candidate_Personal_Info_Table". my code works fine whenever a single record is updated but when i try to updated multiple rows it gives error:
"Sub query returned more then 1 value".
Following is my code :
ALTER TRIGGER [dbo].[Candidate_PostInfo_UPDATE]
ON [dbo].[Candidate_Post_Info_Table]
AFTER UPDATE
AS
BEGIN
IF ##ROWCOUNT = 0
RETURN
DECLARE #Candidate_Post_ID int
DECLARE #Candidate_ID varchar(50)
DECLARE #Action VARCHAR(50)
DECLARE #OldValue VARCHAR(MAX)
DECLARE #NewValue VARCHAR(MAX)
DECLARE #Admin_id int
IF UPDATE(Verified)
BEGIN
SET #Action = 'Changed Verification Status'
SET #Candidate_Post_ID = (Select ID From inserted)
SET #Candidate_ID = (Select Identity_Number from inserted)
SET #NewValue = (Select Verified From inserted)
SET #OldValue = (Select Verified From deleted)
IF(#NewValue != #OldValue)
BEGIN
INSERT INTO Candidate_Post_Info_Table_ChangeLogs(Candidate_Post_ID, Candidate_ID, Change_DateTime, action, NewValue, OldValue, Admin_ID)
VALUES(#Candidate_Post_ID, #Candidate_ID, GETDATE(), #Action, #NewValue, #OldValue, '1')
END
END
END
i have searched stack overflow for this issue but couldn't get any related answer specific to this scenario.
When you insert/update multiple rows into a table, the Inserted temporary table used by the system holds all of the values from all of the rows that were inserted or updated.
Therefore, if you do an update to 6 rows, the Inserted table will also have 6 rows, and doing something like this:
SET #Candidate_Post_ID = (Select ID From inserted)
Will return an error, just the same as doing this:
SET #Candidate_Post_ID = (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6)
From the looks of things, you tried to do this with an iterative approach. Set-based is better. Maybe consider doing it like this in the body of your TRIGGER (without all of the parameters...):
IF UPDATE(Verified)
BEGIN
INSERT INTO Candidate_Post_Info_Table_ChangeLogs
(
Candidate_Post_ID
,Candidate_ID
,Change_DateTime
,action
,NewValue
,OldValue
,Admin_ID
)
SELECT
I.ID
,I.Identity_Number
,GETDATE()
,'Changed Verification Status'
,I.Verified
,O.Verified
,'1'
FROM Inserted I
INNER JOIN Deleted O
ON I.ID = O.ID -- Check this condition to make sure it's a unique join per row
WHERE I.Verified <> O.Verified
END
A similar case was solved in the following thread using cursors.... please check it
SQL Server A trigger to work on multiple row inserts
Also the below thread gives the solution based on set based approach
SQL Server - Rewrite trigger to avoid cursor based approach
*Both the above threads are from stack overflow...

If else expression compare not working

i want to perform a compare if #accid2 not equal #accid then roll back action, else perform insert.
My result of this trigger is even that is not match but it still insert into my table.
here is my code:
ALTER TRIGGER [dbo].[TG_checkacctypehtl]
ON [dbo].[Accommodation_Hotel] INSTEAD OF INSERT
AS
DECLARE #accid NVARCHAR(50), #accid2 NVARCHAR(50),#hid NVARCHAR(50),#fsp NVARCHAR(50), #fc NVARCHAR(50), #sr NVARCHAR(50);
SELECT #hid = i.hotel_id FROM INSERTED i;
SELECT #fsp = i.facillities_swimming_pool FROM INSERTED i;
SELECT #fc = i.facillities_catering FROM INSERTED i;
SELECT #sr = i.star_rating FROM INSERTED i;
SELECT #accid2 = i.accommodation_id FROM INSERTED i;
SELECT #accid = accommodation_id FROM [dbo].[Accommodation] WHERE accommodation_type= 'hotel' AND accommodation_id=#accid2;
BEGIN
BEGIN TRAN
SET NOCOUNT ON
PRINT #accid2
PRINT #accid
IF(#accid2 != #accid)
BEGIN
RAISERROR('Record Not Inserted, Accommodation ID is not a Hotel Id',16,1); ROLLBACK; END
ElSE BEGIN
INSERT INTO [dbo].[accommodation_hotel] (hotel_id,facillities_swimming_pool,facillities_catering,star_rating,accommodation_id)
VALUES (#hid,#fsp,#fc,#sr,#accid2);COMMIT;
END
END
*print is for check the value i get.
is that my logic error or my syntax error?
I would rewrite the whole trigger something like this...
ALTER TRIGGER [dbo].[TG_checkacctypehtl]
ON [dbo].[Accommodation_Hotel]
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[accommodation_hotel] (hotel_id,facillities_swimming_pool,facillities_catering,star_rating,accommodation_id)
SELECT i.hotel_id
,i.facillities_swimming_pool
,i.facillities_catering
,i.star_rating
,i.accommodation_id
FROM inserted i
WHERE EXISTS ( SELECT 1
FROM [dbo].[Accommodation] a
WHERE a.accommodation_type= 'hotel'
AND a.accommodation_id = i.accommodation_id)
IF EXISTS (SELECT 1 FROM inserted i
WHERE NOT EXISTS ( SELECT 1
FROM [dbo].[Accommodation] a
WHERE a.accommodation_type= 'hotel'
AND a.accommodation_id = i.accommodation_id)
)
BEGIN
RAISERROR('Records with invalid Accommodation ID is not a Hotel Id not inserted',16,1);
END
END
Insert the rows with valid accommodation ids and raise an error if there are any rows with invalid Hotel Ids, Also no need for all those variables.
Also triggers are fired for each transaction, not for each row. Your code assume there will only be one rows inserted ever in the table at a time.
Should be IF(#accid2 <> #accid)

How can I update the data row by row by the loop after insert those records into another table in mssql?

Does anyone know how can I update the data row by row by the loop after insert those records into another table in mssql?
Example:
I have the following table (tableA)
ID Name is_Feeded
1 Alvin 0
2 Ben 0
3 Lee 1
4 David 0
I want to insert those table from tableA to tableB then update the column is_Feeded to 1 in tableA through a loop?
Anyone know how can I do it in mssql?
Assuming SQL Server 2005 or higher, you can do this in a single statement.
UPDATE A
OUTPUT
inserted.ID,
inserted.Name
INTO
dbo.TableB (ID, Name)
SET
A.is_Feeded = 1 -- is fed?
FROM
dbo.tableA A
WHERE
A.is_Feeded = 0
;
A trigger is also possible, but I don't recommend using one if you can avoid it. If you must to use a trigger (such as perhaps a case where you can't control updates to tableA) then:
CREATE TRIGGER TableA_U ON dbo.TableA FOR UPDATE
AS
INSERT dbo.tableB (ID, Name)
SELECT
I.ID,
I.Name
FROM
inserted I
;
To me it is more natural to insert to tableB based on an update to tableA than to update tableA in response to an insert to tableB.
I would write a trigger for tableB. After you insert a row there, the trigger can update the specific value in tableA
First copy data from tableA to tableB
INSERT INTO tableB
SELECT Name, id FROM tableA;
then set is feeded:
UPDATE tableA SET is_feeded = true
and finally you should do this in one transaction (syntax depends on your DB system, e.g. MySQL: http://dev.mysql.com/doc/refman/5.0/en/commit.html)
you should directly add update field is_feeded when inserting data to TABLEB.
CREATE PROCEDURE xxxxx
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON ;
DECLARE #iOK INT ;
SET #iOK = 0 ;
BEGIN TRY
BEGIN TRANSACTION -- Start the transaction
--start Inserting --
INSERT INTO tableB
SELECT Name ,
id
FROM tableA ;
UPDATE tableA
SET is_feeded = true
-- If we reach here, success!
COMMIT
SET #iOK = 1 ;
END TRY
BEGIN CATCH
-- Whoops, there was an error
IF ##TRANCOUNT > 0
ROLLBACK
-- Raise an error with the details of the exception
DECLARE #ErrMsg NVARCHAR(4000) ,
#ErrSeverity INT
SELECT #ErrMsg = ERROR_MESSAGE() ,
#ErrSeverity = ERROR_SEVERITY()
RAISERROR(#ErrMsg, #ErrSeverity, 1)
END CATCH
SELECT #iOK ;
END

Update trigger insert Null

I am trying to create trigger on SQL Server 2008. I want that if i update field in tabele log that the new value update field in another table Doc. This is the code for trigger:
Create TRIGGER dbo.DocSt
ON dbo.log
AFTER UPDATE
IF (SELECT COUNT(*) FROM inserted) > 0
BEGIN
IF (SELECT COUNT(*) FROM deleted) > 0
BEGIN
UPDATE [dbo].[Doc]
SET
[ID_user] = (select ID_user from inserted)
WHERE
IDN= (select id_doc from inserted)
END
END
When I update field in table log triger update table Doc but it insert NULL.
What i am doing wrong? Thanks!
This code won't ever work - what happens in your UPDATE statement updates 10 rows?? What does this select give you:
SET [ID_user] = (select ID_user from inserted)
You're trying to set a single value to a whole return set from a SELECT statement - that won't work, obviously.
You need to create an UPDATE statement that joins with the Inserted pseudo-table:
CREATE TRIGGER dbo.DocSt
ON dbo.log AFTER UPDATE
UPDATE [dbo].[Doc]
FROM Inserted i
SET [ID_user] = i.ID_User
WHERE IDN = i.id_doc
That way, for each entry in Inserted, you're joining your table dbo.Doc to it and update the ID_user column.