Creating AFTER INSERT TRIGGER on Oracle table - oracle

I don’t know how to create AFTER INSERT TRIGGER with the condition Table_1.Table_2_ID = Table_2.ID .
CREATE OR REPLACE TRIGGER Table_2_TRG
AFTER INSERT
ON Table_1
FOR EACH ROW
BEGIN
UPDATE Table_2
SET Col1 = '1'
FROM (SELECT Table_2_ID FROM Table_1)
WHERE Table_1.Table_2_ID = Table_2.ID;
END;
It is needed to change record’s value in the Table_2 AFTER INSERT a record in the Table_1 with the similar ID (Table_2_ID in the Table_1 and ID in the Table_2 are identical).
Col1 in the Table_2 has type VARCHAR2.
I have this code, but after running statement there is an error:
“2/5 PL/SQL: SQL Statement ignored
4/5 PL/SQL: ORA-00933: SQL command not properly ended”

If I got it right, you need such a WHERE clause:
CREATE OR REPLACE TRIGGER Table_2_TRG
AFTER INSERT
ON Table_1
FOR EACH ROW
BEGIN
UPDATE Table_2 b
SET b.Col1 = '1'
WHERE b.id = :new.table_2_id;
END;

this will work:
CREATE OR REPLACE TRIGGER Table_2_TRG
AFTER INSERT
ON Table_1
FOR EACH ROW
BEGIN
UPDATE Table_2
SET Col1 = '1'
where id=:new.id;
END;

Related

Trigger created with compilation errors. ORA-:missing SELECT keyword

I am trying to create a trigger that fires after an insert/update and checks for null values in couple of columns. In case any one of them is NULL, it queries other tables and updates the current table
CREATE OR REPLACE TRIGGER sample_trigger
AFTER INSERT OR UPDATE
ON test_table
FOR EACH ROW
BEGIN
IF :NEW.ID IS NULL OR :NEW.CODE IS NULL
THEN
UPDATE (:NEW.ID,:NEW.CODE) = (SELECT T1.ID,
T2.CODE
FROM TABLE_1 T1
JOIN TABLE_2 T2 ON T1.ID=T2.ID
WHERE ID=:NEW.TEST_ID);
END IF;
END;
/
Warning: Trigger created with compilation errors.
ERROR: PL/SQL: ORA-00928: missing SELECT keyword
You don't UPDATE the :new pseudo-record. Just assign values to it
SELECT t1.id, t2.code
INTO :new.id, :new.code
FROM table1 t1
join table2 t2 on t1.id = t2.id
WHERE id = :new.test_id
A couple additional notes
Your WHERE clause will generate an ambiguous reference error. Since both t1 and t2 have an ID column, you'd need to specify which table's column you are comparing against.
If test_table is the same as either table_1 or table_2, that's going to produce a mutating table exception.
Your trigger should be a BEFORE INSERT since it's modifying data not an AFTER INSERT trigger.
Triggers have to follow syntax as any other program unit; UPDATE you wrote is invalid (obviously), but - you don't need it. Here's what you might have done:
declare two variables which will hold ID and CODE values
set TEST_TABLES's columns values to those variables
CREATE OR REPLACE TRIGGER sample_trigger
AFTER INSERT OR UPDATE
ON test_table
FOR EACH ROW
DECLARE
l_id test_table.id%type;
l_code test_table.code%type;
BEGIN
IF :NEW.ID IS NULL OR :NEW.CODE IS NULL
THEN
SELECT t1.id, t2.code
INTO l_id , l_code
FROM table_1 t1 JOIN table_2 t2 ON t1.id = t2.id
WHERE id = :new.test_id;
:new.id := l_id;
:new.code := l_code;
END IF;
END;
/

Oracle returning statement for an insert into operation with 'select from' source

We would like to return ids inserted from an insert statement that has a 'select from' clause as its source of values.
Example:
Create table Table1 (Col1 Number)
declare
vId number;
begin
insert into Table1 (select 1 from dual)
returning COL1 into vId;
end;
Error:
ORA-06550: line 5, column 5:
PL/SQL: ORA-00933: SQL command not properly ended
Is there something missing in the syntax, is it possible to do this? Thank you.
Returning into works only, when columns are listed before VALUES:
declare
vId number;
begin
insert into Table1 (col1) VALUES ((select 1 from dual))
returning COL1 into vId;
dbms_output.put_line( vId);
end;
==========
vId: 1

Oracle - trigger after update

