I have trigger for auditing, which stored the action performed on any row of EMP table.
This trigger works fine, except in some cases (which occurs very rarely, and I cannot identify exact condition) it gives me
Oracle Error: ORA-01400: cannot insert NULL into ("MY_SCHEMA"."HIST_EMP"."ACTION")
CREATE OR REPLACE TRIGGER HIST_EMP_AIUD
AFTER UPDATE OR INSERT OR DELETE
ON EMP
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
v_action VARCHAR2(1) := 'D';
BEGIN
IF INSERTING THEN
v_action := 'A';
ELSIF UPDATING THEN
v_action := 'U';
END IF;
IF DELETING THEN
INSERT INTO hist_emp (source_rowid, source_date, action)
VALUES (:old.rowid, SYSDATE, v_action);
ELSIF INSERTING OR UPDATING THEN
INSERT INTO hist_emp (source_rowid, source_date, action)
VALUES (:new.rowid, SYSDATE, v_action);
END IF;
EXCEPTION
WHEN OTHERS THEN
--Code to Log
-- <some exception handling should be placed here >
END;
This generally happens when I am deleting the row, but I am not sure.
Any thought on why this will be happening? The code looks ok to me...
Something weird is going on with variable v_action initialization, I guess. Try handling all 3 possibilities:
v_action:= null;
IF INSERTING THEN
v_action := 'A';
ELSIF UPDATING THEN
v_action := 'U';
ELSIF DELETING THEN
v_action := 'D';
END IF;
Related
thanks for helping me.
The first insert works OK but the second doesnt insert anything. Can you help me please. Im learning plsql but there is still some things i dont know.
PROCEDURE PR_INS_INVESTIGATION (
PIN_INS_INVESTIGATION IN IN_INS_INVESTIGATION)
IS
LST_INS_INVESTIGATED RC_INS_INVESTIGATED;
EX_NO_DATA EXCEPTION;
BEGIN
INSERT INTO PQR076INVESTIGATION (CCPQR076IDINVESTIGATION,
CCPQR076DATE,
CCPQR076AREA,
CCPQR076STATE,
CCPQR076USER)
VALUES (PIN_INS_INVESTIGATION.IDINVESTIGACION,
SYSDATE,
PIN_INS_INVESTIGATION.AREA,
PIN_INS_INVESTIGATION.STATE,
USER);
COMMIT;
IF LST_INS_INVESTIGATED IS NOT NULL
AND LST_INS_INVESTIGATED.COUNT > 0
THEN
FOR j IN LST_INS_INVESTIGATED.FIRST .. LST_INS_INVESTIGATED.LAST
LOOP
INSERT INTO PQR075INVESTIGATED (CCPQR075IDINVESTIGATION,
CCPQR075NIDENT,
CCPQR075NAME,
CCPQR075USER)
VALUES (PIN_INS_INVESTIGATION.IDINVESTIGAtION,
LST_INS_INVESTIGATED (J).NUMBERID,
LST_INS_INVESTIGATED (J).NAME,
USER);
COMMIT;
END LOOP;
END IF;
END;
This is the way im testing the procedure:
´´´
declare
pin_ins_investigation in_ins_investigation;
begin
pin_ins_investigation := in_ins_investigation();
pin_ins_investigation.IDinvestigation := '1234460';
pin_ins_investigation.AREA := '05';
pin_ins_investigation.STATE := 'E';
pin_ins_investigation.LST_INS_investigated.extend;
pin_ins_investigation.LST_INS_investigated(1).NUMBERID := '1014350360';
pin_ins_investigation.LST_INS_investigated(1).NAME := 'PETER TOSH';
pkg_package.pr_ins_investigation(pin_ins_investigation => pin_ins_investigation);
end;
´´´
The way I see it, this:
IF LST_INS_INVESTIGATED IS NOT NULL
AND LST_INS_INVESTIGATED.COUNT > 0
is never true so nothing within the IF - END IF block is ever executed.
You declared it as
LST_INS_INVESTIGATED RC_INS_INVESTIGATED;
but lst_ins_investigated doesn't contain anything, it is just declared, never populated with any values. Once you fix that, code might work.
I created a trigger, and this is the code below, for which I got the above error. I am doing this on Oracle Live SQL. I think it is a Live SQL specific error because the same code doesn't have much problems on a local database. Here is the code below:
create or replace trigger t1
after update or insert or delete
on emp_43
declare
o char(1);
begin
if inserting then
o := 'i';
elsif updating then
o := 'u';
else
o := 'd';
end if;
insert into emp_trail values(o,sysdate);
end;
please help this noob out.
this is the snapshot of the code and error on live sql
correct syntax is
create or replace trigger t1
after update or insert or delete
on emp_43
declare o char(1);
begin
if (inserting) then
o := 'i';
elsif (updating) then
o := 'u';
else
o := 'd';
end if;
insert into emp_trail values(o,sysdate);
end;
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;
I am just want to enter forms detail column data into a database column from a detail block and that must check first entered data which it already have in that column when i entered data data saves in other tables but in token_staus is not entering data and message me No data found for that i write a loop which is not working for me i am making some kind of mistake obviously but not sure where it is
DECLARE
TOKEN_NO NUMBER;
TOKEN_STATUS1 NUMBER;
--TOKEN_STATUS2 := :TOKEN_STATUS;
BEGIN
SELECT SR_NO, TOKEN_STATUS INTO TOKEN_NO, TOKEN_STATUS1 FROM LOOPT2 WHERE SR_NO = :TOKEN_NO;
--IF :TOKEN_STATUS IS NULL
--THEN
LOOP
GO_BLOCK('TOKEN_REC2');
FIRST_RECORD;
INSERT INTO LOOPT2(TOKEN_STATUS) VALUES(:TOKEN_STATUS);
NEXT_RECORD;
EXIT WHEN :SYSTEM.LAST_RECORD = 'TRUE';
END LOOP;
--END IF;
EXCEPTION
when others then
message (sqlerrm);
END;
Please help me
Little Foot please
If I understood you correctly, it would be something like this (check comments within the code): key thing here seems to be a BEGIN-EXCEPTION-END block within the LOOP.
DECLARE
TOKEN_NO NUMBER;
TOKEN_STATUS1 NUMBER;
BEGIN
GO_BLOCK('TOKEN_REC2');
FIRST_RECORD;
LOOP
BEGIN
SELECT SR_NO, TOKEN_STATUS
INTO TOKEN_NO, TOKEN_STATUS1
FROM LOOPT2
WHERE SR_NO = :TOKEN_NO;
-- if such a :TOKEN_NO exists, that SELECT will return some values
-- which means that you want to skip it, so - don't do anything
EXCEPTION
-- if such a :TOKEN_NO does not exist, SELECT will return
-- NO_DATA_FOUND which means that you want to perform insert
WHEN NO_DATA_FOUND THEN
INSERT INTO LOOPT2 (TOKEN_STATUS)
VALUES (:TOKEN_STATUS);
WHEN TOO_MANY_ROWS THEN
NULL;
END;
EXIT WHEN :SYSTEM.LAST_RECORD = 'TRUE';
NEXT_RECORD;
END LOOP;
END;
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.