Compound Trigger is Triggering Only Once - sql

I have an ORDS enabled schema which accepts bulk JSON records and splits them one by one, and inserts them one by one into UEM table.
I've tried to create a trigger which fetches the last inserted row's id and use that value to insert into another table. The problem is, the trigger below only fetches and inserts the last inserted row's id, and it only does 1 insert.
To be more specific:
ORDS gets a bulk JSON payload which consists of 4 records.
POST handler starts a Procedure which splits these 4 records by line break, and immediately inserts these to CLOB columns of UEM table as 4 separate rows by using "connect by level". There is also the ID column which is automatically created and incremented.
In the parallel I also would like to get the ID of these rows and use it in another table insert. I've created the compound trigger below, but this trigger only retrieves the ID of the last record, and inserts only one row.
Why do you think it behaves like this? In the end, the procedure "inserted" 4 records.
CREATE OR REPLACE TRIGGER TEST_TRIGGER5
FOR INSERT ON UEM
COMPOUND TRIGGER
lastid NUMBER;
AFTER STATEMENT IS
BEGIN
SELECT MAX(ID) INTO lastid FROM UEM;
INSERT INTO SPRINT1 (tenantid, usersessionid, newuser, totalerrorcount, userid) VALUES ('deneme', 'testsessionid', 'yes', lastid, 'asdasfqwqwe');
END AFTER STATEMENT;
END TEST_TRIGGER5;

inserts these to CLOB columns of UEM table as 4 separate rows by using "connect by level".
You have 1 INSERT statement that is inserting 4 rows.
In the parallel I also would like to get the ID of these rows and use it in another table insert. I've created the compound trigger below, but this trigger only retrieves the ID of the last record, and inserts only one row.
Why do you think it behaves like this? In the end, the procedure "inserted" 4 records.
It may have inserted 4 ROWS but there was only 1 STATEMENT and you are using an AFTER STATEMENT trigger. If you want it to run for each row then you need to use a row-level trigger.
CREATE OR REPLACE TRIGGER TEST_TRIGGER5
AFTER INSERT ON UEM
FOR EACH ROW
BEGIN
INSERT INTO SPRINT1 (tenantid, usersessionid, newuser, totalerrorcount, userid)
VALUES ('deneme', 'testsessionid', 'yes', :NEW.id, 'asdasfqwqwe');
END TEST_TRIGGER5;
/
db<>fiddle here

Why? Because it is a statement level trigger. If you wanted it to fire for each row, you'd - obviously - use a row level trigger which has the
for each row
clause.

Related

Trigger: How does the inserted table work? How to access its rows?

I have the following table
Data --Table name
ID -- Identity column
PCode -- Postal Code
I created the following trigger:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * from inserted
END
And inserted the following values
INSERT INTO Data VALUES (125)
INSERT INTO Data VALUES (126)
INSERT INTO Data VALUES (127)
It shows this:
But I was expecting something like this:
After the 1st insertion, the trigger is executed -> one row is shown in the inserted table.
After the 2nd insertion, the trigger is executed -> two rows are shown in the inserted table.
After the 3rd insertion, the trigger is executed -> three rows are shown in the inserted table.
According to msdn.microsoft all the rows inserted are in this table.
How can I access the inserted table so that I can see all the expected rows and not separately?
You can not. From the Use the inserted and deleted Tables article on microsoft.com, you can read:
The inserted table stores copies of the affected rows during INSERT and UPDATE statements.
That means that the inserted table will only contain rows for the current INSERT or UPDATE statement.
If you do want to see all rows for several such INSERT or UPDATE statements, you will have to store these rows in a table you created yourself.
There are 2 table available in a trigger, the inserted and the deleted. Each update on table XXX is actually a delete row X from XXX then an insert of row X in table XXX. So the inserted inside the trigger is a copy of what got inserted. You can do a lot with a trigger, but triggers are dangerous.
For example, on a performance gig, I found a huge SP being run by a trigger, we dropped it and the database came back online. Or another example, if you do a trigger wrong to audit logins, you can down the server.
As TT mentioned, if you want to see all the inserted records then you need to change your Trigger to something like this:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * into "tablename"
from
(Select * from inserted) Ins
END

SQL Server triggers on certain column and value

