Does anyone know why this trigger is not working? - sql

create or replace NONEDITIONABLE TRIGGER SetNapomena
BEFORE INSERT
ON stavkafakture
FOR EACH ROW
DECLARE
V_napomena VARCHAR2(20);
BEGIN
EXECUTE IMMEDIATE 'ALTER TRIGGER zabranjeno DISABLE';
SELECT napomena INTO V_napomena
FROM faktura
WHERE brojfakture =:NEW.brojfakture;
:NEW.napomena := V_napomena;
EXECUTE IMMEDIATE 'ALTER TRIGGER zabranjeno ENABLE';
END;
When I insert into a table (in this case stavkafakture) I get this error:
Cannot commit in a trigger
I did some research and added Pragma Autonomous Transaction and commit, but after adding them I try to insert a row in the table it loads forever and never works.
It stays in load forever.
Does anyone know why?

In Oracle DDL statement like CREATE, ALTER, DROP generate an explicit commit.
IE if you issue this kind of statement this does not requires a COMMIT nor a ROLLBACK :
CREATE TABLE MyTable(MyField NUMBER);
This will create the MyTable table and cannot be ROLLBACK.
This is a limitation of Oracle that other RDBMS like PostreSQL doesn't have.

Related

Postgresql catch rollback when function fails on one of multiple inserts but trigger was executed

I've got plpgsql function that does multiple inserts to multiple tables.
I've also trigger that do some stuff f.g notifies some service.
The process looks like this:
Insert into table A
Trigger executed on table A
Function fails on
insert into table B
And then transaction is rollbacked and I've got no data in table A but trigger has executed.
Furthemore there is no any DELETE on table A.
My trigger and function:
CREATE OR REPLACE FUNCTION some_function() RETURNS trigger AS
$$
BEGIN
PERFORM pg_notify('pgchannel1', row_to_json(new)::text);
RETURN NULL;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER some_trigger
AFTER INSERT
ON some_table
FOR EACH ROW
EXECUTE PROCEDURE some_function();
I would like to have this process like that:
Insert into table A
Insert into table B
Trigger executed on table A / Trigger executed when function is done
How could I catch that transaction was rollbacked and not executing trigger?
Is there any way to trigger function status?
Yes, you can do that with constraint triggers:
CREATE CONSTRAINT TRIGGER some_trigger
AFTER INSERT ON some_table
DEFERRABLE INITIALLY DEFERRED FOR EACH ROW
EXECUTE PROCEDURE some_function();
Such a trigger will fire at the end of the transaction rather than immediately.

Should i commit at the end of the procedure which is called by an oracle scheduler job

I am running an oracle JOB which will run a PROCEDURE to CREATE TRUNCATE INSERT DROP some relevant tables.
Is this the best way to do a functionality like this ?
Should I Commit at the end of the procedure or not ?
CREATE OR REPLACE Procedure PR_NAME
IS
BEGIN
CREATE TABLE TABLE_1_BAC AS SELECT * FROM TABLE1_VIA_DBLINK;
TRUNCATE TABLE TABLE_1;
INSERT INTO TABLE_1 SELECT * FROM TABLE_1_BAC;
DROP TABLE TABLE_1_BAC;
--COMMIT;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
To create TABLE_1 only once for present data :
CREATE TABLE TABLE_1 AS SELECT * FROM TABLE1_VIA_DBLINK;
and creating an insert trigger for TABLE1_VIA_DBLINK, populating TABLE_1 through this trigger for new datas, and to get rid of this job and procedure seems more feasible.
As you stay in this job, perhaps you'll wait for huge data to be inserted.
By the way, if you insist on using this job, you don't need to issue commit, since and there's already an implicit commit exists inside job mechanism.
What kind of job do you use? JOB or SCHEDULER JOB?
I don't see any reason to DROP/CREATE the table. I don't see any reason why you use the intermediate table at all.
Simply make
CREATE OR REPLACE Procedure PR_NAME
IS
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE TABLE_1';
INSERT INTO TABLE_1 SELECT * FROM TABLE1_VIA_DBLINK;
COMMIT;
END;
You don't need any exception handler. In case of JOB you will not see the exception anyway. In case of SCHEDULER JOB you can see exception in views
*_SCHEDULER_JOB_LOG
*_SCHEDULER_JOB_RUN_DETAILS
If you make just this kind of operation you should consider MATERIALIZED VIEW which basically make the same: TRUNCATE and INSERT INTO ... SELECT * FROM ...
No. You don't need to commit.
Those commands are DDL (Data Definition Language) in SQL. So Oracle Database will issue a commit together with the command.
DML (Data Manipulating Language) - like SELECT, UPDATE, INSERT, DELETE requires a commit.
In a scenario, where you will update, delete and insert records. Then you ran a create table command. The records inserted, updated and deleted will be committed (save) to the database.

