I try to delete some data from one table when deleting from other tables, but I don’t understand what’s wrong.
So i used triggers and this one works :
ALTER TRIGGER [dbo].[deleteBankAccount]
ON [dbo].[Clinic]
AFTER DELETE
AS
BEGIN
DELETE FROM Bank_account WHERE number_bank_account = (SELECT TOP 1 number_bank_account FROM DELETED)
END
This trigger has almost the same code and there’s just the problem.
DELETE FROM Clinic WHERE Clinic_name = 'Clover'
The conflict occurred in...table" dbo.Dogovor ", column 'Legal_address_Clinic'.
ALTER TRIGGER [dbo].[DeleteDogovor]
ON [dbo].[Clinic]
AFTER DELETE
AS
BEGIN
DELETE FROM Dogovor WHERE Legal_address_Clinic = (SELECT TOP 1 Legal_address_Clinic FROM DELETED)
END
Related
I'm confused how a trigger in SQL Server knows what event fired the trigger and what to do.
For example I have a trigger that update on table A and it is performing AFTER INSERT, DELETE, UPDATE. Now my question is how I make the body to perform each task when it triggered, do I need to make separate triggers for each task or is it a way to specify what it needs to do for each task on a single body and a single trigger. And if it is okay can anybody give some explanation and example for it
Thanks
If you really must do a single trigger - this is the logic needed to keep the three operation - INSERT, UPDATE and DELETE - apart:
CREATE TRIGGER dbo.YourTriggerName
ON dbo.YourTable
AFTER DELETE, INSERT, UPDATE
AS
BEGIN
-- check if both the Inserted as well as the Deleted pseudo tables exist
IF EXISTS (SELECT * FROM Inserted) AND EXISTS (SELECT * FROM Deleted)
BEGIN
-- trigger operation : UPDATE
-- "Inserted" contains the new values for the rows after the update
-- "Deleted" contains the old values for the rows before the update
END
-- check if only the Inserted pseudo tables exists
IF EXISTS (SELECT * FROM Inserted) AND NOT EXISTS (SELECT * FROM Deleted)
BEGIN
-- trigger operation: INSERT
-- "Inserted" contains the values for the rows inserted
END
-- check if only the Deleted pseudo tables exists
IF NOT EXISTS (SELECT * FROM Inserted) AND EXISTS (SELECT * FROM Deleted)
BEGIN
-- trigger operation: DELETE
-- "Deleted" contains the values for the rows having been deleted
END
END;
BE AWARE: the trigger is called once per statement - not once per row - so the Inserted and Deleted pseudo tables will potentially contain multiple rows - handle them in a set-based manner, as tables - don't do anything like
SELECT #ID = i.ID FROM Inserted i
This will NOT WORK for multiple rows being inserted at once in a single SQL statement!
But as I said - this is a bit messy, makes for a really large trigger, and makes it hard to maintain this code. I'd personally would much rather have three separate, focused triggers - one for each of the operations you need to handle.
I have two tables at the current moment, located in two different schema dbo.table1 and historyschema.table1history. I have created a trigger that moves all historical data from table1 (upon insert, delete, and update) to table1history.
I originally tried to design the trigger to transfer the information with a INSERT INTO [historyschema].[table1history] select #columns...
Explicitly stating all columns to transfer, but since the two tables have the exact same columns (except history has an extra creation_timestamp and creation_status) I wanted to add them generically with a select * statement. I did this because then when the database has a column added I don't want to have to go back and manually change the trigger every time.
I need a try/catch statement in case there is an error but it doesn't work because the error obtained isn't caught by try/catch (The Error Obtained is Implicit Conversion because of wrongly aligned tables). I was wondering if there is a way to iterate through the columns of table1 and make sure the columns are formatted in such a way where the information will not create an error when being put into table1history.
CREATE TRIGGER [dbo].[table1_History_Change]
ON [dbo].[table1]
AFTER UPDATE, INSERT, DELETE
AS
DECLARE #Now AS DateTIME = GETDATE()
SELECT *
INTO #ModifiedTemp
FROM
(SELECT 'I' *, creation_status, #Now creation_timestamp
FROM inserted
UNION
SELECT *, 'D' creation_status, #Now creation_timestamp
FROM deleted) SubQuery
IF (SELECT COUNT(*) FROM #ModifiedTemp WHERE creation_status = 'D') > 0
AND (SELECT COUNT(*) FROM #ModifiedTemp WHERE creation_status = 'I') > 0
BEGIN
DELETE FROM #ModifiedTemp
WHERE creation_status = 'D'
UPDATE #ModifiedTemp
SET creation_status = 'U'
END
BEGIN TRY
INSERT INTO [HistorySchema].[Table1History]
SELECT *
FROM #ModifiedTemp
END TRY
BEGIN CATCH
PRINT 'History unsuccessfully saved (ERROR: bundle_procedure_change)'
DROP TABLE #ModifiedTemp
RETURN
END CATCH
DROP TABLE #ModifiedTemp
(This is my first posts so if you have any criticisms to help me to improve they are appreciated :).)
NOTE: If the tables are formatted incorrectly I want the trigger to simply not create the history but follow through with the transaction on the main table.
Your entire trigger can be simplified to something close to this. I don't know what columns you really have. You should NEVER use * here because if your base table changes your trigger is broken. Be explicit with columns.
CREATE TRIGGER [dbo].[table1_History_Change] ON [dbo].[table1]
after update, insert, delete as
set nocount on;
INSERT INTO [HistorySchema].[Table1History]
(
CreationStatus
, creation_timestamp
, Col1
)
select CreationStatus = case when i.ID is null then 'D' when d.ID is null then 'I' else 'U' end
, creation_timestamp = getdate()
, isnull(i.Col1, d.Col2) --this will get the new values for inserted and updated or the current value for a delete
from inserted i
full outer join deleted d on d.ID = i.ID
I'm fairly new in T-SQL but i have a question concerning triggers. I have written a trigger that is used in my stored procedure witch inserts and updates data.
Now the trigger works when any row is updated in table [dbo].[users]
I don't know how to modify this trigger so that if data is inserted into [dbo].[users] table activate the trigger (this works now), but how to acheive an update scenario on the same trigger that if only a specific row is UPDATED in [dbo].[users] table that only then the trigger should be activated.
For example
If a new user is inserted and all rows are inserted in this table - activate trigger
If an old trigger is updated but only a specific field in this table is updated (working_state is the name of a column) then only should the trigger should be activated.
Source code what I have is shown here:
ALTER TRIGGER [dbo].[t_temp_triger_name]
ON [dbo].[users]
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
DECLARE #working_state char(1),
#user_code char(11)
DECLARE zm CURSOR FOR
SELECT
working_state,
user_code
FROM
inserted
-- Added update statement that activates the trigger only when a specific -
-- column update is executed
UPDATE [dbo].[users]
SET working_state = 1
FROM [dbo].[users] U
INNER JOIN DELETED D ON U.user_code= D.user_code
WHERE U.working_state<> D.working_state
OPEN zm
FETCH NEXT FROM zm INTO #working_state, #user_code
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC [FNF].[dbo].[NamedProcedure]
#working_state, #user_code
FETCH NEXT FROM zm INTO #working_state, #user_code
END
CLOSE zm
DEALLOCATE zm
END
I have came up with a solution
Added this to my code after declaration
Everything works fine.
IF EXISTS (SELECT 1 FROM deleted)
BEGIN
DECLARE zm CURSOR FOR
SELECT
u.working_state,
u.user_code
FROM
inserted U
LEFT JOIN DELETED D ON U.user_code= D.user_code
WHERE U.working_state<> D.working_state
END
ELSE
BEGIN
DECLARE zm CURSOR FOR
SELECT
working_state,
user_code
FROM
inserted
END
I have 2 tables:
tblStock (PartNo, StockQty, StockLocation)
tblTransfer (PartNo, StockQty, FromLocation, ToLocation)
When I delete data in tblTransfer, the stock is reversed back to tblStock.
The insert trigger is working fine, but the delete trigger is not working.
Please see my delete trigger:
CREATE TRIGGER [dbo].[UpdateStock]
ON [dbo].[tblTransfer]
FOR DELETE, UPDATE
AS
BEGIN
SET NOCOUNT ON;
MERGE tblStock s
USING (SELECT d.PartNo, d.StockLocation
FROM Deleted d) MergeData ON s.PartNo = MergeData.PartNo
AND s.StockLocation = MergeData.FromLocation
WHEN MATCHED THEN
UPDATE SET
s.StockQty = s.StockQty - MergeData.StockQty
s.StockLocation = MergeData.ToLocation
END;
create trigger trg_test
on dbo.tbltransfer
after delete
as
begin
update tbl
set tbl.stockqnty=d.quantity, tbl.stocklocation=d.location
from
tblstock tbl
join
deleted d
on d.partno=tbl.partno
end
I've been tasked with pushing records from one table (T1) to another (T2). I have the insert portion complete as follows:
CREATE TRIGGER [dbo].[CP_to_TW2]
ON [dbo].[TEST_PROJ]
FOR INSERT
AS
BEGIN
INSERT INTO dbo.TEST_TW (PROJECT_ID,PROJECT_DESC,PROJECT_MANAGER)
SELECT PROJ_ID,PROJ_ID+PROJ_NAME,PROJECT_MANAGER FROM inserted
END
TEST_PROJ is T1 and TEST_TW is T2. The PROJECT_ID and PROJ_ID columns store the unique IDs. The trigger fires correct and inserts corresponding rows into T2. However, I am unsure how to get modifications made to T1 to show in T2. For example, if the Project manager is updated in T1 it needs to also update in T2. In addition to this, I am unsure how to make that records in T2 are deleted when they are deleted in T1. Any help would be greatly appreciated.
You can create triggers also for delete or update ops, in update you have deleted table in addition to inserted
CREATE TRIGGER [dbo].[CP_to_TW2]
ON [dbo].[TEST_PROJ]
AFTER UPDATE
AS
BEGIN
UPDATE TEST_TW....
END
CREATE TRIGGER [dbo].[CP_to_TW2]
ON [dbo].[TEST_PROJ]
AFTER DELETE
AS
BEGIN
DELETE FROM dbo.TEST_TW (PROJECT_ID,PROJECT_DESC,PROJECT_MANAGER)
WHERE xxx in (SELECT xxx FROM deleted)
END