PL/SQL calling a function inside a trigger - oracle

I am trying to create a function using Oracle PL/SQL that stores the current date into a variable. This function will be called inside a trigger. The trigger (among other things) will insert this variable into a new table that has already been created. My code complies and runs without errors, but it doesn't work. Nothing happens. The trigger is an ON DELETE trigger, so when I delete one row from the original table, it just stays. Any clues what I am missing? Thank you.
Function:
CREATE OR REPLACE FUNCTION get_date (i_stdid archive_student.stdid%TYPE)
RETURN date
AS
v_date DATE;
BEGIN
SELECT CURRENT_DATE INTO v_date FROM DUAL;
RETURN v_date;
END;
Function call inside trigger:
CREATE OR REPLACE TRIGGER ARCHIVE_DELETED_STUDENT
AFTER DELETE ON STUDENT
FOR EACH ROW
DECLARE
v_date archive_student.change_date%TYPE;
BEGIN
-- other if statements here that are working properly
v_date := get_date(:old.stdid);
INSERT INTO archive_student (change_date) VALUES (v_date);
END;

You doing well, check this SQLFiddle.
Only one thing - you missed stdid while inserting into archive_student so it is null after insert.

Related

How can I get the inserted primary key value from AFTER INSERT trigger in Oracle?

My Oracle DB has a table DOC_WF_COMM and its primary key is DWFC_ID. Primary key value is based on a sequence called SQ_DOC_WF_COMM.
I have created a row level AFTER INSERT trigger on that table and inside the trigger I need to join the inserted record with some other tables like this:
create or replace TRIGGER TRG_DOC_WF_COMM_AFT_INS AFTER INSERT ON DOC_WF_COMM REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
L_SUBJECT VARCHAR2(300);
L_BODY CLOB;
L_PNT_CODE VARCHAR(100) := NULL;
L_DR_PRJ_ID NUMBER(12);
L_STR_EMAIL VARCHAR2(120);
L_DWFC_TO_USR_ID VARCHAR2(12);
L_PNT_ID NUMBER(12);
L_PNT_EMAIL_YN VARCHAR(1);
L_PNT_ACTIVE_YN VARCHAR(1);
L_PNT_NOTIFY_YN VARCHAR(1);
BEGIN
IF INSERTING THEN
L_PNT_CODE := 'WFNT_MESSAGE';
SELECT DR_PRJ_ID, STR_EMAIL, DWFC_TO_USR_ID INTO L_DR_PRJ_ID, L_STR_EMAIL, L_DWFC_TO_USR_ID
FROM DOC_WF_COMM
JOIN DOC_WF_USERS ON DWFU_ID = DWFC_DWFU_ID
JOIN DOC_WORKFLOW ON DWF_ID = DWFU_DWF_ID
JOIN DOCUMENT_REF ON DR_ID = DWF_DR_ID
JOIN ST_REGISTER ON STR_ID = DWFU_STR_ID
WHERE DWFC_ID = :NEW.DWFC_ID AND DWFC_RESPONSE IS NULL;
-- SOME QUERIES HERE
END IF;
END;
The trigger is compiled successfully and when I insert record into DOC_WF_COMM table I get this error:
ORA-01403: no data found ORA-06512
The error is :NEW.DWFC_ID in WHERE clause and I have change it to these values:
:OLD.DWFC_ID
SQ_DOC_WF_COMM.NEXTVAL
SQ_DOC_WF_COMM.CURRVAL
But no any luck. Any idea why this error is and how can I resolve it?
The problem is this line in your trigger:
PRAGMA AUTONOMOUS_TRANSACTION;
That means the trigger executes as an isolated transaction in a separate session, which means it cannot see the uncommitted state of any other session. Crucially this includes the session which fires the trigger, so the autonomous transaction cannot see the record you just inserted. Hence, NO_DATA_FOUND.
You haven't posted the whole trigger or explained what you're trying to do, so only you know why you have included the PRAGMA. However, the chances are you don't need it. Remove the PRAGMA (and the COMMIT) and your trigger should work just fine.
If I understood you correctly, create a local variable and put the next sequence value in there. Then it can be referenced throughout the code, always having the same value. Something like this:
declare
l_seq number := my_seq.nextval;
begin
insert into table_a (id, ...) values (l_seq, ...);
update table_b set id = l_seq where ...
select ... into ... from ... where id = l_seq;
end;
I changed the query inside the trigger to this, it is working fine
SELECT STR_PRJ_ID, STR_EMAIL, :NEW.DWFC_TO_USR_ID INTO L_DR_PRJ_ID, L_STR_EMAIL, L_DWFC_TO_USR_ID
FROM DOC_WF_USERS, ST_REGISTER
WHERE :NEW.DWFC_TO_USR_ID = DWFU_US_ID AND DWFU_STR_ID = STR_ID AND DWFU_ID = :NEW.DWFC_DWFU_ID;
Not sure why is that. If anyone can figure out the mistake in the query given in the question, please let me know. Thanks

