CREATE TABLE "EMPLOYEE_BP"
( "EMP_ID" VARCHAR2(10) NOT NULL ENABLE,
"FNAME" VARCHAR2(20),
"LNAME" VARCHAR2(20),
"JOB_ROLE" VARCHAR2(20),
"AIRPORT_CODE" VARCHAR2(10) NOT NULL ENABLE,
"SALARY" NUMBER(9,0),
"MOBILE" NUMBER(10,0)
);
CREATE or REPLACE TRIGGER emp_after_insert AFTER INSERT ON EMPLOYEE
FOR EACH ROW
DECLARE
BEGIN
INSERT INTO EMPLOYEE_BP values (:NEW.EMP_ID, :NEW.FNAME, :NEW.LNAME, :NEW.JOB_ROLE, : NEW.AIRPORT_CODE, : NEW.SALARY, : NEW.MOBILE);
DBMS_OUTPUT.PUT_LINE('Record successfully inserted into emp_backup table');
END;
--> Apparently constraints are not inserted into backup tables
The table gets created, but it gives me an error for the trigger on line 4,where the begin statement is. Ther error is error at line 4 statement ignored. The synthax seems ok and I'm confident it's a small error but I can't figure it out. I am using Oracle.
Thanks in advance.
Running the trigger as you have it, I actually get an internal Oracle error, which is not good. But I think the problem is with the spaces you have between the : and the NEW.
This works for me:
SQL> CREATE or REPLACE TRIGGER emp_after_insert AFTER INSERT ON EMPLOYEE
2 FOR EACH ROW
3 DECLARE
4 BEGIN
5 INSERT INTO EMPLOYEE_BP values (:NEW.EMP_ID, :NEW.FNAME, :NEW.LNAME, :NEW.JOB_ROLE, :NEW.AIRPORT_CODE, :NEW.SALARY, :NEW.MOBILE);
6 DBMS_OUTPUT.PUT_LINE('Record successfully inserted into emp_backup table');
7 END;
8 /
Trigger created.
I'm not an Oracle expert but you would either need to strike your DECLARE line or actually declare something based on this example
CREATE or REPLACE TRIGGER emp_after_insert AFTER INSERT ON EMPLOYEE
FOR EACH ROW
DECLARE
unused varchar2(10);
BEGIN
INSERT INTO EMPLOYEE_BP values (:NEW.EMP_ID, :NEW.FNAME, :NEW.LNAME, :NEW.JOB_ROLE, :NEW.AIRPORT_CODE, :NEW.SALARY, :NEW.MOBILE);
DBMS_OUTPUT.PUT_LINE('Record successfully inserted into emp_backup table');
END;
Related
I need to create a Trigger to monitor this table :
CREATE TABLE "REFERENCE"
( "NUM_CONTRACT" VARCHAR2(20 CHAR),
"NATURE" VARCHAR2(20 CHAR),
"PR" VARCHAR2(14 CHAR),
)
I just want to store the date of the last modification and his "PR" in this table :
CREATE TABLE EVENT_REFERENCE (
ID NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL,
reference VARCHAR(14) NOT NULL UNIQUE,
date_modification TIMESTAMP(6),
PRIMARY KEY (ID)
)
I use a merge in order to avoid to have duplicate rows with the same reference and different date . I just want to keep the date of last modification for each reference rows
For that i created this trigger but idk what's wrong with it . Can anyone help me ?
CREATE OR REPLACE TRIGGER TRG_REFERENCE
AFTER INSERT OR UPDATE ON REFERENCE
FOR EACH ROW
DECLARE
PRAGMA autonomous_transaction;
BEGIN
IF INSERTING
THEN
MERGE INTO EVENT_REFERENCE hist
USING (select :new.pr
from dual) t1
ON (t1.pr=hist.reference)
WHEN MATCHED THEN
UPDATE SET hist.date_modification=systimestamp
WHEN NOT MATCHED THEN
INSERT INTO EVENT_REFERENCE (REFERENCE, DATE_MODIFICATION)
VALUES (:NEW.prm, systimestamp);
END IF;
COMMIT;
END;
You have:
:NEW.prm when it should be :NEW.pr
INSERT INTO EVENT_REFERENCE (REFERENCE, DATE_MODIFICATION) when you just need INSERT (REFERENCE, DATE_MODIFICATION)
You also use AFTER INSERT OR UPDATE and then check IF INSERTING why not just use AFTER INSERT?
The fixed code:
CREATE OR REPLACE TRIGGER TRG_REFERENCE
AFTER INSERT OR UPDATE ON REFERENCE
FOR EACH ROW
DECLARE
PRAGMA autonomous_transaction;
BEGIN
IF INSERTING
THEN
MERGE INTO EVENT_REFERENCE hist
USING DUAL t1
ON (:new.pr=hist.reference)
WHEN MATCHED THEN
UPDATE SET hist.date_modification=systimestamp
WHEN NOT MATCHED THEN
INSERT (REFERENCE, DATE_MODIFICATION)
VALUES (:NEW.pr, systimestamp);
END IF;
COMMIT;
END;
/
db<>fiddle here
I got a table Location
CREATE TABLE Location (
idL INTEGER,
City VARCHAR2(15) NOT NULL,
Street VARCHAR2(35) NOT NULL,
Nation CHAR(6) NOT NULL,
CONSTRAINT PK_idL PRIMARY KEY(idL)
);
And a table Person
CREATE TABLE Person(
p_Name VARCHAR2(20) NOT NULL,
p_Surname VARCHAR2(20) NOT NULL,
idP INTEGER,
b_Date DATE NOT NULL,
id_PL INTEGER,
CONSTRAINT PK_idP PRIMARY KEY(idP),
CONSTRAINT FK_idPL FOREIGN KEY(id_PL) REFERENCES Location(idL)
);
I calculate the primary key "automatically" as it follows:
CREATE SEQUENCE seq_loc_pk
start with 1
increment by 1;
CREATE OR REPLACE TRIGGER auto_pk_loc
BEFORE INSERT ON Location
FOR EACH ROW
BEGIN
:new.idL := seq_loc_pk.nextval;
END;
/
Now I want to insert the residence for a new person (after I've created the right view of course) with an instead of trigger like this:
CREATE OR REPLACE TRIGGER newperson
INSTEAD OF INSERT ON Residence
FOR EACH ROW
DECLARE
nl Loc.idL%TYPE;
BEGIN
ALTER TRIGGER auto_pk_loc DISABLE; -- Error
nl := seq_loc_pk.nextval;
:NEW.idL := nl;
INSERT INTO Location VALUES(:NEW.City,:NEW.Street,:NEW.Nation);
INSERT INTO Patient VALUES(:NEW.P_Name,:NEW.P_Surname,:NEW.B_Date,,nl);
ALTER TRIGGER auto_pk_loc ENABLE;
END;
/
I thought about disabling and enabling the trigger auto_pk_loc so that it doesn't create extra values for no reason, but I think this is not the right way to do it? What is it though? Thanks for whoever answers.
You can do this by placing it in execute immedaite:
BEGIN
execute immedidate 'ALTER TRIGGER auto_pk_loc DISABLE';
nl := seq_loc_pk.nextval;
:NEW.idL := nl;
INSERT INTO Location VALUES(:NEW.City,:NEW.Street,:NEW.Nation);
INSERT INTO Patient VALUES(:NEW.P_Name,:NEW.P_Surname,:NEW.B_Date,,nl);
execute immedidate 'ALTER TRIGGER auto_pk_loc ENABLE';
END;
/
But this will cause you all sorts of issues; DDL commits so you'll have to make this an autonomous transaction and you'll hit concurrency problems. This is best avoided.
A better method is to use the returning clause to fetch the value you just inserted:
BEGIN
INSERT INTO Location VALUES(:NEW.City,:NEW.Street,:NEW.Nation)
returning idl into nl;
INSERT INTO Patient VALUES(:NEW.P_Name,:NEW.P_Surname,:NEW.B_Date,nl);
END;
/
Though as #astentx noted, you probably want to use merge to avoid having duplicate locations. This doesn't support returing, so you'll have to use some combination of insert+update instead.
Finally - assuming you're on 12c or higher - it's better to use an identity column or sequence default to auto-generate the location IDs over a trigger.
create or replace TRIGGER dept_id_trig
BEFORE INSERT ON DEPARTMENTS
FOR EACH ROW
DECLARE
BEGIN
IF(:NEW.DEPARTMENT_ID IS NULL )
THEN
select DEPT_DEPTID_SEQ.nextval INTO :new.DEPARTMENT_ID FROM dual;
END IF;
END;
Please check below trigger.
CREATE OR REPLACE TRIGGER dept_id_trig
BEFORE INSERT ON DEPARTMENTS
FOR EACH ROW
DECLARE
BEGIN
:new.DEPARTMENT_ID := DEPT_DEPTID_SEQ.nextval;
END;
If you are on Oracle 12c or later, use an IDENTITY clause on the column rather than a trigger:
CREATE TABLE departments(
department_id NUMBER(10,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINTS departments__department_id__pk PRIMARY KEY
)
This is a trigger generated from Oracle itself when creating a new table:
create or replace TRIGGER dept_id_trig
BEFORE INSERT ON DEPARTMENTS
FOR EACH ROW
BEGIN
<<COLUMN_SEQUENCES>>
BEGIN
IF INSERTING AND :NEW.DEPARTMENT_ID IS NULL THEN
SELECT DEPT_DEPTID_SEQ.NEXTVAL INTO :NEW.DEPARTMENT_ID FROM SYS.DUAL;
END IF;
END COLUMN_SEQUENCES;
END;
I have a code that uses a trigger to do an update into a table after a dml insert has been done, but i need the information inside an atributte that is a nested table, and with that information do the update, but my code throws a mutating table error, and i want to know what is it that i am doing wrong, this is the code with the tables, types and trigger involved.
----create the type tipo_detalle---------------
CREATE OR REPLACE TYPE tipo_detalle AS OBJECT(
codigo NUMBER(1),
cantidad NUMBER(2)
);
/
-----declare the nested table with type tipo_detalle---
CREATE OR REPLACE TYPE detalle_anidado AS TABLE OF tipo_detalle;
/
---------create the table pedido------------------------
CREATE TABLE pedido(
cod_bodega REFERENCES bodega,
dia NUMBER(8),
columna_detalle detalle_anidado,
PRIMARY KEY(cod_bodega,dia)
)
NESTED TABLE columna_detalle STORE AS columna_detalle_anidada
((PRIMARY KEY(NESTED_TABLE_ID,codigo)));
---table where i am going to insert after insert in pedido----
CREATE TABLE inventario(
cod_bodega REFERENCES bodega,
cod_producto REFERENCES producto,
existencia NUMBER(8),
PRIMARY KEY(cod_bodega,cod_producto)
);
------ trigger to do an insert into inventario-----------
CREATE OR REPLACE TRIGGER triggers_de_pedido
FOR INSERT OR UPDATE OR DELETE ON pedido
COMPOUND TRIGGER
contador NUMBER(8);
fila pedido.columna_detalle%TYPE;
cod_producto_ NUMBER(1);
cantidad_ NUMBER(2);
indice NUMBER(4);
AFTER EACH ROW IS
BEGIN
IF INSERTING THEN
SELECT columna_detalle INTO fila FROM pedido WHERE
cod_bodega=:NEW.cod_bodega AND dia=:NEW.dia;
indice:=fila.FIRST;
WHILE indice IS NOT NULL LOOP
cod_producto_:=fila(indice).codigo;
cantidad_:=fila(indice).cantidad;
UPDATE inventario SET existencia=existencia-cantidad_
WHERE cod_bodega=:NEW.cod_bodega AND cod_producto=cod_producto_;
indice:=fila.NEXT(indice);
END LOOP;
END IF;
END AFTER EACH ROW;
END triggers_de_pedido;
/
The error is raised because you are selecting from the Trigger owner(the table pedido) inside the Trigger.
Change this select statement
SELECT columna_detalle INTO fila FROM pedido WHERE ...
to
IF INSERTING THEN
fila := :NEW.columna_detalle;
This question is not a duplicate from this one because even if the error messages are equal the answers there do not apply to my case.
I need to change a previous PK Id column defined as VARCHAR(36) NOT NULL to an incremental integer value. I'm trying to write a script to do this but when I run the alter table statement it fails with the error on the title.
The table is previously defined as:
CREATE TABLE journal_messages(
ID VARCHAR(36) NOT NULL, -- column to be changed
MESSAGE VARCHAR(2048) NOT NULL,
MESSAGE_TYPE VARCHAR(30) NOT NULL,
MSG_DATE TIMESTAMP NOT NULL,
MODULE_CODE INTEGER NOT NULL
);
ALTER TABLE journal_messages ADD (CONSTRAINT journal_messages_pk PRIMARY KEY (ID));
The script I'm running is:
DELETE FROM JOURNAL_MESSAGES;
ALTER TABLE JOURNAL_MESSAGES DROP COLUMN ID;
CREATE SEQUENCE journal_messages_seq START WITH 1;
ALTER TABLE JOURNAL_MESSAGES ADD (ID NUMBER(10) DEFAULT journal_messages_seq.nextval NOT NULL); -- error happens here
ALTER TABLE journal_messages ADD (
CONSTRAINT journal_messages_pk PRIMARY KEY (ID));
When I try to create a trigger it to update the incremental, it fails with SQL Error [4098] [42000]: ORA-04098: trigger 'TRG_SEQ_JOURNAL_MSG' is invalid and failed re-validation when I try to insert a new tuple:
ALTER TABLE JOURNAL_MESSAGES DROP COLUMN ID;
ALTER TABLE JOURNAL_MESSAGES ADD (ID NUMBER(10) NOT NULL);
create or replace trigger trg_seq_journal_msg
before insert on journal_messages
for each row
begin
:new.id := journal_messages_seq.nextval;
end;
/
INSERT INTO JOURNAL_MESSAGES (message, MESSAGE_TYPE, msg_date, MODULE_CODE) VALUES ('test', 'alteration', CURRENT_TIMESTAMP, '10');
Umm ... not like that, but like this:
once the table is empty, you don't have to drop the column - just modify its datatype
use a trigger to automatically set IDs value
If you were on 12c, you could have used identity column.
SQL> CREATE TABLE journal_messages(
2 ID VARCHAR(36) NOT NULL, -- column to be changed
3 MESSAGE VARCHAR(2048) NOT NULL,
4 MESSAGE_TYPE VARCHAR(30) NOT NULL,
5 MSG_DATE TIMESTAMP NOT NULL,
6 MODULE_CODE INTEGER NOT NULL
7 );
Table created.
SQL> delete from journal_Messages;
0 rows deleted.
SQL> alter table journal_messages modify (id number(10));
Table altered.
SQL> CREATE SEQUENCE journal_messages_seq START WITH 1;
Sequence created.
SQL> create or replace trigger trg_bi_joumes
2 before insert on journal_messages
3 for each row
4 begin
5 :new.id := journal_messages_seq.nextval;
6 end;
7 /
Trigger created.
SQL>
[EDIT: after reading your comment and saw your edition]
That still works OK - I literally copy/pasted your code and got this:
SQL> ALTER TABLE JOURNAL_MESSAGES DROP COLUMN ID;
Table altered.
SQL> ALTER TABLE JOURNAL_MESSAGES ADD (ID NUMBER(10) NOT NULL);
Table altered.
SQL> create or replace trigger trg_seq_journal_msg
2 before insert on journal_messages
3 for each row
4 begin
5 :new.id := journal_messages_seq.nextval;
6 end;
7 /
Trigger created.
SQL> INSERT INTO JOURNAL_MESSAGES (message, MESSAGE_TYPE, msg_date, MODULE_CODE) VALUES ('test', 'alteration', CURRENT_TIMESTAMP, '10')
2 ;
1 row created.
SQL>
As you can see, everything seems to be just fine. Try the following: recompile the trigger and show errors (if any; if so, please, post them here):
SQL> alter trigger trg_seq_journal_msg compile;
Trigger altered.
SQL> show err
No errors.
SQL>