SQL Server trigger inserting whole table rows, instead of new - sql-server

I m making a mistake somewhere but can't figure out.
Scenario is this:
Whenever a new row is inserted in table 'TestTrigger', the table TriggerInsert should get a value capturing time when a new row was inserted in TestTrigger.
The problem is, whenever the trigger hits, instead of just a new row, the whole table gets repopulated in TestTrigger, each time. I only want to capture, the new rows not the entire table getting inserted on each trigger.
Here is my trigger:
USE [irfaan]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Trigger [dbo].[InsertTriggerTest] on [irfaan].[dbo].[TestTrigger]
--For Insert
After insert
as
INSERT into TriggerInsert (CurrTime, IOFNum) SELECT (GetDate()), SONum FROM TestTrigger
Please assist where I am going wrong.

If you want to look at just the rows that were inserted, you must use the Inserted pseudo table - not the dbo.TestTrigger base table....
ALTER TRIGGER dbo.InsertTriggerTest
ON irfaan.dbo.TestTrigger
FOR INSERT
AS
INSERT INTO TriggerInsert (CurrTime, IOFNum)
SELECT GETDATE(), SONum
FROM Inserted

Your SELECT query is returning all rows from your source table (TestTrigger). Use the table inserted instead. It will contain just the rows that are being inserted into TestTrigger instead of all of the rows as you are currently getting.
INSERT into TriggerInsert (CurrTime, IOFNum) SELECT (GetDate()), SONum FROM Inserted

Related

get last inserted primary key of type varchar in sql server

i have two table userGold and AspNetUserRoles(UserId,RoleId) .
primary key type of UserGold is nvarchar(450)
same for AspNetUserRole.
my problem is that i want to get the last inserted primary key in UsereGold and insert it in AspNetUserRoles table using a trigger.
SCOPE_IDENTITY didn't work cause my primary key type is nvarchar.
i don't know what to do.
i saw solution like output inserted but it didn't work
create trigger addrole
on UserGold
after Insert
as
Begin
declare
#userid nvarchar(450)
set #userid=CAST(SCOPE_IDENTITY() AS nvarchar(450))
insert into AspNetUserRoles(UserId,RoleId)
values(#userid,'2c258e8d-c648-4b38-9b01-989d4dd525fe')
end
You should not write triggers - or anything else in a database - that only expect a single row to change. Databases work with sets of information, not single "records". Imagine what happens if someone create 5 rows in UserGold in a single insert statement. You can't put 5 userid values into a single #userId variable.
What you want is something like
-- assuming your tables are in the dbo schema! Make sure you include the schema name
create trigger AddDefaultRole on dbo.UserGold after insert as begin
set nocount on;
insert dbo.AspNetUserRoles (UserId, RoleId)
select UserId, '2c258e8d-c648-4b38-9b01-989d4dd525fe'
from inserted;
end
For more information, see Inserted and Deleted tables for triggers

SQL Server Inserting multiple rows using Triggers

I am loading data from a JSON file to a table "main.jsontable" the trigger job is to insert the data of all different countries from "main.jsontable" into "main.country" table. My problem is that the trigger needs to handle inserting multiple rows my current code is:
create or alter trigger main.afterParsing
on main.jsontable
after insert
as
begin
declare #country nvarchar(50);
insert into main.country(countryName)
values(#country)
end;
but I get this error (obviously because triggers can only handle inserting 1 row at a time):
Cannot insert the value NULL into column 'countryName', table 'assignment2.main.country'; column does not allow nulls. INSERT fails.
Does anyone know how I can use the trigger to insert multiple rows?
Thanks
You need to use the Inserted pseudo table, and you need to understand that it can contain multiple rows (if your INSERT statement inserted more than 1 row at once), and you need to treat that table accordingly, using a proper set-based approach.
Try something like this:
create or alter trigger main.afterParsing
on main.jsontable
after insert
as
begin
insert into main.country(countryName)
select countryName
from Inserted
-- if the data being inserted could have NULL in the
-- countryName - filter those entries out
where countryName is not null
end;

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

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.

adding data in column depending on another columns in same table

Dear
i already create one table for employee information with ASP.net interface
now i show add one operation in my table as below,
i have four columns( WorkDatey,WorkDatem,WorkDated,absentday) all the columns from integer type in table name employee.
now i should add new column (realworkdays) and the result here should be automatic save after entering previous data as example:
WorkDatey= 2011 ,
WorkDatem= 2 ,
WorkDated=14 ,
absentday=6
the operation should be : (2011*365)+(2*30)+(14)-(6) and result will store in column (realworkdays).
i already try it as trigger but i have some thing wrong:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER daysResult
ON [dbo].[employee]
AFTER insert
As
DECLARE #realworkdays int
BEGIN
SET NOCOUNT ON;
select WorkDatey,WorkDatem,WorkDated,absent from [dbo].[employee]
#realworkdays= (workdatey*350)+(workdatem*29)+(workdated)-(absent)
insert into [dbo].[employee] (totaldays)values (#realworkdays)
END
GO
Since you are using sql server 2005, i would suggest you use a computed column
ALTER TABLE employee DROP COLUMN realworkdays;
ALTER TABLE employee ADD COLUMN realworkdays AS (
(WorkDatey * 365) +
(WorkDatem * 30) +
(WorkDated) -
(absentday)
)
You can add the PERSISTED so it will store the data, optionally indexing it.
On a side note, your trigger is inserted a new row, instead of updating the value of the current row.
You are supposed to update the inserted records, not insert new ones.
So, it should be the UPDATE statement, and you can do both the calculations and the updates in one go.
CREATE TRIGGER daysResult
ON [dbo].[employee]
AFTER insert
AS
BEGIN
UPDATE employee
SET realworkdays = (inserted.workdatey*350)+(inserted.workdatem*29)+
(inserted.workdated)-(inserted.absent)
FROM inserted
WHERE employee.ID = inserted.ID
END
Still it would be better to use a computed column, as #The Scrum Meister has suggested.

Resources