Can we use both instead of and after in triggers? - sql-server

I want to define instead of for insert and update operations but after for the delete operation.
Is it possible? Or, do I need to write an additional trigger for that? For example, no rows can be removed.
CREATE TRIGGER test_trigger ON my_table
instead of INSERT,UPDATE for DELETE
AS
BEGIN
.......
END

It seems you would need 2 triggers. Only 1 INSTEAD OF trigger may be create per DML action type per table, although DML action types may be combined, as in this case, i.e. both INSERT and UPDATE.
CREATE TRIGGER test_trigger_instead_of_ins_upd ON my_table
instead of INSERT,UPDATE
AS
BEGIN
.......
END
---------------------------------------------------------
CREATE TRIGGER test_trigger_after_del ON my_table
after DELETE
AS
BEGIN
.......
END

Related

Trigger to update a record to null whenever there is an insert or update on a row in the table in Oracle DB

Need help in writting a Trigger to update a record to NULL whenever there is an insert or update on a row in the table in Oracle DB.
CODE
create or replace trigger updateRowToNull
AFTER
UPDATE OR INSERT
ON CUSTOMER for each row
BEGIN
update customer set customeraddr=NULL;
END;
A trigger cannot modify the table to which it is attached with a separate transaction. A "before" trigger can, however, manipulate column values within the transaction that causes it to be fired.
create or replace trigger update_row_to_null
before update or insert on customer
for each row
begin
:new.customeraddr := null;
end;

Trigger for both insert and update

I'm trying to create a trigger that will prevent a user from inserting to or updating the quantity in my orderLines table if the amount is greater than the quantity on the products table.
Is there a way to do it in a single trigger or do I have to create to separate ones for both insert and update actions?
Below is how my trigger starts:
CREATE TRIGGER OrdersLines_ITrig
ON ordersLines
FOR INSERT
AS
Depends on the BEGIN/END blocks:
Triggers have special INSERTED and DELETED tables to track "before" and "after" data. So you can use something like IF EXISTS (SELECT * FROM DELETED) to detect an update. You only have rows in DELETED on update, but there are always rows in INSERTED.
CREATE TRIGGER dbo.TriggerName
ON dbo.TableName
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
BEGIN
----Do update
END;
IF EXISTS (SELECT * FROM Inserted) AND NOT EXISTS (SELECT * FROM deleted)
BEGIN
-----Do insert
END;
END
This is a simple requirement you can handle using CHECK CONSTRAINT itself. If you are defining trigger, you have to properly rollback the transaction. Have proper error message etc. You can simply have a check constraint, which will do all these things for you.
I would suggest you to do below steps:
Create a user defined function, which returns TRUE or FALSE, based on the quantity in the Product table.
CREATE FUNCTION CheckQuantity(#productID INT)
RETURNS BIT
AS
BEGIN
---LOGIC
END
Leverage the user defined function in the CHECK constraint.
ALTER TABLE OrderLines ADD CONSTRAINT CHK_Quantity CHECK( dbo.CheckQuantity(ProductId) = = 1)

Clone Sql table automatically from sql

I have two exactly same tables. My question: is there any way when i'm inserting something in first table automatically sql server to copy this row into another table.
I know that i can do it manually
select * into table1 from table2 where table2ID=#table2ID
But i'm wondering if i can create a table dynamically and set it when a row is inserted, copy row's data into another table also.
So with this way i dont need to run extra code to do that, sql will do this automatically
You can use a TRIGGER which is an object that you link to a table with a particular operation (INSERT, UPDATE, DELETE or any combination of those). The trigger's code will execute on each operation done to the linked table.
Basic example:
CREATE TRIGGER dbo.CopyToTable2 ON Table1
AFTER INSERT -- The trigger will execute after any insert done to Table1
AS
BEGIN
SET NOCOUNT ON
INSERT INTO Table2 (
Column1,
-- OtherColumns
)
SELECT
I.Column1
-- OtherColumns
FROM
inserted AS I -- "inserted" is a special table that references the trigger's tracking table for new or updated records
END
The use of a trigger is appropriate here. It might look something like this:
CREATE TRIGGER SomeTriggerName ON theSourceTable
FOR INSERT
AS
INSERT INTO DestinationTable
(column1, someothercolumn)
SELECT (column1, someothercolumn)
FROM inserted

Prevent insert on trigger and perform an update instead

I have a trigger that is raised after an insert or update. In case of an insert, I want to check if the record being inserted on table exists. If exists, then I want to ignore the insert and perform an update within trigger for that record. How can I do this? Is is possible to do it within an after insert,update trigger (not using instead of trigger)?

Trigger not firing for all rows when inserting multiple rows SQL

Am facing a problem with trigger.
I created a trigger for a table like this
ALTER TRIGGER [dbo].[manageAttributes]
ON [dbo].[tr_levels]
AFTER insert
AS
BEGIN
set nocount on
declare #levelid int
select #levelid=levelid from inserted
insert into testtable(testid) values(#levelid)
-- Insert statements for trigger here
END
But when I insert rows into table tr_levels like this
insert int tr_levels (column1,colum2) values(1,2)
trigger triggered perfectly
But when I tried to insert into table as a bulk like this
insert int tr_levels (column1,colum2) values(1,2),(3,4),(5,6)..
Trigger doesnt fires for all the rows. It fires only one time for the first row. Is that bug with SQL or is there a solution to trigger the trigger for all rows insertion in a bulk insert query
No, it does fire for all rows - once - but you're ignoring the other rows by acting as if inserted only contains one. select #scalar_variable=column from inserted will arbitrarily retrieve a value from one of the rows and ignore the others. Write a set-based insert using inserted in a FROM clause
You need to treat inserted as a table that can contain 0, 1 or multiple rows. So, something like:
ALTER TRIGGER [dbo].[manageAttributes]
ON [dbo].[tr_levels]
AFTER insert
AS
BEGIN
set nocount on
insert into testtable(testid)
select levelid from inserted
END
You have the same issue many people have that: you think the trigger is fired per row. It is not - it is per operation. And inserted is a table. You take one (random) value and ignore the rest. Fix that and it will work.
Triggers fire once per statement in the base table. So if you insert 5 rows in one statement, the trigger fires once and inserted has the 5 rows.

Resources