I wanted to ask if this is a DML or DDL Trigger ?
CREATE OR REPLACE TRIGGER INFORMATION_TIMEZONE
BEFORE INSERT ON information
FOR EACH ROW
BEGIN
IF (session_params.getCurrentRefperso) IS NOT NULL THEN
:new.DT_HOUR_TIME_ZONE := current_timestamp();
END IF;
END;
The BEFORE INSERT defines this trigger to be fired when an INSERT is done.
As INSERT is a DML statement, the trigger is a DML trigger.
A DDL trigger would e.g. have BEFORE CREATE or BEFORE DROP in the trigger definition.
Related
Im trying to create a trigger to controle parameters aren't NULL, but when i try to INSERT for example:
INSERT INTO puntuacions(puntuacio, contingut, data) VALUES (6,NULL,CURRENT_DATE);
Console start on a big LOOP trying to make INSERT inside function. Im not sure if i must do INSERT on function or at end of trigger.
BTW on avg select im trying to set an AVG value from a SELECT to insert on table.
I have this code:
FUNCTION:
create or replace function p_controla() returns trigger as $controla_puntuacions$
begin
IF new.puntuacio IS NULL OR new.contingut IS NULL OR new.data IS NULL
THEN
RAISE 'SIUSPLAU OMPLE TOTES LES DADES DE LA TAULA';
ELSE
INSERT INTO puntuacions(puntuacio, contingut, data) VALUES (new.puntuacio,new.contingut,new.data);
UPDATE continguts SET puntuacio = (SELECT AVG(puntuacio) FROM puntuacions WHERE contingut = new.contingut) WHERE idcontingut = new.contingut;
RAISE ' OK! ';
END IF;
END;
$controla_puntuacions$ language plpgsql;
TRIGGER:
create trigger controla_puntuacions
before insert on puntuacions
for each row execute procedure p_controla();
There are four problems with this trigger:
You expect that INSERT INTO puntuacions inserts a record which is handled by a trigger. A trigger does not work this way. INSERT INTO puntuacions in the trigger function instructs the database to insert another row. It will also fire this trigger again and will cause an infinite recursion. The row being inserted is in new. Values in new will be inserted to this table after the trigger returns new.
UPDATE continguts based on data in puntuacions is not appropriate in the before insert trigger, because the row is not inserted yet.
RAISE ' OK! ' raises an exception. So, the insert won't complete correctly even if all values are not null.
The trigger lacks return. When you fix 3, this will lead to a runtime error.
One issue is with the syntax for each row execute procedure. This syntax still works, but it is old-fashioned and now it is deprecated. The keyword FUNCTION should be used here instead of PROCEDURE.
For updating continguts you can create an after insert trigger.
If you want to insert a row after the trigger completes, it has to return new.
If you want just to display a message "OK", you can use RAISE NOTICE.
Potential solution:
The function for a before insert trigger:
create or replace function p_controla() returns trigger as $controla_puntuacions$
begin
IF new.puntuacio IS NULL OR new.contingut IS NULL OR new.data IS NULL
THEN
RAISE 'SIUSPLAU OMPLE TOTES LES DADES DE LA TAULA';
ELSE
RAISE NOTICE ' OK! ';
END IF;
RETURN new;
END;
$controla_puntuacions$ language plpgsql;
After insert trigger function:
create or replace function puntuacions_after_ins() returns trigger as $puntuacions_after_ins$
begin
UPDATE continguts SET puntuacio = (SELECT AVG(puntuacio) FROM puntuacions WHERE contingut = new.contingut) WHERE idcontingut = new.contingut;
RETURN new;
END;
$puntuacions_after_ins$ language plpgsql;
After insert trigger:
create trigger puntuacions_after_ins
after insert on puntuacions
for each row execute function puntuacions_after_ins();
The return value in the after insert function is ignored, but anyway this function has to return something.
I have mostly the same code for a trigger that occurs before a INSERT or UPDATE,
and instead of creating 2 triggers, is there any way to know the type of event occurring dynamically inside the trigger ?
Example:
CREATE OR REPLACE FUNCTION UpsertClientLog() RETURNS TRIGGER AS $$
DECLARE action_type VARCHAR(255);
BEGIN
IF (event == 'INSERT') THEN
action_type = 'Create'
ELSE
action_type = 'Update'
END IF;
-- Same code from here on out ..
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER UPSERT_CLIENT_LOG BEFORE INSERT OR UPDATE ON client
FOR EACH ROW EXECUTE PROCEDURE UpsertClientLog();
You can use special variable TO_OP:
TG_OP
Data type text; a string of INSERT, UPDATE, DELETE, or TRUNCATE telling for which operation the trigger was fired.
CREATE TABLE table_001(
Day_date date
);
CREATE TABLE table_002(
new_Day_date date
);
CREATE OR REPLACE TRIGGERS trigger
AFTER INSERT ON table_001
FOR EACH ROW
BEGIN
INSERT INTO table_002 VALUES(SYSDATE)
END;
You have a few syntax errors. It's not "TRIGGERS". Also, give a valid trigger name. A semicolon was missing after the insert.
CREATE OR REPLACE TRIGGER trigger_name
AFTER INSERT ON table_001
FOR EACH ROW
BEGIN
INSERT INTO table_002(new_Day_date) VALUES(SYSDATE);
END;
/
CREATE OR REPLACE TRIGGER trigger_name
AFTER INSERT ON table_001
FOR EACH ROW
BEGIN
INSERT INTO table_002 VALUES(SYSDATE);
END;
I'm trying to execute the following SQL statement on Oracle 11g. I'm not experienced when it comes to Oracle and I'm not sure why this is failing. This query was provided to me by our developer.
I was attempting to execute this through the SQL worksheet in OEM.
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG BEFORE
INSERT OR UPDATE ON tbl_AdminCommands FOR EACH ROW
BEGIN
IF inserting
AND :new.ADMINCOMMANDID IS NULL THEN
SELECT TBL_ADMINCOMMANDS_SEQ.nextval INTO :new.ADMINCOMMANDID FROM DUAL;
END IF;
END;
ALTER TRIGGER TBL_ADMINCOMMAND_TRG ENABLE;
The code you show works for me, but only as two separate commands:
1)
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG BEFORE
INSERT OR UPDATE ON tbl_AdminCommands FOR EACH ROW
BEGIN
IF inserting
AND :new.ADMINCOMMANDID IS NULL THEN
SELECT TBL_ADMINCOMMANDS_SEQ.nextval INTO :new.ADMINCOMMANDID FROM DUAL;
END IF;
END;
2)
ALTER TRIGGER TBL_ADMINCOMMAND_TRG ENABLE;
Try doing them one at a time.
As an aside, this line:
SELECT TBL_ADMINCOMMANDS_SEQ.nextval INTO :new.ADMINCOMMANDID FROM DUAL;
can be simplified to this in 11G:
:new.ADMINCOMMANDID := TBL_ADMINCOMMANDS_SEQ.nextval;
In fact, the whole trigger can be simplified to:
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG
BEFORE INSERT ON tbl_AdminCommands
FOR EACH ROW
WHEN (NEW.ADMINCOMMANDID IS NULL)
BEGIN
:new.ADMINCOMMANDID := TBL_ADMINCOMMANDS_SEQ.nextval;
END;
If you are using SQL*Plus, you should end your PL/SQL commands with a single forward slash on a line by itself:
CREATE OR REPLACE TRIGGER TBL_ADMINCOMMAND_TRG
BEFORE INSERT OR UPDATE ON tbl_AdminCommands
FOR EACH ROW
BEGIN
IF inserting AND :new.ADMINCOMMANDID IS NULL
THEN
SELECT TBL_ADMINCOMMANDS_SEQ.nextval
INTO :new.ADMINCOMMANDID
FROM DUAL;
END IF;
END;
/
ALTER TRIGGER TBL_ADMINCOMMAND_TRG ENABLE;
Also note that if your trigger uses IF inserting you could do only a trigger BEFORE INSERT.
I created a trigger as below:
CREATE OR REPLACE TRIGGER trigger_test
AFTER INSERT ON trigger_1
FOR EACH ROW
DECLARE
t_identifier VARCHAR2(10);
t_name VARCHAR2(20);
BEGIN
t_identifier := (:NEW.IDENTIFIER);
t_name := (:NEW.NAME);
INSERT INTO trigger_2(IDENTIFIER,NAME)VALUES(t_identifier,t_name);
COMMIT;
END;
I am trying to insert a row in trigger_1
INSERT INTO trigger_1(IDENTIFIER,NAME)
VALUES('1234567','Vijay');
It is giving me the errors:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "LVSDBO46.TRIGGER_TEST", line 8
ORA-04088: error during execution of trigger 'LVSDBO46.TRIGGER_TEST'
Could nybody please help?
Just remove
COMMIT;
from the trigger code. Trigger execute in an ongoing transaction, so you cannot do a separate commit. When the transaction is commited, your insert in trigger_2 will also be commited.
Might I suggest shortening it a bit.
CREATE OR REPLACE TRIGGER trigger_test
AFTER INSERT ON trigger_1
FOR EACH ROW
BEGIN
INSERT INTO trigger_2 (IDENTIFIER,NAME) VALUES (:NEW.IDENTIFIER,:NEW.NAME);
END;
In case you really really need to commit (chances are you don't have to, but just in case...) you can create a procedure with the AUTONOMOUS_TRANSACTION PRAGMA.