Get a reference to insert rows with triggers - sql

I'm trying to get a reference to a set of rows that I'm trying to insert into a table through a multiple insert. For example if I execute:
INSERT INTO T VALUES (0,'A'),(1,'B'),(2,'C')
I would like to get a reference in a before insert trigger to a "table" that contains these 3 rows. Is that possible?
And another question: what does a REFERENCING NEW_TABLE represents in a before trigger (maybe could this be the answer to the first question)?
Thanks

According to documentation:
REFERENCING NEW TABLE AS identifier
Specifies a temporary table name which identifies the affected rows as modified by the triggering SQL operation and by any SET
statement in a BEFORE trigger that has already executed.
Also take a look:
FOR EACH STATEMENT
Specifies that the triggered action is to be applied only once for the whole statement. This type of trigger granularity cannot be
specified for a BEFORE trigger or an INSTEAD OF trigger (SQLSTATE
42613). If specified, an UPDATE or DELETE trigger is activated, even
if no rows are affected by the triggering UPDATE or DELETE statement.
maybe it will suite better your needs (of course you need to go with AFTER trigger)

Related

How does returned trigger from function affects BEFORE or AFTER statement?

I'm having a little trouble with understanding functions and triggers in sql. I didn't post the code of procedure chkInsertAritcle but let's say it returns NEW if it managed to make change and NULL if it didn't.
So my question is about the trigger. If I put AFTER INSERT does that means that it will complete INSERT without depending on the return value? And what
happens with the rest of the rows?
Next question is if I put BEFORE INSERT, in what order does code runs?
Thanks!
CREATE TRIGGER ArticleIns
AFTER INSERT ON ListOfArticles
FOR EACH ROW
EXECUTE PROCEDURE chkInsertArticle();
First all BEFORE triggers run in alphabetical order, then the operation is performed, then all AFTER triggers run in alphabetical order.
Each operation sees the result of the previous one as input, and if any trigger returns NULL, processing for that row stops. So if a BEFORE trigger returns NULL, the DML operation won't take place.
This happens independently for each row affected by the triggering DML statement.
So if the trigger runs before insert, then the code runs before the data is inserted into the row and constraints are checked. So for example you might want to add a timestamp before the data is committed to the database,
If it runs after then the data is already present in the table and all constraints have been checked. This is usually where you want to trigger another process based on the row data, maybe update another table, send an e-mail etc.
In your example, the data will be in the database before your procedure runs. So if your procedure modifies the row data, it needs to be in the database.

After insert auto increment trigger

The problem here is that, we use an application called ArcGIS that creates an upper management layer for our database, and when our users use ArcGIS to create a new object in the database, it adds a default value (0) to the primary key, so when the second object is created it triggers an ORA error for having duplicate values.
So my idea was to create an auto increment trigger for our PK but use AFTER INSERT instead.
I couldn't find any example online for this specific case and simply switching BEFORE to AFTER gives an error saying that you can't use NEW with AFTER
SQL code of what I tried (taken from other questions):
CREATE OR REPLACE TRIGGER "IMOVEL_TRIGGER"
after insert on IMOVEL
for each row
begin
select IMOVEL_SEQ.nextval into :NEW.GEOCODIGO_IMOVEL from dual;
end;
It cant be a BEFORE INSERT trigger, because the application overwrites it
Simplifying, what I need is a AFTER INSERT trigger, that updates the PK to the sequence .nextval, it doesn't let me use :OLD or :NEW, so I'm not sure what must be done.
Or an update trigger that only runs after it is created
This is pretty new territory for me, having to learn SQL now just to solve this issue
You can change :NEW values only in a BEFORE trigger. By the time you reach the AFTER trigger, the row has already been inserted, so it's too late to change the columns.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7004.htm says:
Restrictions on BEFORE Triggers
BEFORE triggers are subject to the following restrictions:
You cannot specify a BEFORE trigger on a view or an object view.
You can write to the :NEW value but not to the :OLD value.
Restrictions on AFTER Triggers
AFTER triggers are subject to the following restrictions:
You cannot specify an AFTER trigger on a view or an object view.
You cannot write either the :OLD or the :NEW value.
It's not clear why you want to use an AFTER trigger for assigning sequence values to the PK. The common solution is to use a BEFORE trigger.
See example in: How to create id with AUTO_INCREMENT on Oracle?
CREATE SEQUENCE IMOVEL_TRIGGER_SEQ START WITH 1;
Trigger definition:
CREATE OR REPLACE TRIGGER IMOVEL_TRIGGER
BEFORE INSERT ON IMOVEL
FOR EACH ROW
BEGIN
SELECT IMOVEL_TRIGGER_SEQ.NEXTVAL
INTO :new.GEOCODIGO_IMOVEL
FROM dual;
END;

