Need a trigger which runs on deletion.
The code I wrote is not working: It is firing the trigger but is not inserting any records.
I want it to insert the to be deleted row in a audit table.
My code:
CREATE TRIGGER [EXERCISE].[delete_trigger] ON [EXERCISE].[Fact_Sales]
AFTER DELETE
AS
INSERT INTO [EXERCISE].[Fact_Sales_Audit](City_ID,Product_ID,Time_ID,Created_Date,Updated_Date)
SELECT F.City_ID,F.Product_ID,F.Time_ID,F.Created_Date,F.Updated_Date
FROM [EXERCISE].[Fact_Sales] F
JOIN deleted D
ON F.Fact_Sales_ID = D.Fact_Sales_ID
PRINT 'Deleted row entered.'
It is not working. Reason I suspect is- the row is being deleted from the table before the trigger is fired and thats why it is not able to join and hence not inserting any records. But when I debug and print messages I can see that trigger happens before deletion.
Can someone please explain me how exactly does this trigger work?
You are deleting rows from the [EXERCISE].[Fact_Sales] table, yet in your trigger you are joining to this table, expecting the records to still be there - they are not.
At that point, the Deleted pseudo-table has the same schema as the [EXERCISE].[Fact_Sales] table, but with the rows you have just deleted in it. Instead of trying to join back to a table for rows you know aren't there any more, just use the Deleted table directly for your insert:
CREATE TRIGGER [EXERCISE].[delete_trigger]
ON [EXERCISE].[Fact_Sales]
AFTER DELETE
AS
INSERT INTO [EXERCISE].[Fact_Sales_Audit](City_ID,Product_ID,Time_ID,Created_Date,Updated_Date)
SELECT D.City_ID,
D.Product_ID,
D.Time_ID,
D.Created_Date,
D.Updated_Date
FROM deleted D
The trigger does fire after the delete on the main table, as the AFTER DELETE syntax implies. It fires somewhere between when the delete statement is executed, and before the control is returned to the user. It takes place in the same transaction - e.g. if the delete was rolled back for whatever reason, the inserts performed by the trigger would also be rolled back.
You should simplify your trigger definition to fetch just deleted row(s) from virtual table DELETED. What will happen is your deleted rows will be temporarily stored in that table and then will be inserted into audit table.
NB! Be sure you have set primary key on your Fact_Sales table.
CREATE TRIGGER [delete_trigger] ON [Fact_Sales]
FOR DELETE
AS
INSERT INTO [Fact_Sales_Audit](Fact_Sales_Id,City_ID,Product_ID,Time_ID,Created_Date,Updated_Date)
SELECT Fact_Sales_Id,City_ID,Product_ID,Time_ID,Created_Date,Updated_Date
FROM DELETED
Related
In SQL server, when does a trigger get fired?
The problem is, I have a table where 45,000 records are going to be inserted.
And I want to copy all 45k records to other tables.
But I don't want the trigger to run on every insert, i.e 45000 times trigger.
My trigger is basically copying record from TableA to TableB.
Trigger:
Create trigger tri_1
on TableA
after insert
as
Begin
Insert into TableB (ID,Name,Others)
select ID,Name,Others from TableA
inner join inserted
on inserted.ID = TableA.ID
End
The above is just the template of my trigger.
Also, I have a question, the trigger mentioned above, how is it working? like firing for each row or after all insert is done?
In SQL Server, the trigger is fired when the insert statement is completed.
In some databases, the trigger is executed for each row inserted (in those databases for each row is often part of the syntax). By contrast, SQL Server keeps track of the changed rows, which is why they are stored in table-like structures, inserted and deleted -- and it is a mistake to assume that these contain only one row.
I have a trigger that runs after the update record in the table A, add records to a table B
Now the table B has a trigger that works to ensure that the values entered are correct, when there is a problem with it, the role of a trigger table B is to prevent the entry record (I can not use a unique index because the conditions are in other tables), but I want to avoid only the current record entry, as well as not to prevent the update is done in Table A and not the all good records in this transaction.
the ROLLBACK function is canceling all open transactions.
I have a trigger to copy over the data from Table A to table B when table A is changed
The trigger is like this :
ALTER TRIGGER ATrigger
ON A AFTER INSERT, DELETE, UPDATE
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM B WHERE id IN (SELECT id FROM deleted)
INSERT INTO B(Id, col1,col2) (SELECT i.Id, i.col1, i.col2 FROM inserted i)
END
But i see not all the data inserted in A are copied to B, the data copied seems very random
I was searching around, found it might caused by multi-insert, someone is suggesting using cusor, but i think for mine, it should be ok to insert or delete from the inserted, deleted table using this two sql.
Please advise, thanks!
I'm not certain this is your problem but your trigger has 2 "gotchas". First on an insert the deleted table will have no rows in it so no deletes will be done. Second is the reverse and potentially your problem. On a delete the inserted table has no rows. So all of the IDs are going to be deleted from table B but not re-inserted. On top of this if ID is not a unique key for table A then when you insert a second copy of it you will be deleting all of your history in table B and only adding the "new" history.
If you can provide more information on the structure of the 2 tables and the purpose of the trigger, not to mention any patterns on the rows being inserted or not being inserted as the case may be we can be of more help.
I have problem with deleteing rows in table which has trigger which invokes trigger of second table, which updates row in first table. Here is the description:
Table A (id,b_table_count)
Table B (id,a_table_id_fk)
Table A has trigger BEFORE DELETE which has instructions:
BEGIN
DELETE FROM b where a_table_fk = OLD.id;
RETURN OLD;
END;
Table B has trigger AFTER DELETE with instruction:
UPDATE a SET b_table_count = b_table_count-1 WHERE OLD.a_table_id_fk = a.id;
When I delete row from table A, which has no connected rows in B, everything is correct.
But, when I delete row from table A, which has connected row(s) in table B, then DELETE statement returns "Query returned successfully: 0 rows affected" . I must execute DELETE statment second time, then row is finnaly deleted. After first DELTE only connected ROWS are deleted in TABLE B, but row being deleted in table A remains.
Do you have answer for that? I suspect that pgsql doesn't allow to update row being deleted in trigger, but I haven't found anything about it in pgsql documentation.
What is the solution?
I'm having a similar problem, but with one table only. Deleting rows from the given table fires a trigger (before delete), that searches for related rows int the same table (by a given condition), and if finds them, these rows get updated. Now, if an updated row is to be deleted by the same delete command, then it doesn't gets deleted.
So basically, if you create a trigger, that always updates the same row that is being deleted, you can't delete anything from now on.
I don't know if this is on purpose, or not. From one way, it seems logical, that's for sure. If you update a record, it's not the same record that was intended for deletion.
(sorry for bad english)
So basicly you have a A -> trigger -> B -> trigger -> A situation, which is actually incorrect thing to do by design and I think postgres locks the row that is executing trigger or A row is locked but i'm not sure about all inner behavior of postgres.
so you can try DELETE FROM B WHERE a_id = %Row_to_delete_id% first and then
DELETE FROM A WHERE a_id = %Row_to_delete_id%, in a transaction,
but i highly recommend you revise your trigger dependencies
If a run an INSERT INTO statement that triggers an INSERT AFTER trigger. What table/row(s) does the inserted and deleted objects represent in the trigger? For example,
INSERT INTO Person.person (personID, name) VALUES (1, 'robert')
CREATE TRIGGER myTrigger
ON Person.person
AFTER INSERT AS
BEGIN
insert into Person.PersonMovies (personID, movieID)
select inserted.personID from inserted _--i know the code is incomplete, but i'm curious only about the inserted part._
END
I'm confused as to what records are held by the inserted table. Would it be the records in the insert statement that triggered the trigger or the Person.PersonMovies table?
Yes, the inserted/deleted tables gives your trigger code access to the records changed by the statement that caused (triggered) the trigger. Also remember that your statements could have effected multiple rows, so your deleted or inserted tables could have multiple records.
The rows in the pseudotables inserted and deleted are based on the table defined in you ON clause.
The Inserted table holds the rows from the original Insert statement that caused the trigger to fire.
See also this MSDN article.
The inserted and deleted pseudotables hold one record for each row in the table that was created or deleted by the statement that fired the trigger. For an update, the deleted table holds the old version of the records, and the inserted table holds the new. The schema of the pseudotables matches the actual table.