SQL Server Inserting multiple rows using Triggers - sql-server

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;

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

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

SQL Server trigger inserting whole table rows, instead of new

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

i am using insert statement to insert data from oracle forms to database but its inserting 2 rows instead of one

I am using insert statement to insert data from oracle forms to database but instead of one row.. its inserting two rows automatically..?
I am using the following query:
insert into xx_book_grp3 ( BOOK_ID,AUTHOR_ID,ISBN,PAGES,PUBLISHING_DATE,BOOK_TYPE,COST,BOOK_NAME) values (xxtrn_grp3_book_id.nextval,:XX_BOOK_GRP3.AUTHOR_ID,:XX_BOOK_GRP3.ISBN,:XX_BOOK_GRP3.PAGES,:XX_BOOK_GRP3.PUBLISHING_DATE,
:XX_BOOK_GRP3.BOOK_TYPE,
:XX_BOOK_GRP3.COST,
:XX_BOOK_GRP3.BOOK_NAME);
commit;
Try this to prevent duplicate insert:
-- I think you can check for existing record on author_id and isbn or even isbn only is sufficient:
Declare
v_count number;
Begin
Select count(*) into v_count from xx_book_grp3
where author_id = :xx_book_grp3.author_id and isbn = :xx_book_grp3.isbn;
if v_count = 0 then
insert into xx_book_grp3 ( BOOK_ID,AUTHOR_ID,ISBN,PAGES,PUBLISHING_DATE,BOOK_TYPE,COST,BOOK_NAME) values (xxtrn_grp3_book_id.nextval,:XX_BOOK_GRP3.AUTHOR_ID,:XX_BOOK_GRP3.ISBN,:XX_BOOK_GRP3.PAGES,:XX_BOOK_GRP3.PUBLISHING_DATE,
:XX_BOOK_GRP3.BOOK_TYPE,
:XX_BOOK_GRP3.COST,
:XX_BOOK_GRP3.BOOK_NAME);
commit;
end if;
end;
First of all, make sure you have a primary key in your table. Please note: PK eliminates duplication.
I also suggest checking your form for any insert for the same table.
You may be have a database trigger or a database procedure which is called from by name inside any form 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