Sql Oracle 12c Trigger

I need some help.
I'm trying to create a Trigger that execute a procedure whenever insert, delete or update operations are done on a specific table.
This is the trigger
CREATE OR REPLACE NONEDITIONABLE TRIGGER NQDI.GAV_TRG
AFTER INSERT or UPDATE or DELETE ON D_GAV
FOR EACH ROW
BEGIN
PRC_FILL_D_GAV(:old.report_name);
END;
Unofortunately, since the trigger starts before any commit has been done and I need to read from the same table, it gives me the 'D_GAV table is being modified can't be read' error.
Besides, the FOR EACH ROW makes the trigger start for every record changed, while I want the trigger to start only at the end, when every update, insert or delete has been committed, but I haven't find a way to preserve the :old.report_name while doing this.
I know I could do what I want with an "up and running process", but I'd like to avoid that. Is there any other solution that I'm overlooking?
You want a compound trigger. After each row event you insert the data into an array. And after the statement you loop through the data and call your procedure.
create or replace trigger nqdi.gav_trg
for insert or update or delete on d_gav compound trigger
type type_table_of_gav is table of d_gav%rowtype;
v_gavs type_table_of_gav := type_table_of_gav();
after each row is
begin
v_gavs.extend(1);
v_gavs(v_gavs.count).report_name := coalesce(:old.report_name, :new.report_name);
end after each row;
after statement is
begin
for i in 1 .. v_gavs.count loop
prc_fill_d_gav(v_gavs(i).report_name);
end loop;
end after statement;
end gav_trg;

When does an insert commit with a trigger on the table?

I have a very simple trigger I wrote for a table at work. The problem is when I use 'AFTER INSERT', the trigger locks the table and nothing else can write to it. When I use 'BEFORE INSERT', the trigger works just fine. Both versions of the trigger compile just fine, but only the 'AFTER INSERT' gives me the error when I use a simple insert statement into the 'EVENT_MESSAGE' table. Below is the trigger and error message:
create or replace TRIGGER TWCC_MHE_RERELEASE
AFTER INSERT
ON EVENT_MESSAGE
FOR EACH ROW
DECLARE
m_count number(3);
BEGIN
select count(*) into m_count from event_message where event_id = 7010 and ek_wave_nbr = :new.ek_wave_nbr;
IF :new.event_id = 7010
THEN
insert into TEST_COUNT
(count, wave_nbr, create_date_time)
values
(m_count,:new.ek_wave_nbr, sysdate);
END IF;
END;
A mutating table occurs when a statement causes a trigger to fire and that trigger references the table that caused the trigger. The best way to avoid such problems is to not use triggers :P
Changed the trigger to an after trigger.
Changed it from a row level trigger to a statement level trigger.
Convert to a Compound Trigger.
Modified the structure of the triggers to use a combination of row and statement level triggers.
Made the trigger autonomous with a commit in it.

Trigger with Autonomous Transaction

I want to know if declaring AUTONOMOUS_TRANSACTION means that the rule action starts after event transaction INSERT on tab has ended (AKA triggering transaction had a successful COMMIT).
I'm using Oracle DB 11.2
Here I have added the trigger:
CREATE OR REPLACE TRIGGER rule1
AFTER INSERT ON tab
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE ('
ALTER TABLE vert_strukt
ADD '||:NEW.name||' VARCHAR2(40) ');
INSERT INTO resulted (name_unique)
VALUES (:NEW.name);
COMMIT;
END;
I recommend you to use a Stored procedure to do so. Also, no transaction control statements are allowed in a trigger. ROLLBACK, COMMIT, and SAVEPOINT cannot be used.