Create a string from inserted.id via trigger - sql

I'm creating a trigger on insert that will create a new record in another table using the id from the newly inserted row.
I need to format the id before I insert it into the other table. This is my code so far.... having problems creating the formated #PseudoID.
CREATE TRIGGER OnInsertCreateUnallocatedPseudo
ON tblTeams
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
DECLARE #PseudoID NVARCHAR(50), #tmID NVARCHAR(10)
SELECT #tmID = CONVERT(nvarchar(10),inserted.tmID) FROM inserted
--NEED SOME CODE TO CREATE A PADDED OUT PseudoID e.g.
-- if #tmID = '7' then #PseudoID = 'PSU0007'
-- if #tnID = '25' then #PseudoID = 'PSU0025'
INSERT INTO [dbo].[tblUsersPseudo].....
END

You can't assign it to a variable within the trigger since there could be multiple rows, but you could do something like this to insert into the other table.
LEFT('PSU0000',LEN('PSU0000')-LEN(CONVERT(nvarchar(10),inserted.tmID))) + CONVERT(nvarchar(10),inserted.tmID)

You can't assume that Inserted has only a single row, you have to treat it as a table with 0-N rows and carry out set-based operations on it (rather than procedural).
FORMAT will format your existing id into the new format you require.
INSERT INTO [dbo].[tblUsersPseudo] (id, col1, col2, ...)
SELECT FORMAT(id,'PSU0000')
, col1, col2
FROM Inserted;

Related

Trigger works based on type of insert SQL Server

I am working in SQL Server Management Studio v18, and I have the following trigger:
CREATE TRIGGER [dbo].[update_surface]
ON [dbo].[my_table]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #surface_m2 REAL
SET #surface_m2 = (SELECT cast(round(CAST(Dimension1*Dimension2 as decimal)/ cast(1000000 as decimal),3,3) as decimal(10,3)) AS surface FROM my_table WHERE Surface_m2 IS NULL)
UPDATE dbo.my_table SET Surface_m2 = #surface_m2
END
I have two columns in my_table, which are Dimesion1 and Dimension2. I want that the trigger multiplies them, and set the result to other column in the same table, which is Surface_m2, whenever this column is null. The trigger does his function, but based on the type of insert I do:
If I insert a row in my_table by the graphic environment the trigger works as I wish. With each new row, Surface_m2 has his own result.
But if I insert by INSERT INTO my_table VALUES ().... (query) the trigger updates Surface_m2 column of all previous rows with the result of each new insert.
Why is the trigger working like that? Is there any other simple way to do what I am trying to do?
Thanks.
Insert trigger gives you actual values that are inserted in a special table called... "inserted".
So what you need to do is join this table against your main table and perform the logic needed, no variables required.
Something like this untested code
create trigger...
begin
UPDATE t
SET Surface_m2 = cast(round(CAST(t.Dimension1*t.Dimension2 as decimal)
/ cast(1000000 as decimal),3,3) as decimal(10,3))
from dbo.my_table t
inner join inserted i
ON i.ID = t.ID
WHERE t.Surface_m2 IS NULL
end
This begs the question though, why can't you just insert the Surface_m2 value yourself. Or even better, change Surface_m2 to be a computed column if it's always depends on Dimension1 and Dimension2

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

Internal Trigger to Obtain Newly Inserted Records

I am trying to execute a query but am having trouble. To start I have Table A and Table B. Table A has the following columns (RowID, ItemNumber, CaseCount, Elc, TotalElc, TimeStamp). Table B has the following columns( RowID, ItemNumber, Elc, TotalElc)
I am using a dashboard to insert values into Table A. I am inserting integers into ItemNumber, and CaseCount.
When these values are inserted, I am using an internal trigger on Table A after any inserts that have been made. The internal trigger obtains the values that were just inserted and uses the ItemNumber to lookup Table B to obtain the ELC and Totallc and insert it into Table A where the ItemNumber matches Table B.
How to obtain the values with the trigger to retrieve the newly inserted values (values being ItemNumber, CaseCount)?
Then after the values are retrieved, how to use the item numbers(will be 20 ItemNumbers inserted at once) to look up values in table B and insert them into Table A where the ItemNumber matches?
I don’t have much code since I am practically stuck on number one . Any help is most appreciated.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER ObtainValues
ON Table A
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for trigger here
END
GO
As you have created Trigger on Table A, whenever a row is insert, SQL Server will create a table called INSERTED which holds newly added rows only. The scope of this INSERTED table is within your Trigger body only.
Check the below code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER ObtainValues
ON Table A
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE TableA
SET col1 = B.col1,
col1 = B.col1
FROM TableB B
WHERE B.ItemNumber = (SELECT ItemNumber FROM INSERTED)
END
GO
Similarly, when delete event occurs, DELETED table is created.
Taking Nithin's fine example as a starting point. I modified this so it will handle multiple row inserts.
CREATE TRIGGER ObtainValues
ON TableA
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE TableA
SET col1 = B.col1,
col1 = B.col1
FROM TableB B
INNER JOIN TableA A on a.[YourPrimaryKey] = b.[YourPrimaryKey]
SET NOCOUNT OFF;
GO

After insert not working

all id columns has auto_increment
In my trigger:
ALTER trigger [dbo].[mytrig]
on [dbo].[requests]
after INSERT, UPDATE
as
begin
declare #MyId1 int
set #MyId1 = (select Id from inserted)
declare #MyId2 int
declare #MyId3 int
if (select column1 from inserted) = 1
begin
insert into [dbo].[contracts] select column1,column2,column3 .... from inserted
set #MyId2 = SCOPE_IDENTITY()
insert into [dbo].[History] select column1,column2,column3 .... from inserted
set #MyId3 = SCOPE_IDENTITY()
insert into [dbo].[contracts_depts](Id_Contract ,column5) select #MyId2,column6 from request_depts where Id_request=#MyId1
insert into [dbo].[History_depts] (Id_InHistory,column5) select #MyId3,column6 from request_depts where Id_request=#MyId1
end
end
#MyId1 returns value only after update but not after insert. Do I have to use scope_identity() or something ?
Your main issue is: you're assuming the triggers is called once per row - that is NOT the case!
The trigger is called once per statement, and if your statement affects multiple rows, the Inserted pseudo table will contain multiple rows - so your statement here
set #MyId1 = (select Id from inserted)
really isn't going to work - it will select one arbitrary row (out of however many there are).
You'll need to rewrite your trigger to take this fact into account! Assume that Inserted contains 100 rows - how do you want to deal with that? What are you trying to achieve? Triggers don't return values - they will record into an audit table, or update other rows, or something like that ....