How to fire trigger after every insert in sql server table automatically? - sql

I am new to SQL Server triggers. I am facing a problem recently that I have two tables named tbl_Item and tbl_changePrice. I want to update tbl_Item when tbl_changeprice is inserted new row. With this new row name same date data will be updated in tbl_item table.
Here is my trigger what is tried by me for updating the table:
Alter TRIGGER trgAfterInsert ON [dbo].[tbl_changePrice]
After insert
AS
declare #itemname int;
declare #saleprice decimal(18,2);
declare #buyprice decimal(18,2);
select #itemname=i.name from inserted i;
select #saleprice=i.saleprice from inserted i;
select #buyprice=i.pprice from inserted i;
update tbl_Item set sellingPrice= #saleprice, buyingPrice= #buyprice where name= #itemname
PRINT 'AFTER INSERT trigger fired.'
GO

To handle multiple rows being inserted at once - you need to rewrite your trigger to be able to deal with multiple rows in Inserted - something like this:
ALTER TRIGGER trgAfterInsert
ON [dbo].[tbl_changePrice]
AFTER INSERT
AS
UPDATE dbo.tbl_Item
SET sellingPrice = i.saleprice, buyingPrice = i.pprice
FROM Inserted i
WHERE tbl_Item.name = i.name
PRINT 'AFTER INSERT trigger fired.'
GO

Related

Insert trigger in SQL Server

