Oracle SQL Developer Triggers IF - oracle

The question is asking me to update the Reorder to either "Y" or "N" depending on whether what the store has on hand is less then the Minimum requirement.
Here is what I have so far, but it keeps giving me error. This is my first time writing triggers.
CREATE OR REPLACE TRIGGER TRG_REORDER
AFTER INSERT OR UPDATE OF ON_HAND, MINIMUM ON PART
FOR EACH ROW
BEGIN
IF NEW.ON_HAND <= NEW.MINIMUM THEN
SET NEW.REORDER = 'Y';
ELSE
SET NEW.REORDER = 'N';
END IF;
END;
Found a solution to my problems, AFTER has its limitation, so from reading this little doc about BEFORE and AFTER triggers and this other doc about triggers as well.
CREATE OR REPLACE TRIGGER TRG_REORDER
BEFORE INSERT OR UPDATE OF ON_HAND, MINIMUM ON PART
FOR EACH ROW
BEGIN
IF :NEW.ON_HAND < :NEW.MINIMUM THEN
:NEW.REORDER := 'Y';
ELSE
:NEW.REORDER := 'N';
END IF;
END;

Related

IF THEN ELSE NESTED PL/SQL ORACLE

I am a beginner using PL/SQL in oracle database, I just want to develop the coding that has been exist before. I want to put new condition and statement IF THEN ELSE NESTED after this code ELSIF updating THEN H_TYP := 'U';
But I am stuck with the my code, I have not yet find the way to fixing my code.
Here is my code;
create or replace TRIGGER TMCI_SUB_ITEM_MASTER_TR_R
AFTER DELETE OR INSERT OR UPDATE ON TMCI_SUB_ITEM_MASTER
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
BEGIN
DECLARE
H_ID TMCI_SUB_ITEM_MASTER_R.HST_ID%TYPE;
H_TYP TMCI_SUB_ITEM_MASTER_R.TSK%TYPE;
rdate DATE;
t_max_rev TMCI_SUB_ITEM_MASTER_R.REV%TYPE;
H_INS_USR_ID TMCI_SUB_ITEM_MASTER_R.INS_USR_ID%TYPE;
BEGIN
rdate := SYSDATE;
IF INSERTING THEN H_TYP := 'I';
...
ELSIF updating THEN H_TYP := 'U';
IF H_INS_USR_ID = 'SL01' THEN
SELECT NVL(MAX(Rev), 0) INTO t_max_rev FROM TMCI_SUB_ITEM_MASTER_R WHERE ITM_CD = :old.ITM_CD;
INSERT INTO TMCI_SUB_ITEM_MASTER_R
VALUES( H_ID,
H_TYP,
:old.ITM_CD,
CASE WHEN :old.ITM_NM <> :new.ITM_NM THEN CONCAT(:new.ITM_NM,'')
ELSE :new.ITM_NM
END);
ELSE
SELECT NVL(MAX(Rev), 0) INTO t_max_rev FROM TMCI_SUB_ITEM_MASTER_R WHERE ITM_CD = :old.ITM_CD;
INSERT INTO TMCI_SUB_ITEM_MASTER_R
VALUES( H_ID,
H_TYP,
:old.ITM_CD,
CASE WHEN :old.ITM_NM <> :new.ITM_NM THEN CONCAT(:new.ITM_NM,'*')
ELSE :new.ITM_NM
END);
END IF;
ELSIF deleting THEN H_TYP := 'D';
...
END IF;
END;
END;
If I login by SL01 result will always read in the last statement (ELSE ...). It should be execute the first statement.
I need a help for fixing this problem.
It looks like you are never setting H_INS_USR_ID to any value. I assume it is meant to the user for the incoming row? If that is the case, then
H_INS_USR_ID TMCI_SUB_ITEM_MASTER_R.INS_USR_ID%TYPE;
becomes
H_INS_USR_ID TMCI_SUB_ITEM_MASTER_R.INS_USR_ID%TYPE := :new.INS_USR_ID;

PL/SQL Unable to get return value of a function when called through trigger - Oracle

