t-sql INSTEAD OF deleting a row PRINT its id - sql-server

Is it possible to make such a trigger that runs when you try to delete a row and prints something like this: "Attempting to delete row ROW_ID", instead of actually deleting the row?
UPD: Thanks. Worked for me:
GO
CREATE OR ALTER TRIGGER Trigger_2 ON Authors
INSTEAD OF DELETE
AS BEGIN
DECLARE #deleted_id INT;
DECLARE cursor_deleted CURSOR
FOR SELECT au_id FROM deleted;
OPEN cursor_deleted;
FETCH NEXT FROM cursor_deleted INTO #deleted_id;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT('Attempting to delete author ' + STR(#deleted_id));
FETCH NEXT FROM cursor_deleted INTO #deleted_id;
END;
CLOSE cursor_deleted;
DEALLOCATE cursor_deleted;
END;
GO
DELETE FROM Authors WHERE au_id BETWEEN 1 AND 10;

Yeah it is, and there are many approaches.
using a trigger you can either set the trigger to run after a deletion and u will have to use "ROLLBACK" to undo the deletion operation.
or just simply use INSTEAD OF where as the name suggests the trigger will replace the who deletion operation.
hope this helps in any way.
ps: after a deletion operation deleted data are stored in a Global table named "deleted" use to get any data or metaData that u need.
CREATE TRIGGER schema_name.trigger_name
ON table_name
// this trigger is executed instead of any deletion
INSTEAD OF DELETE
AS
BEGIN
// return the one to be deleted's id.
return deleted.id
END

Related

SQL Server Trigger DELETE only a few records [duplicate]

I want to create a trigger to check what is being deleted against business rules and then cancel the deletion if needed. Any ideas?
The solution used the Instead of Delete trigger. The Rollback tran stopped the delete. I was afraid that I would have a cascade issue when I did the delete but that didn't seem to happen. Maybe a trigger cannot trigger itself.
Use an INSTEAD OF DELETE (see MSDN) trigger and decide within the trigger what you really want to do.
The solution used the Instead of Delete trigger. The Rollback tran stopped the delete. I was afraid that I would have a cascade issue when I did the delete but that did'nt seem to happen. Maybe a trigger cannot trigger itself. Anyhow, thanks all for your help.
ALTER TRIGGER [dbo].[tr_ValidateDeleteForAssignedCalls]
on [dbo].[CAL]
INSTEAD OF DELETE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #RecType VARCHAR(1)
DECLARE #UserID VARCHAR(8)
DECLARE #CreateBy VARCHAR(8)
DECLARE #RecID VARCHAR(20)
SELECT #RecType =(SELECT RecType FROM DELETED)
SELECT #UserID =(SELECT UserID FROM DELETED)
SELECT #CreateBy =(SELECT CreateBy FROM DELETED)
SELECT #RecID =(SELECT RecID FROM DELETED)
-- Check to see if the type is a Call and the item was created by a different user
IF #RECTYPE = 'C' and not (#USERID=#CREATEBY)
BEGIN
RAISERROR ('Cannot delete call.', 16, 1)
ROLLBACK TRAN
RETURN
END
-- Go ahead and do the update or some other business rules here
ELSE
Delete from CAL where RecID = #RecID
END
The trigger can roll back the current transaction, which will have the effect of cancelling the deletion. As the poster above also states, you can also use an instead of trigger.
According to MSDN documentation about INSTEAD OF DELETE triggers:
The deleted table sent to a DELETE
trigger contains an image of the rows
as they existed before the DELETE
statement was issued.
If I understand it correctly the DELETE is actually being executed. What am I missing?
Anyway, I don't understand why do you want to delete the records and if the business rules are not passed then undelete those records. I would have swear it should be easier to test if you pass the business rules before deleting the records.
And I would have said use a transaction, I haven't heard before about INSTEAD OF triggers.

SQL Server 2014, trigger : how to iterate over deleted rows?