I want to write a trigger when there is certain value inserted in certain column instead of whole table, for example I want my trigger to act when the value NewName is inserted in the column Names on students table.
CREATE TRIGGER newtrg
ON students
AFTER INSERT
AS BEGIN
PRINT 'Trigger fired!'
END
You have to understand how triggers work in SQL Server - they fire on a per statement level - not per row - so you cannot just check to see if the row being inserted contains NewName in the Names column - an INSERT statement could insert dozens of rows at once, and your trigger will only fire once for the whole statement.
Therefore, you cannot prevent a single row from being inserted - if your INSERT statement inserted 57 rows, and one of them contains NewName in the Names column, you can either just change that value on that particular row, or you can rollback the transaction and stop the whole INSERT process - NONE of the 57 rows will be inserted.
So what do you really want to do, in the end? If your INSERT of n rows contains a single row with a value of NewNames in the Names column - do you want to stop the whole INSERT process and rollback the transaction? In that case - use something like this:
CREATE TRIGGER newtrg
ON students
AFTER INSERT
AS
IF EXISTS (SELECT * FROM Inserted WHERE Names = 'NewName')
-- any of of the rows being inserted contains `NewName`
-- in this case, ABORT the whole INSERT
ROLLBACK TRANSACTION
Or if you want to update those rows after they've been inserted to get a new value (instead of NewNames) - try something like this:
CREATE TRIGGER newtrg
ON students
AFTER INSERT
AS
UPDATE s
SET Names = 'SomeOtherValue'
FROM dbo.Students s
INNER JOIN Inserted i ON s.StudentID = i.StudentID -- use the primary key here
WHERE i.Names = 'NewName'

Trigger - After insert and delete example

I have a requirement as a trigger should get fired when any row is inserted or deleted from table FAB which contains num as unique value. and depending upon that num value, another table should be update.
e.g.
FAB table
num code trs
10 A2393 80
20 B3445 780
Reel table
reelnr num use flag
340345 10 500 1
when num 10 from FAB table gets deleted(or any new num gets inserted), the trigger should get fired and should check the reel table which contains that num value and give the reelnr.
How to proceed with this?
you can Use Inserted & Deleted Table in SQL
These two tables are special kind of table that are only available inside the scope of the triggers.
If you tries to use these tables outside the scope of Triggers then you will get Error.
Inserted : These table is use to get track of any new records that are insert in the table.
Suppose there are Six rows are inserted in your table then these table will consist of all the six rows that are inserted.
Deleted : These table is used to track all the Deleted record from your tables.
Last delete rows will be tracked by these table.
For Insert :
CREATE TRIGGER TR_AUDIT_Insert
ON Reel_table
FOR INSERT
AS
BEGIN
INSERT INTO Reel_table (reelnr, num, use, flag)
SELECT
reelnr,
num,
use,
flag
FROM
INSERTED
END
For Delete :
CREATE TRIGGER TR_AUDIT_Delete
ON Product
FOR DELETED
AS
BEGIN
INSERT INTO Reel_table (reelnr, num, use, flag)
SELECT
reelnr,
num,
use,
flag
FROM
DELETED
END
Note :
I don't know from where these three reelnr, use flag values you are getting
So, Please modify this as per your need.
This is the format of the Triggers that normally we use.
You also can do this by using single trigger also
I dont know what is your exact requirement
If you want to achieve by only single Trigger then you can refer this link :
Refer

Restricting max no of rows insert in SQLite

I want to create a table which should contain max of 5 rows, when ever there is a 6th insert operation the last row must be deleted.
I want max of 5 rows and I want to do this in SQLIte database in android.
please suggest me a query which is simple.
You could do a row count in your application. If it returns more than four, or eaqual to five, rows you delete the last row before inserting a new one.
UPDATE:
I did a bit of testing on a table which i named test_table, and added this trigger:
DELIMITER $$
CREATE TRIGGER `schema_name`.`trigger_name` BEFORE INSERT ON `database_name`.`test_table`
FOR EACH ROW
if (select count(*) from test_table)> 4 /* count records to see if it exeeds your limit */
then
delete from test_table where id=(SELECT MAX(id) FROM test_table LIMIT 1); /* delete last row */
END if;
END
When I try to insert a sixth row I'm getting this error:
ERROR 1442: 1442: Can't update table 'test_table' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
I looked it up and found this answer: https://stackoverflow.com/a/21117071/1355562 - which lead me to http://dev.mysql.com/doc/refman/5.6/en/stored-program-restrictions.html.
The section "Restrictions for Stored Functions", point 5, says "... cannot modify a table that is already being used..."
Looks like you have to do this in you application bro ;)
ops.. just noticed you're working an MySQLlite.. Maybe it's different. This was for MySQL... Sorry about that...

sql server trigger referencing last row

I want to write a trigger in SQL Server to insert 2 rows into table2 when a row is inserted into table1. I want to use a column value from table1.
So my trigger looks like this
create trigger triggername on table1
as
begin
insert into
insert into
end
How do I get the value of any column from the last inserted row (the row insertion which fires the trigger). I.e. the equivalent of 'referencing row' in oracle
Triggers in SQL Server fire per statement not per row. There are two pseudo tables inserted and deleted that you can use (for an insert trigger the only one of interest is inserted)
CREATE TRIGGER YourTrigger ON Table1
FOR INSERT
AS
INSERT INTO Table2
SELECT * from inserted /*This will contain multiple rows if it is a multi-row insert*/
hi
i have the solution myself. i missed the alias
select #patient_no=fldL1BasCode from inserted
should be
select #patient_no=i.fldL1BasCode from inserted i