Insert trigger in SQL Server - sql

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

Related

INSERT return value of stored procedure

I'm trying to INSERT a RETURN value for a stored procedure and I just can't get it to work.
I have one table called "person.person_ids" with fields "id int, uid uniqueidentifier"
and a bunch of other tables called for example "person.employee", "person.client" etc. These tables all get their "id"s as foreign keys from the "person.person_ids" table.
The procedure does this:
CREATE PROCEDURE PERSON.NewPerson
AS
BEGIN
DECLARE #ret INT;
INSERT INTO PERSON.ID_PERSON
VALUES (NEWID());
SET #ret = SCOPE_IDENTITY()
RETURN #ret;
END
GO
and my INSERT looks like this:
INSERT INTO PERSON.EMPLOYEE VALUES
(EXECUTE PERSON.NewPerson, 1, '15434235', '10768348153', '1962-3-2', '1999-10-2', 'PETER', '', 'SMITH', 'HAMMER')
GO
Basically I'm trying to create a stored procedure of function that I can call to automatically generate a new record in "person.person_ids" whenever I insert a new record into "person.employee".
I tried using OUTPUT from INSERT but I could not get it to work and INSERT isn't allowed inside of functions.
Here is your code with the issues fixed and some recommended improvements. The comments explain what and why.
SP:
CREATE PROCEDURE PERSON.NewPerson
(
-- Use an output parameter to get values out of an SP
#NewId INT OUT
)
AS
BEGIN
-- Recommended to always list the columns you are inserting to
-- Personally my preference is to select them (because that scales to multiple inserts), I never use the 'values' clause.
INSERT INTO PERSON.ID_PERSON (uid)
SELECT NEWID();
SET #NewId = SCOPE_IDENTITY();
-- The return statement is for a status for the SP, usually 0 for success, some other int for an error
RETURN 0;
END
GO
Calling SP:
DECLARE #MyNewId INT;
-- Run the SP before your insert to get your new value
EXEC PERSON.NewPerson #MyNewId OUT;
-- Then insert - ideally with a list of columns
INSERT INTO PERSON.EMPLOYEE
SELECT #MyNewId, 1, '15434235', '10768348153', '1962-3-2', '1999-10-2', 'PETER', '', 'SMITH', 'HAMMER'

FIM - SQL Triggers for updating records in Delta table

I'm writing a DML trigger when change (update or Insert) happens in one table (Master table), I want to write the whole row into another table (Delta table).
The Master and Delta tables contains the same column with same datatype, except that Delta table contains an additional column called 'change_type', which should say either 'INSERT' OR 'MODIFY', depending on which trigger is updating the delta table.
The difficulty I'm having is I want to use the inserted table to update the Delta table row but its giving me errors.
CREATE TRIGGER [dbo].[TR_Update]
ON [dbo].[People_Master]
AFTER Update
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #RowCount int
Declare #ID int
Declare #Email nvarchar(50)
Declare #ct nvarchar(10)
select #ID = ID from inserted
Select #RowCount=COUNT(*) from People_Delta where People_Delta.ID = #ID and People_Delta.change_type = 'Modify';
if(#RowCount = 0)
Begin
Insert into People_Delta (ID,Email,uac,Department,FirstName,change_type)
values (iserted.ID,inserted.Email,inserted.uac,inserted.Department,inserted.Firstname'Modify');
END
END
GO
My table has 5 columns.
ID (primary key)
Email
Firstname
uac
Department
You are missing a , in your INSERT statement.
And because the number of columns you have specified does not match with the number of values you are inserting, you get an error.
inserted.Firstname , 'Modify'
Insert into People_Delta (ID,Email,uac,Department,FirstName,change_type)
values (iserted.ID,inserted.Email,inserted.uac,inserted.Department,inserted.Firstname,'Modify');

Insert trigger with an IF statement

I'm looking for a way to fire a trigger based on a condition and below is my sql. How do i include an IF statement in this trigger to fire if ac_mail = '1#mail.com'
CREATE TRIGGER username
ON temp
AFTER INSERT
AS
DECLARE #var1 int ,#var2 char (100)
select #var1 = al_id, #var2 = ac_mail
From temp
BEGIN
INSERT INTO user (v_id,v_m)
VALUES (#var1,#var2)
END
The trigger should only fire if ac_mail = '1#mail.com'
Triggers can fire for multiple rows - so using scalar variables to capture the data is usually wrong. As is querying the base table rather than inserted - inserted contains just the rows that caused the trigger to fire, whereas you're querying temp for any random row. And finally, of course, as I've said twice now, multiple rows. So you don't want an if because some of those rows might match your condition and other might not match.
I think you want:
CREATE TRIGGER username
ON temp
AFTER INSERT
AS
INSERT INTO user (v_id,v_m)
select al_id,ac_mail from inserted where ac_mail = '1#mail.com'
See how much simpler it is?
try this :-
CREATE TRIGGER username
ON temp
AFTER INSERT
AS
DECLARE #var1 int ,#var2 char (100)
Select #var1 = al_id
,#var2 = ac_mail
From inserted
IF #var2 = '1#mail.com'
BEGIN
INSERT INTO user (v_id,v_m)
VALUES (#var1,#var2)
END
Try this sql
CREATE TRIGGER username
After INSERT ON temp
REFERENCING NEW ROW AS New
FOR EACH ROW
if(New.ac_mail=='1#mail.com')
begin
INSERT INTO user (v_id,v_m)
VALUES (New.al_id,New.ac_mail)
end

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

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

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.