Oracle Trigger PLS 00103

I am a novice in PL/SQL and DB objects. I have written an after insert trigger based on condition but I am getting PLS 00103 error encountered ;. Please help.
Below is my trigger script,
CREATE TRIGGER trigger1 AFTER INSERT
ON Table1
FOR EACH ROW
when (new.upper(Table1.column1)='ABC')
Declare
ITEM_CODE table2.ITEM_CODE%TYPE;
BEGIN
ITEM_CODE := :new.ITEM_CODE;
INSERT INTO table2( PK,ITEM_CODE,EVENT_NUMBER)
VALUES(EVENT_NUMBER_SEQ.NEXTVAL, ITEM_CODE,EVENT_NUMBER_SEQ.NEXTVAL);
END;
I am executing this script through Toad.
Thanks in Advance.
problem is here: when (new.upper(Table1.column1)='ABC') should be (when upper(new.column1) ='ABC')
Also you don't need declare variable only to assign value. Just use value directly.
CREATE TRIGGER trigger1 AFTER INSERT
ON Table1
FOR EACH ROW
when (upper(new.column1) ='ABC')`
BEGIN
-- IF (upper(:new..column1) ='ABC') THEN
INSERT INTO table2( PK,ITEM_CODE,EVENT_NUMBER)
VALUES(EVENT_NUMBER_SEQ.NEXTVAL, :new.ITEM_CODE,EVENT_NUMBER_SEQ.NEXTVAL);
--END IF;
END;

Oracle auto increment trigger issue

I am having an issue when creating the auto increment trigger in Oracle 11g. If someone can point out what I am doing wrong, I would really appreciate it. My script for the sequence is this :
CREATE SEQUENCE SPSS_QUOTE_LINE_ITEMS_SEQ start with 1
increment by 1
minvalue 1;
The script for trigger:
CREATE OR REPLACE TRIGGER SPSSQUOTELINEITEMS_ON_INSERT
BEFORE INSERT ON SPSS_QUOTE_LINE_ITEMS
FOR EACH ROW
BEGIN
SELECT SPSS_QUOTE_LINE_ITEMS_SEQ.NEXTVAL
INTO :new.line_num
FROM dual;
END;
The error I am getting:
[Code: 900, SQL State: 42000] ORA-00900: invalid SQL statement
Thanks a lot.
The correct way of doing this to modify your trigger as below:
CREATE OR REPLACE TRIGGER SPSSQUOTELINEITEMS_ON_INSERT
BEFORE INSERT ON SPSS_QUOTE_LINE_ITEMS
FOR EACH ROW
BEGIN
:new.line_num := SPSS_QUOTE_LINE_ITEMS_SEQ.NEXTVAL;
--No need to write any Select Into statement here.
END;
Or if i follow your way then it goes like
CREATE OR REPLACE TRIGGER SPSSQUOTELINEITEMS_ON_INSERT
BEFORE INSERT ON SPSS_QUOTE_LINE_ITEMS
FOR EACH ROW
declare
var number;
BEGIN
SELECT SPSS_QUOTE_LINE_ITEMS_SEQ.NEXTVAL
INTO var
FROM dual;
:new.line_num :=var;
END;
You normally use the terms in a trigger using :old to reference the old value of the column and :new to reference the new value.

Accessing the trigger table inside the trigger's body

How can I access a table that has a trigger on inside the trigger's body?
create or replace trigger insert_try after insert on triggerTable for each row
begin
insert into anotherTable (triggerFunction(:new.field1), 155,155);
end;
create or replace function triggerFunction(param1 in number) return number as
abc number;
begin
select max(field1) into abc from triggerTable where field1!= param1;
return abc ;
end triggerFunction;
This results in "SQLSyntaxErrorException: ORA-04091". Is there any way to do the insert operation independent of the trigger and run the trigger afterwards?
I don't see any reason to use the function which queries the same table on which the trigger is defined. It does nothing but sends the :new.field1 as parameter and get's the same value back.
Since you already use FOR EACH ROW, you can access the old and new values as :old and :new.
CREATE OR REPLACE TRIGGER insert_try
AFTER INSERT ON triggerTable
FOR EACH ROW
BEGIN
INSERT INTO anotherTable
(:new.field1, 155,155
);
END;
/
It will simply insert the value from field1 of triggertable into anothertable.
Make the function autonomous by using pragma autonomous_transaction
create or replace function triggerFunction(param1 in number) return number as
abc NUMBER;
pragma autonomous_transaction ;
begin
select max(field1) into abc from triggerTable where field1!= param1;
return abc ;
end triggerFunction;
Then try inserting , mutating table error will not come in this case .

How can i fix this Mutating table from a procedure an trigger

This trigger will pass on inserted values to a procedure which will insert those values in another table. I'm getting a mutating table error. How can i fix this?
CREATE OR REPLACE TRIGGER ADD_INVOICE
BEFORE INSERT OR UPDATE OF APP_NO,C_NO ON APPOINTMENT
FOR EACH ROW
DECLARE
BEGIN
POP_INVOICE(:NEW.APP_NO,:NEW.C_NO,:NEW.APP_DATE);
END;
/
CREATE OR REPLACE PROCEDURE POP_INVOICE(
I_APP_NO IN INVOICE.APP_NO%TYPE,
I_C_NO IN INVOICE.C_NO%TYPE,
I_INV_DATE IN INVOICE.INV_DATE%TYPE)
AS
CURSOR C_POP IS SELECT PRICE FROM TREATMENT T,APPOINTMENT A
WHERE T.TRT_NO=A.TRT_NO
AND A.APP_NO=I_APP_NO;
V_BILL INVOICE.BILL%TYPE;
BEGIN
OPEN C_POP;
FETCH C_POP INTO V_BILL;
UPDATE INVOICE
SET INV_NO=INV_IDSEQ.NEXTVAL,
APP_NO=I_APP_NO,
C_NO=I_C_NO,
BILL=V_BILL,
INV_DATE=I_INV_DATE;
END;
/
The problem is caused by referencing the table with the trigger on it within the trigger itself. Changing the procedure to accept the TRT_NO as a parameter removes the need to include APPOINTMENT in the query, and so will avoid the mutating table exception. Depending on how many records there are for each treatment, you could even incorporate the cursor into your UPDATE statement.
I think this should do it, although I haven't been able to check against a database.
CREATE OR REPLACE TRIGGER ADD_INVOICE
BEFORE INSERT OR UPDATE OF APP_NO,C_NO ON APPOINTMENT
FOR EACH ROW
DECLARE
BEGIN
POP_INVOICE(:NEW.APP_NO,:NEW.C_NO,:NEW.APP_DATE,:NEW.TRT_NO);
END;
/
The revised procedure:
CREATE OR REPLACE PROCEDURE POP_INVOICE(
I_APP_NO IN INVOICE.APP_NO%TYPE,
I_C_NO IN INVOICE.C_NO%TYPE,
I_INV_DATE IN INVOICE.INV_DATE%TYPE,
I_TRT_NO IN APPOINTMENT.TRT_NO%TYPE
)
AS
CURSOR C_POP IS SELECT PRICE
FROM TREATMENT T
WHERE T.TRT_NO = I_TRT_NO;
V_BILL INVOICE.BILL%TYPE;
BEGIN
OPEN C_POP;
FETCH C_POP INTO V_BILL;
CLOSE C_POP;
INSERT INVOICE
(inv_no, app_no, c_no, bill, inv_date)
VALUES
(INV_IDSEQ.NEXTVAL, I_APP_NO, I_C_NO, V_BILL, I_INV_DATE);
END;
/

Resources