I am calling a function in oracle in an after update trigger. The Function is returning a value that is equated to perform a select and an insert operation.
The issue is when I am calling this function in the trigger it is getting terminated, that is it is not performing the corresponding insert operation. But the function is working fine when I execute it by itself. Also, if the trigger is run by removing the condition which is returned by the function, it is getting executed as expected.
Function:
CREATE OR REPLACE FUNCTION VERIFY_FINAL
(case_id IN number)
RETURN varchar2
IS
is_marked_final varchar2(4);
loop_count number(2);
cursor c1 is
SELECT sub_case_status from
cdm_master_sub_case
where master_id = (case_id);
BEGIN
is_marked_final := 'Y';
loop_count := 0;
FOR rec in c1
LOOP
IF (rec.sub_case_status = '1') THEN
is_marked_final := 'Y';
ELSIF (rec.sub_case_status = '2') THEN
is_marked_final := 'Y';
ELSE
loop_count := loop_count + 1;
END if;
END LOOP;
IF (loop_count > 0) THEN
is_marked_final := 'N';
END if;
RETURN is_marked_final;
END;
Trigger:
CREATE OR REPLACE TRIGGER CDM_MASTER_SUB_CASE_TRIGGER
AFTER UPDATE
on CDM_MASTER_SUB_CASE
FOR EACH ROW
DECLARE
check_var varchar2(4);
unique_id varchar2(100);
transaction_id number(10);
BEGIN
transaction_id := :new.MASTER_ID;
check_var := VERIFY_FINAL(transaction_id);
IF (check_var = 'Y') THEN
select UNIQUE_CUST_ID
INTO unique_id
from ASM355.cdm_matches
where MASTER_ID = :new.MASTER_ID
and rownum = 1;
INSERT INTO tracking_final_cases (MASTER_ID,unique_cust)
values (:new.master_id,unique_id);
END if;
END;
I would appreciate it if anyone can point me in the right direction.
1.) As tmrozek points out a return of 'N' will not do the associated insert. I might suggest having an ELSE to that IF that does something to indicate if that is what is happening.
2.) I would also point out that your SELECT INTO, if it does not find a corresponding value, would cause issues. You might want to do something to ensure that this trigger is failsafe, or have you considered what you want the code to do if that situation occurs? (Error out? Insert a null unique_id?)
3.) If you are looking at the results from a different session, bear in mind that the inserted tracking_final_cases will not be visible until you commit your changes in the session that called the trigger.
I don't know your table data but it is possible to your function to return 'N' so it wouldn't meet your trigger condition (check_var = 'Y').
If you run command like that:
update CDM_MASTER_SUB_CASE
set sub_case_status = 3;
you will probably get your problem.
Thanks guys for the time, it got resolved. I was querying a select statement in the function body over a table on which the corresponding trigger was created.

How to resolve fetch out of sequence in oracle?

I have a procedure in which I am often getting the following error in oracle 11g:
ORA-01002: fetch out of sequence ORA-06512:
at "LEAVE.GES_ERP_LEV_FFS_INTERFACE_PRC", line 350 ORA-06512: at line 1.
at line 350 I have-
BEGIN
FOR V_INTERFACE_EMP IN CUR_INTERFACE_EMP LOOP (Line 350)
EXIT WHEN CUR_INTERFACE_EMP%NOTFOUND;
V_ERR_FLAG := 'N';
V_LOCAL_EMP := 'Y';
BEGIN
The Cursor CUR_INTERFACE_EMP is declared as below
SELECT GELF.*
FROM GES_ERP_LEV_FFS_INTERFACE_T GELF
WHERE (GELF.BALANCE_FLAG != 'W'
OR GELF.CASE_FLAG = 'S'
OR SELF.BALANCE_FLAG IS NULL)
AND GELF.PROCESS_FLAG = 'N'
AND GELF.DATE_OF_RELEASE <= TRUNC(SYSDATE);
If i update some records of the table with Process_Flag Y,the batch works fine for some time and then again after some days we get this same issue.
Please help,let me know in case data is also needed for the mentioned table.
If i update some records of the table with Process_Flag Y,the batch
works fine for some time and then again after some days we get this
same issue.
You try to fetch from a SELECT FOR UPDATE, however a COMMIT has already been issued before it.
I think you have a COMMIT somewhere INSIDE the LOOP which is causing this issue.
A quote by Tom Kyte here:
for x in ( select rowid rid, t.* from T ) loop
update T set x = x+1 where rowid = x.rid;
commit;
end loop;
That implicit cursor is fetched from "across a commit". It is the
practice of keeping a cursor open after committing. It is a bad
practice and is a common cause of ORA-1555 (the above looping
construct in particular)
Also, you are using a CURSOR FOR LOOP. The CURSOR FOR LOOP will terminate when all of the records in the cursor have been fetched. So, you don't need to EXIT explicitly.
You could simply do it as:
FOR V_INTERFACE_EMP IN CUR_INTERFACE_EMP
LOOP
V_ERR_FLAG := 'N';
V_LOCAL_EMP := 'Y';
...
END LOOP;
I was facing the same issue of fetch out of sequence in oracle plsql.
The problem was below line of code which was used in a procedure that was getting called from inside the loop.
-------------problem code--------
if p_ret is null
then
p_ret := 'SUCCESS';
rollback;
return;
end if;
-------------problem code--------
I should not have used rollback.
So, watch out for rollback and commit inside the loop statement.