ATTENTION! Using trigger is necessary for me! The only way needed for me to perform following task - is to use trigger!
The question is - I need a trigger, which would be called on rowS deletion in a certain table. The thing trigger must do - iterate over every deleted
row, and perform some code - depending on current iterated row values.
for example, I made this trigger, which works when I delete one row
by command
DELETE FROM books WHERE id=5
the trigger is here:
GO
CREATE TRIGGER onBookDelete ON books
INSTEAD OF DELETE
AS
DECLARE #book_id int
BEGIN
SET NOCOUNT ON;
SELECT id FROM deleted
SET #book_id = (SELECT id FROM deleted)
PRINT #book_id
BEGIN
DELETE FROM "books-topics" WHERE book_id=#book_id
DELETE FROM "books-genres" WHERE book_id=#book_id
DELETE FROM books WHERE id=#book_id
END
END;
So, what I want to achieve - is to create trigger with same task,
but it must work when I delete many rows at one time, for example
DELETE FROM books WHERE id=5 OR id=3 OR id=8
by same task I mean, for example, calling the following code on each deleted row
DELETE FROM "books-topics" WHERE id=DELETEDROW.book_id
DELETE FROM "books-genres" WHERE id=DELETEDROW.book_id
DELETE FROM books WHERE id=DELETEDROW.book_id
Your teacher should have thought about a better example for an instead of delete trigger. This problem is what on delete cascade is there for in the first place.
However, since your assignment is to use a trigger, I would suggest something like this instead:
CREATE TRIGGER onBookDelete ON books
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRASACTION
BEGIN TRY
DELETE bt
FROM "books-topics" bt
INNER JOIN deleted d ON bt.book_id= d.book_id
DELETE bg
FROM "books-genres" bg
INNER JOIN deleted d ON bg.book_id= d.book_id
DELETE b
FROM books b
INNER JOIN deleted d ON b.book_id= d.book_id
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH
END;

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.

SQL Server: trigger updating a just inserted row

I currently working with an old application that I don't own any source code but I really need to add some new logic to the app.
The only way I found to do it is to mess up with database data, and change whatever I need with a trigger.
I wrote the following trigger that should update 2 columns of a just inserted row:
CREATE TRIGGER addLoteInfo ON fi
FOR INSERT
AS
DECLARE
#loteN varchar(15),
#refN varchar(18),
#CientifN varchar(40),
#CaptureZ varchar(20)
declare MY_CURSOR cursor for
select
i.lote, i.ref
from inserted i
open MY_CURSOR
fetch next from MY_CURSORinto #loteN, #refN
while ##fetch_status = 0
begin
SELECT #CientifN = u_ncientif FROM SE where lote LIKE #loteN and ref LIKE #refN;
SELECT #CaptureZ = u_zcaptura FROM SE where lote LIKE #loteN and ref LIKE #refN;
UPDATE FI SET LNCIENT=#CientifN, LZCAP=#CaptureZ;
fetch next from CURSOR_TESTE into #loteN, #refN
end
close MY_CURSOR
deallocate MY_CURSOR
The problem is when a new registry is inserted, it seems it gets to a deadlock.
Its impossible to do what I'm trying to do?
Can you help me with another approach?
You need to use INSTEAD OF trigger if you want to modify newly inserted/updated record on the fly.

preventing a specific record from being deleted

I want to prevent a specific record from being deleted. This trigger works fine for that specific record. However, other records still remain when they're being deleted. Why?
ALTER TRIGGER [Globalization].[CountriesTracker]
ON [Globalization].[Countries]
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
IF ((Select COUNT(*) from [Deleted]
Where [Deleted].[CountryId] = '36bd1536-fb56-4ec4-957e-1b3afde16c56') = 1)
BEGIN
RAISERROR('You can not delete this specific record!', 0, 0)
ROLLBACK TRANSACTION
RETURN
END
END
How can I ensure that rows not matching the above condition are being deleted as expected?
You have an INSTEAD OF trigger so you need an actual DELETE in it.
I'd also consider simply filtering the protected row out because:
Do you need an error throwing? Or silently ignore?
What about multi row deletes that contain the protected row: abort the whole, or delete the rest?
Something like:
ALTER TRIGGER [Globalization].[CountriesTracker] ON [Globalization].[Countries]
INSTEAD OF DELETE
AS
SET NOCOUNT ON;
DELETE
CT
FROM
[Globalization].[Countries] C
JOIN
DELETED D ON C.CountryId = D.CountryId
WHERE
[Deleted].[CountryId] <> '36bd1536-fb56-4ec4-957e-1b3afde16c56'
GO
Because this is INSTEAD OF you still need to perform the delete operation for the default case.

Resources