I have trigger:
CREATE OR REPLACE TRIGGER TR.TR_OUTPUT_EHT_UPDATE_OPE
AFTER DELETE
ON TR.TR_JN_OUTPUT_EHT
FOR EACH ROW
DECLARE
BEGIN
UPDATE TR.TR_BP tbp
SET tbp.DONE= 2, tbp.DATA_WYK = SYSDATE
WHERE EXISTS (SELECT ARCH.NR
FROM TR.TR_KB_OUTPUT_ARCH ARCH
WHERE ARCH.NR = tbp.NRKK)
AND NOT EXISTS (SELECT OUTPUT.NR_SERYJNY
FROM TR.TR_JN_OUTPUT OUTPUT
WHERE OUTPUT.NR = tbp.NRKK);
END;
/
After that I want to get the "NRKK" of just updated row and update another table which is connected by this "NRKK":
UPDATE P.TR_OPE OPE
SET OPE.DATA = SYSDATE,
OPE.STATUS = OPE.STATUS + 1
WHERE OPE.NRKK = "NRKK"
I tried to do:
SELECT tbp.NRKK INTO v_nrkk FROM TR.TR_BP tbp WHERE tbp.DATA = (SELECT
MAX(tbp.DATA) FROM TR.TR_BP tbp1);
but I have errors: ORA 04091, ORA 06512 and ORA 04088.
EDITED:
I created another trigger:
CREATE OR REPLACE TRIGGER TR.TR_OP_E
AFTER UPDATE ON TR.TR_BP
FOR EACH ROW
DECLARE
v_nrkk TR.TR_BP.NRKK % TYPE;
BEGIN
SELECT tbp.NRKK INTO v_nrkk FROM TR.TR_BPtbp WHERE tbp.DATA = (SELECT
MAX(tbp.DATA) FROM TR.TR_BP tbp1);
IF v_nrkk is NOT NULL THEN
UPDATE P.TR_OPE OPE
SET OPE.DATA = SYSDATE, OPE.STATUS = 1
WHERE OPE.ID_BR = '00100300'
AND OPE.NRKK = v_nrkk;
END IF;
END;
/
But I have still errors...
As mentioned by #Renato Afonso, you can avoid mutating table error via using a COMPOUND TRIGGER. See below demo;
--Tables
CREATE TABLE TABLE_1 (data NUMBER);
/
CREATE TABLE TABLE_2 (DATA1 NUMBER);
/
--Record in table_1
SQL> select * from TABLE_1;
DATA
----------
1
--Record in table_2
SQL> select * from TABLE_2;
DATA1
----------
5
Trigger:
CREATE OR REPLACE TRIGGER TR_OP_E FOR
INSERT OR UPDATE OR DELETE
ON TABLE_1
COMPOUND TRIGGER
v_nrkk TABLE_1.DATA%TYPE;
AFTER STATEMENT
IS
BEGIN
--Selecting from the same table on which trigger is created
SELECT tbp.data
INTO v_nrkk
FROM Table_1 tbp
WHERE tbp.DATA = (SELECT MAX (tbp.DATA)
FROM Table_1 tbp1);
IF v_nrkk IS NOT NULL
THEN
UPDATE TABLE_2 OPE
SET OPE.DATA1 = v_nrkk;
END IF;
END
AFTER STATEMENT;
END;
/
Execution:
SQL> UPDATE TABLE_1 SET DATA = 2;
1 row updated.
SQL> COMMIT;
Commit complete.
SQL> select * from TABLE_1;
DATA
----------
2
SQL> select * from TABLE_2;
DATA1
----------
2

Create a table in Oracle SQL If table does not exist using select and join

The question is very common, but I am facing one single issue in there for which I am not able to find the answer.
What I have to do is, create a table if the table does not exist.
But while creating the table, I need to create it from the select query(which is result of JOIN of two tables).
This is for "ORACLE SQL DEVELOPER" / "PL/SQL".
The query I am using is:
DECLARE
count_matching_tbl BINARY_INTEGER := 0;
BEGIN
SELECT COUNT(*)
INTO count_matching_tbl
FROM dba_tables
WHERE LOWER(table_name) = 'testtable';
IF(count_matching_tbl = 0)
THEN
EXECUTE IMMEDIATE ( ' CREATE TABLE testtable AS (SELECT A.*, B.* from tab1 A JOIN tab2 B ON A.id = B.RID WHERE 1=2)');
END IF;
END;
If tab1 and tab2 table has same name column then ambiguity occure while creating table and inserting record so instead of * replace table column which is add in testtable like
CREATE TABLE testtable AS (SELECT A.cola1, B.colb1 from tab1 A JOIN tab2 B ON A.id = B.RID WHERE 1=2
ask your dba to give "select on dba_tables " to your schema .
Since you are using a pl/sql procedure , you need to have permissions granted directly to you rather than through a role.
The issue was because of the static SQL data.
The table was created dynamically, but the rest of the statements were trying to access the static data.
To solve this, I have created two anonymous blocks, the first one having the create table statement, commit it and end the block.
The next anonymous block will have the rest of the statements to be executed after the IF clause.
This solved my problem.
DECLARE
count_matching_tbl BINARY_INTEGER := 0;
BEGIN
SELECT COUNT(*)
INTO count_matching_tbl
FROM dba_tables
WHERE LOWER(table_name) = 'testtable';
IF(count_matching_tbl = 0)
THEN
EXECUTE IMMEDIATE ( ' CREATE TABLE testtable AS (SELECT A.*, B.* from tab1 A JOIN tab2 B ON A.id = B.RID WHERE 1=2)');
COMMIT;
END IF;
END;
/
BEGIN
-- Rest of the database execution statements
COMMIT;
END;
/

create trigger by checking the value of a field being inserted in oralce

I need to create a before insert trigger on TABLE1 such that it inserts COL2 and COL3 of the new row being inserted in TABLE1 into TABLE2 only when TABLE1.FIELD1 = 'XYZ'. How do I do this so that trigger gets fired only when the condition is met?
CREATE OR REPLACE TRIGGER my_trigger
before insert
ON table_1
FOR EACH ROW
BEGIN
IF :NEW.FIELD1 = 'XYZ'
then
INSERT INTO table_2 (col1, col2) VALUES (:NEW.col1, :NEW.col2);
END IF;
END;
/
or how a_horse_with_no_name noted, your can use the the WHEN clause
CREATE OR REPLACE TRIGGER my_trigger
before insert
ON table_1
FOR EACH ROW
WHEN (NEW.FIELD1 = 'XYZ')
BEGIN
INSERT INTO table_2 (col1, col2) VALUES (:NEW.col1, :NEW.col2);
END;
/

Resources