Change inserted value with trigger

I've just started to learn SQL a few weeks ago and I'm trying to make a trigger which changes the inserted value into 10 if it's smaller than 10. I searched for 4h now and I've found a lot of answers but none was good(for me). I really don't understand where the problem is.
Here is the code:
CREATE OR REPLACE TRIGGER NumberOfBooks
BEFORE INSERT
ON Book
FOR EACH ROW
BEGIN
IF new.nobook < 10
THEN
SET new.nobook = 10;
END IF;
END;
In Oracle's trigger syntax the newly inserted record is referred to by :new, not new (notice the colon). Additionally, SET is a part of an update statement, not a way to set field values - those are done by simple assignments, but note that these are done with := rather than =.
So, your trigger should read:
CREATE OR REPLACE TRIGGER NumberOfBooks
BEFORE INSERT
ON book
FOR EACH ROW
BEGIN
IF :new.nobook < 10
THEN
:new.nobook := 10;
END IF;
END;

How to get number of rows affected by a statement when inside that statement's trigger

I have a statement level trigger that fires whenever INSERT UPDATE or DELETE operations are performed on a table (called customers). I want to display a message (to DBMS_OUTPUT) containing the number of rows that were inserted/updated/deleted.
I just want one message for each triggering statement, eg
'4 rows were inserted into customers table'.
How can I access the number of rows that are affected by the triggering statement from INSIDE the trigger declaration, ie XXX in the code below:
CREATE OR REPLACE TRIGGER customer_changes_trigger_2
AFTER INSERT OR UPDATE OR DELETE ON customers
DECLARE
v_operation VARCHAR(10);
v_number_rows NUMBER;
BEGIN
v_number := XXX;
IF INSERTING THEN
v_operation := 'inserted';
END IF;
IF UPDATING THEN
v_operation := 'updated';
END IF;
IF DELETING THEN
v_operation := 'deleted';
END IF;
DBMS_OUTPUT.PUT_LINE
(v_number_rows|| ' rows were ' || v_operation || ' from customers.');
END;
Can't find anything in the documentation, any help appreciated!
One way is to use a global variable to track the number of rows as there is no other way to get the row count from a statement level trigger. You would then need three triggers... one statement level to initialise the variable before the statement is run, one row level to add one to the variable for each row, one statement level to use the row count however you wish. First, set up the variable and a few procedures to help it:
create or replace package PKG_ROWCOUNT is
NUMROWS number;
procedure INIT_ROWCOUNT;
procedure ADD_ONE;
function GET_ROWCOUNT
return number;
end PKG_ROWCOUNT;
/
create or replace package body PKG_ROWCOUNT as
procedure INIT_ROWCOUNT is
begin
NUMROWS := 0;
end;
procedure ADD_ONE is
begin
NUMROWS := Nvl(NUMROWS, 0) + 1;
end;
function GET_ROWCOUNT
return number is
begin
return NUMROWS;
end;
end PKG_ROWCOUNT;
/
The first trigger to initialise the variable:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_1
before insert or update or delete
on CUSTOMERS
begin
PKG_ROWCOUNT.INIT_ROWCOUNT;
end;
The second to update per row:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_2
after insert or update or delete
on CUSTOMERS
for each row
begin
PKG_ROWCOUNT.ADD_ONE;
end;
/
The third to display the total:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_3
after insert or update or delete
on CUSTOMERS
begin
Dbms_output.
PUT_LINE(PKG_ROWCOUNT.GET_ROWCOUNT || ' rows were affected.');
end;
I'm not 100$ sure if it's available inside AFTER trigger body, but you can try examining sql%rowcount

Resources