Is it possible to update trigger table in update trigger?

I have an update trigger for a table. When I am updating the table rows I need to check certain condition in trigger then based on that I want to update another column.
Is it possible?
You might want to read the documentation for CREATE TRIGGER, especially the remarks section, which includes:
If an INSTEAD OF trigger defined on a table executes a statement against the table that would ordinarily fire the INSTEAD OF trigger again, the trigger is not called recursively. Instead, the statement is processed as if the table had no INSTEAD OF trigger and starts the chain of constraint operations and AFTER trigger executions.
If this, or other parts of the remarks section, don't answer your questions, you probably need to add more to your question about what problems you're having, or what issues you're concerned about.

SQL Trigger - help with fundamentals

I rarely write triggers. I can use help setting up the thing.
CREATE TRIGGER audit_tableName
ON dbo.tableNameAudit
AFTER CREATE, UPDATE, DELETE on tableName
AS
BEGIN
--Get Created,updated,deletes items
INSERT into dbo.tableNameAudit(columns) VALUES ([allCUDitems])
END
GO
How do I get an iterate any CREATED, UPDATED, DELETED items that caused the trigger?
check out this msdn article.
the short of it are there are 2 special tables, inserted and deleted, that are accessible in your trigger. inserted will contain updated rows and inserted rows, while deleted will contain updated rows and deleted rows.
make sure that you understand that for a batch operation a trigger is only fired one time, so be sure to handle the possibility of multiple rows being present in those tables.
Triggers have access to two pseudo tables: INSERTED and DELETED. As their name suggests, these pseudo tables will contain all the values added or removed from the table. An update will cause a row in each of the pseudo-tables. The structure of these pseudo-tables is identical with the structure of the table on which the table is declared.
In addition the UPDATE() function inside a trigger will return TRUE for columns that were updated.
You can use INSERTED.[COLUMN] OR
SELECT [COLUMN]
FROM INSERTED
This on SQL Server.
Hope it helps.

Multiple rows update trigger

If I have a statement
that updates multiple rows, only the trigger will fire only on the first or last row that is being updated (not sure which one). I need to make a trigger that fires for ALL the records that are being updated into a particular table
Assuming SQL Server, A trigger only fires once per update, regardless of the number of rows that are updated. If you need to carry out some additional logic based on updates to multiple rows you can access the changed records by looking at the INSERTED and DELETED logical tables that are accessible in the context of a trigger.
You have not specified the database .....
In Oracle a trigger can be defined to fire for individual rows and based on the type of transaction:
CREATE OR REPLACE TRIGGER BIUDR_MY_TABLE
BEFORE INSERT OR UPDATE OR DELETE
ON MY_TABLE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
pk PLS_INTEGER;
BEGIN
etc ....
You just need to indicate if your trigger needs to be executed "FOR EACH ROW" or "FOR EACH STATEMENT". Adding one of these two clauses in the trigger definition will tell the DBMS when to execute the trigger (most, but not all, DBMSs support it). If you don't indicate this clause then the DBMS uses the default option which in your case seems to be the FOR EACH STATEMENT option, and that's why your trigger only fires one for each update sentence, regardless of how many rows you are updating