I am trying to write a trigger that inserts in a log table the date, name of the table I inserted in, the name of the operation (insert, delete, update) and the number of insertion.
Here is my code:
CREATE TRIGGER [dbo].[Inser]
ON [dbo].[Avion]
AFTER INSERT
AS
BEGIN
DECLARE #codAv int
DECLARE #NumeAv varchar(100)
DECLARE #MotorAv varchar(100)
SELECT #codAv = INSERTED.codA FROM INSERTED
SELECT #NumeAv = INSERTED.NumeA FROM INSERTED
SELECT #MotorAv = INSERTED.Motor FROM INSERTED
SELECT ##ROWCOUNT AS INSERTED;
INSERT INTO LogM (DataM, Numele, Tipul, Numar)
VALUES(GETDATE(), 'Avion', 'Inserare', ##ROWCOUNT);
PRINT 'INSERT trigger fired.'
END
I have a stored procedure where I have something like 20 insertion of this type:
INSERT INTO Avion (Motor,NumeA)
VALUES ('Junkers','Focke-Wulf');
all separated from one another. When I run that code, the table LogM will be populated with 20 new rows of this type:
5 Nov 27 2016 8:58PM Avion Inserare 1.00
I want to make my trigger to count all the insertion stored in a procedure, then insert in LogM only one entry, with the ROWCOUNT not being 1.00, but the number of insertion I made in that stored procedure, and I don't have any idea how can I do this.
Thank you.
Instead of passing ##ROWCOUNT you can not just pass the ID?
##ROWCOUNT works to return the number of rows affected, as you enter one at a time, it will always be one.
CREATE TRIGGER [dbo].[Inser]
ON [dbo].[Avion]
AFTER INSERT
AS
BEGIN
DECLARE #codAv int
DECLARE #NumeAv varchar(100)
DECLARE #MotorAv varchar(100)
SELECT #codAv=INSERTED.codA FROM INSERTED
SELECT #NumeAv=INSERTED.NumeA FROM INSERTED
SELECT #MotorAv=INSERTED.Motor FROM INSERTED
INSERT INTO LogM
(DataM,Numele,Tipul,Numar)
VALUES(GETDATE(),'Avion','Inserare',#codAv);
PRINT 'INSERT trigger fired.'
END

Sql Trigger to add new row when table update

I am new to sql triggers and learning as developing triggers for asp.net application.i am having case where I need to first save table and then edit the same table - this edit create new row in different table but the the problem is every time I edit the table it create new row in different table I want to create row in different table for only first edit.
Dividing my problem for readability.
I have two tables:
Table A and table B
I have written trigger on table A that add row in table B.
Problem:
Every time I edit row in table A a new row get added to table B. (So every edit create new row)
Required result:
I want my trigger to add ONLY one row in table B for the first edit in table A but not for subsequent edits.
I am using update triggers.
Any example with code would be great
Thanks you much in advance .
Create TRIGGER [dbo].[triggerName] ON [dbo].[databaseName]
For Update
As
Begin
DECLARE #i int
DECLARE #d int
DECLARE #action char(6)
DECLARE #Car VARCHAR(20)
IF (##ROWCOUNT = 0) RETURN
SELECT #i = Count(*) From Inserted
SELECT #d = Count(*) From Deleted
SELECT #action = CASE
WHEN (#i <> 0) and (#d <> 0) THEN 'UPDATE'
WHEN (#i = 0) and (#d <> 0) THEN 'DELETE'
WHEN (#i <> 0) and (#d = 0) THEN 'INSERT'
End
SELECT #Car = A From inserted
IF #action = 'UPDATE' AND #Car in ('BMW')
Begin
INSERT INTO Tableb (c,d,f)
Select c,d,f from inserted
End
Your trigger has some flaws in it.
First, You don't need to test if it was fired because of update, insert or delete. The trigger is specified for update, so inserts and deletes will not fire it anyway.
Second, SELECT #Car = A From inserted will raise an error whenever you update more then one row in the table.
Third, As you said, this will insert a record in tableB for every update, while you want it to insert a record only for the first update done (I assume one for the first update on any row, so if you update row 1 then insert, update row 2 then another insert, and update row 1 again don't insert).
I would write it like this:
Create TRIGGER [dbo].[triggerName] ON [dbo].[tableName]
For Update
As
Begin
INSERT INTO Tableb (c,d,f)
Select c,d,f
from inserted i
left join Tableb t ON(i.c = t.c and i.d = t.d and i.f = t.f)
where t.id is null -- or some other non-nullable column
and i.a = 'BMW'
End
You can modify your SQL trigger to execute only after INSERT
CREATE TRIGGER dbo.myTable_Insert
ON dbo.myTable
AFTER INSERT
AS
It is possible to create SQL trigger to run after insert, update or delete as seen in the referred tutorial

Trigger preventing a column from being updated

I have created a trigger as below:
CREATE TRIGGER InsertUpdateATLastViewedMatch
ON dbo.AT_LastViewedMatch
FOR INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
-- update statements for trigger here
declare #id1 int, #matchFK int;
select #id1 = i.id from inserted i;
select #matchFK=i.AT_MatchFk from inserted i;
update dbo.AT_LastViewedMatch set matchId = #matchFK where id = #id1;
END
GO
While this trigger works- I am not able to update the value of the matchId column directly from SQLManager:
If I execute
UPDATE AT_LastViewedMatch set matchId='1179619' where id=5762
for example, I am still seeing the old value for matchId. I think the issue is related to the above trigger (since if I drop the trigger, it works). Is there a way to get past this?
From your trigger definition below, you have created it for insert and update
CREATE TRIGGER InsertUpdateATLastViewedMatch
ON dbo.AT_LastViewedMatch
FOR INSERT,UPDATE <-- Here
so essentially, whenever you are running an update statement from SSMS
UPDATE AT_LastViewedMatch set matchId='1179619' where id=5762
Your trigger performing the below line and setting it to old value
update dbo.AT_LastViewedMatch set matchId = #matchFK where id = #id1;
You need to remove that update from your trigger definition
CREATE TRIGGER InsertUpdateATLastViewedMatch
ON dbo.AT_LastViewedMatch
FOR INSERT

Updating a Table after some values are inserted into it in SQL Server 2008

I am trying to write a stored procedure in SQL Server 2008 which updates a table after some values are inserted into the table.
My stored procedure takes the values from a DMV and stores them in a table. In the same procedure after insert query, I have written an update query for the same table.
Insert results are populated fine, but the results of updates are getting lost.
But when I try to do only inserts in the stored procedure and I execute the update query manually everything is fine.
Why it is happening like this?
there should not be a problem in this.
below code working as expected.
create procedure dbo.test
as
begin
create table #temp (
name varchar(100) ,
id int
)
insert #temp
select name ,
id
from master..sysobjects
update #temp
set name='ALL Same'
from #temp
select * from #temp
drop table #temp
end
go
Best approach is to use Trigger, sample of AFTER UPDATE trigger is below:
ALTER TRIGGER [dbo].[tr_MyTriggerName]
ON [dbo].[MyTableName] AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
--if MyColumnName is updated the do..
IF UPDATE (MyColumnName)
BEGIN
UPDATE MyTableName
SET AnotherColumnInMyTable = someValue
FROM MyTableName
INNER JOIN Inserted
ON MyTableName.PrimaryKeyColumn = Inserted.PrimaryKeyColumn
END
END

Can a storeProcecdure insert fire Trigger?

SQL Server 2008
I have trigger defined on
TABLE_A for 'INSTEAD OF INSERT' and TABLE_B for 'INSTEAD OF INSERT'.
Both the triggers perform merge with the inserted table.
TABLE_A insert is done by user/code and is working well, trigger for insert is fired.
I have Stored procedure SP_1 inside TABLE_A TRIGGER.
SP_1 Inserts data from TABLE_A into TABLE_B based on some conditions.
But the problem is when the stored procedure (SP_1) is inserting data, the trigger on TABLE_B is not fired and the data is just inserted as it is.
So can stored procedure inserts fire triggers?
Pseudo-code
ALTER TRIGGER [dbo].[trgtable_AInsert] ON [dbo].[TABLE_A]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
.......
...........
..............
end
EXEC SP_1 #employee_id
end
ALTER TRIGGER [dbo].[trgtableB_Insert] ON [dbo].[TABLE_B]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
.......
...........
..............
end
end
ALTER PROCEDURE [dbo].[SP_1] #employeeid int
AS
BEGIN
BEGIN TRANSACTION
insert into TABLE_B
.......
...........
..............
from TABLE_A
where employee_ID is #employeeid
COMMIT TRANSACTION
END
Yes triggers can fired by stored procedure inserts!
But I think the problem is that you should try to use AFTER instead of INSTEAD OF triggers in this case. Becasue I can't see all of your code, but it is possible, that the insert is not done because you overrided it in the Instead Of triggers. With AFTER triggers you should have no problems with firing the second trigger.
This is too big for a comment, and needs formatting, so posting as an "answer".
Yes, triggers will fire in this case. Taking your example and slightly modifying it (note the warnings though):
create table Table_A (ID int not null)
go
create table Table_B (ID int not null)
GO
CREATE PROCEDURE [dbo].[SP_1] #employeeid int
AS
BEGIN
BEGIN TRANSACTION
insert into TABLE_B (ID)
SELECT ID from TABLE_A
where ID = #employeeid
COMMIT TRANSACTION
END
GO
Creating the triggers:
CREATE TRIGGER [dbo].[trgtable_AInsert] ON [dbo].[TABLE_A]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
into Table_A a
using inserted i on a.id = i.id
when not matched then insert (ID) values (i.id);
end
--Wrong code, just for example
declare #employee_id int
select #employee_id = ID from inserted --BAD CODE, Ignores multiple rows
EXEC SP_1 #employee_id
end
GO
CREATE TRIGGER [dbo].[trgtableB_Insert] ON [dbo].[TABLE_B]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
into Table_B b
using inserted i on b.id = i.id
when not matched then insert (ID) values (i.id+5);
end
end
GO
And executing a trial insert into Table_A:
insert into Table_A (ID) values (1),(2)
select * from Table_B
On my machine, at the present time, I get a final result of a single row with the value "7". Others may run this sample and get the result "6", because triggers only run once per statement, rather than once per row. But as you can see, both triggers have fired.
As i previously mentioned in the comments #András Ottó
Merge
using(... = "column with possible null values" AND
... = ... AND
... = ...
)
of merge was not working correctly and the records were always inserted.
1 = 1 and E=E and NULL=NULL is not true. (of-course sql 101)
I have overlooked this column and did not place where clause properly to get rid of null values so ended up inserting all the time. Fixing that everything ended up working.
Thanks for the help Every1. Cheers
Apologies.
I'm not going to mark it answered because it is purely my mistake which was not fully mentioned in the question.