I have a oracle procedure which selects data and insert into another table. Bellow is the code.
CREATE OR REPLACE PROCEDURE "CUSTOMER_INCREMENTAL" (
IS
BEGIN
INSERT INTO NDB_AML_CUSTOMER
(ID, TITLE,...)
SELECT ID, TITLE,...
FROM NDB_CUSTOMER_NEW
WHERE DATE_TIME > (SELECT RUN_DATE FROM CHECK_POINT WHERE TABLE_NAME = 'NDB_CUSTOMER_NEW');
UPDATE CHECK_POINT SET RUN_DATE = SYSDATE WHERE TABLE_NAME = 'NDB_CUSTOMER_NEW';
COMMIT;
END;
/
I want to know how to output the events into a table. Like Process Start Time Stamp, Process End Time Stamp & in an exception what error msg. So there will be two columns like Date and Message in the Log Table. Any suggestions?
create or replace procedure my_log (action in varchar2, message in varchar2 )
is
begin
Insert into my_log_table (ACTION, MESSAGE, EVENT_DATE)
values (action, message, sysdate);
commit;
end;
/
CREATE OR REPLACE PROCEDURE "CUSTOMER_INCREMENTAL" ()
IS
err_num NUMBER;
err_msg VARCHAR2(4000);
BEGIN
my_log ('Start','My message');
INSERT INTO NDB_AML_CUSTOMER
(ID, TITLE,...)
SELECT ID, TITLE,...
FROM NDB_CUSTOMER_NEW
WHERE DATE_TIME > (SELECT RUN_DATE FROM CHECK_POINT WHERE TABLE_NAME = 'NDB_CUSTOMER_NEW');
UPDATE CHECK_POINT SET RUN_DATE = SYSDATE WHERE TABLE_NAME = 'NDB_CUSTOMER_NEW';
COMMIT;
my_log ('End','My message');
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SQLERRM;
my_log ('Error' , errnum ||' - ' || err_msg);
END;
/
It's much easier to log to a table, as suggested in the other answer, but rather than writing your own logging procedure, use LOGGER which is well documented and tested.
Here's an example taken from the documentation:
begin
logger.log('This is a debug message. (level = DEBUG)');
logger.log_information('This is an informational message. (level = INFORMATION)');
logger.log_warning('This is a warning message. (level = WARNING)');
logger.log_error('This is an error message (level = ERROR)');
logger.log_permanent('This is a permanent message, good for upgrades and milestones. (level = PERMANENT)');
end;
/
select id, logger_level, text
from logger_logs_5_min
order by id;
ID LOGGER_LEVEL TEXT
---- ------------ ------------------------------------------------------------------------------------------
10 16 This is a debug message. (level = DEBUG)
11 8 This is an informational message. (level = INFORMATION)
12 4 This is a warning message. (level = WARNING)
13 2 This is an error message (level = ERROR)
14 1 This is a permanent message, good for upgrades and milestones. (level = PERMANENT)
Related
I am trying to write a code block where record insert if record already exist then update
table. i am trying If (sql%rowcount = 0) then but it's not working in cursor and more one records.
What I tried so far as the code block is
declare
remp_id varchar2(60);
remp_name varchar2(100);
rdesig varchar2(100);
rdept_no number;
rdesig_no number;
rdept_name varchar2(60);
cursor alfa is
select emp_code, emp_name, desig, dept_name, dept_no, desig_no
from emp
where emp_code between :first_code and :second_code;
begin
open alfa;
loop
fetch alfa
into remp_id, remp_name, rdesig, rdept_name, rdept_no, rdesig_no;
exit when alfa%notfound;
update att_reg_mo
set emp_code = remp_id,
emp_name = remp_name,
desig = rdesig,
dept_name = rdept_name,
dept_no = rdept_no,
desig_no = rdesig_no,
att_date = :att_date,
emp_att = :emp_att,
att_type = 'MA',
reg_date = :reg_date
where emp_code between :first_code and :second_code
and reg_date = :reg_date
and att_date = :att_date;
commit;
if (sql%rowcount = 0) then
insert into att_reg_mo
(emp_code,
emp_name,
desig,
dept_name,
att_date,
emp_att,
att_type,
reg_date,
dept_no,
desig_no)
values
(remp_id,
remp_name,
rdesig,
rdept_name,
:att_date,
:emp_att,
'MA',
:reg_date,
rdept_no,
rdesig_no);
end if;
commit;
end loop;
close alfa;
end;
when i am fire the trigger then record is insert but where need to update record it's update with null values
Or you could use something like that:
DECLARE
cursor test is
select 1 as v from dual
union
select 2 as v from dual;
n_var NUMBER;
BEGIN
for rec in test loop
BEGIN
select 1 into n_var from dual where rec.v=2;
DBMS_OUTPUT.PUT_LINE('Please Update Any Table');
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE('Please Insert Any Table');
END;
end loop;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ('Unexpected error');
END;
SQL%attribute always refers to the most recently run SELECT or DML statement. It refreshes as to start from zero after any of transaction statement such as COMMIT, ROLLBACK or SAVEPOINT is issued, for a session in which AUTOCOMMIT is presumed to be OFF by default. Therefore, you always get zero from SQL%ROWCOUNT which is just before the INSERT statement, and keeping inserting to the concerned table during every run of code block.
So, remove the f i r s t COMMIT, removing also keeps the atomicity of the whole transaction, from your code block.
Demo
I am doing form personalization in HR module .my requirement is when the end-user is trying to terminate than a procedure should get executed and check the condition if the is not met then it should display an error in the front end form
I am using this procedure:=
CREATE OR REPLACE PROCEDURE validate_terminate IS
u_id NUMBER := fnd_global.user_id;
e_id NUMBER;
p_id NUMBER;
l_yes VARCHAR2 (1);
null_found EXCEPTION;
BEGIN
SELECT EMPLOYEE_ID
INTO e_id
FROM fnd_user
WHERE user_id = u_id;
SELECT person_id
INTO p_id
FROM per_all_people_f
WHERE person_id = e_id;
SELECT 'Y'
INTO l_yes
FROM DUAL
WHERE EXISTS
(SELECT 'Y'
FROM pa_expenditure_items_all paei,
pa_expenditures_all pae
WHERE paei.expenditure_id = pae.expenditure_id
AND pae.incurred_by_person_id = p_id
AND paei.cost_distributed_flag = 'N');
IF l_yes = NULL THEN
dbms_output.put_line ('USER CANNOT PERFORM TERMINATE');
RAISE null_found;
END IF;
EXCEPTION
WHEN null_found THEN
dbms_output.put_line ('CONDITION IS NOT MET');
dbms_output.put_line ('CANNOT PROCESS TERMINATE');
WHEN no_data_found THEN
dbms_output.put_line ('CONDITION IS NOT MET');
dbms_output.put_line ('CANNOT PROCESS TERMINATE');
END;
The procedure is working fine but I am unable to execute it in the front end
as I am doing these below are the screenshots
[front end from][1]
[ACTION tab image][2]
but the procedure is not getting executed.
dbms_output.put_line is only in pl/sql visible if serveroutput is on.
You won't see these messages in oracle forms.
You should use message or an alert followed by
raise form_trigger_failure
I have created a procedure for updating my t_ritm table. First I have select rrcd_qnty (which is my product quantity) of a product id from t_rrcd table. Then I update the rrcd_qnty value in t_ritm table.
Here is my procedure:
procedure update_ritm_new_rate(p_oid in varchar2, p_ritm_rate in varchar2, p_euser in varchar2)
is
nrate varchar2(4);
begin
SELECT rrcd_rate into nrate
FROM (select oid, t_rrcd.rrcd_rate
from t_rrcd
where rrcd_ritm= p_oid
ORDER BY oid DESC )
WHERE rownum <= 1
ORDER BY rownum DESC ;
EXCEPTION
WHEN NO_DATA_FOUND THEN nrate := 0;
update t_ritm
set ritm_rate = nrate, euser = p_euser, edat = sysdate
where oid = p_oid;
commit;
end update_ritm_new_rate;
Some of my product id Quantity was null. so I was getting No_Data_Found error. But when and which product id has Quantity value they were successfully updating. For avoiding No_Data_Found I used EXCEPTION WHEN NO_DATA_FOUND THEN nrate := 0; which solved my no_Data_Found error. But when product id has quantity value they were not updating.
I had search lot of for this issue but not get good solution. What should be the best practice for avoiding No_Data_Found error? Could I pass my value if I don't get any No_Data_Found error?
thank in advance
That's because - if your SELECT returns something, it never reaches UPDATE as it is hidden behind the EXCEPTION handler.
Therefore, enclose it (SELECT) into its own BEGIN-END block, and put UPDATE out of it so that it is executed with whichever NRATE value is used.
PROCEDURE update_ritm_new_rate (p_oid IN VARCHAR2,
p_ritm_rate IN VARCHAR2,
p_euser IN VARCHAR2)
IS
nrate VARCHAR2 (4);
BEGIN
BEGIN --> this
SELECT rrcd_rate
INTO nrate
FROM ( SELECT oid, t_rrcd.rrcd_rate
FROM t_rrcd
WHERE rrcd_ritm = p_oid
ORDER BY oid DESC)
WHERE ROWNUM <= 1
ORDER BY ROWNUM DESC;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
nrate := 0;
END; --> this
UPDATE t_ritm
SET ritm_rate = nrate, euser = p_euser, edat = SYSDATE
WHERE oid = p_oid;
COMMIT;
END update_ritm_new_rate;
I have fixed the issue by adding EXCEPTION WHEN NO_DATA_FOUND THEN nrate := 0; after the update query.
procedure update_ritm_new_rate(p_oid in varchar2, p_ritm_rate in varchar2, p_euser in varchar2)
is
nrate varchar2(4);
begin
SELECT rrcd_rate into nrate FROM (select oid, t_rrcd.rrcd_rate from t_rrcd where rrcd_ritm= p_oid ORDER BY oid DESC )
WHERE rownum <= 1 ORDER BY rownum DESC ;
update t_ritm set ritm_rate = nrate, euser = p_euser, edat = sysdate where oid = p_oid;
commit;
EXCEPTION WHEN NO_DATA_FOUND THEN nrate := 0;
end update_ritm_new_rate;
I need to have an update and insert wrapped into a transaction that will be called from an external web application. I'm trying to get back a basic success/failure status when it is called along with an error message if it failed.
What I would like to do is something like the following, but it gives me the following errors:
INTO clause is expected in this SELECT statement
"SQLCODE": invalid identifier
DECLARE STATUS VARCHAR2(128);
MESSAGE VARCHAR2(128);
BEGIN
UPDATE MYTABLE
SET COL1 = 400
WHERE USERNAME = 'bigtunacan' AND pk = 12345;
INSERT INTO MYTABLE (username, col1, col2)
VALUES('bigtunacan', 400, 'foo');
SELECT 'TRUE' AS STATUS, '' AS MSG FROM MYTABLE WHERE ROWNUM = 1;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
SELECT 'FALSE' AS STATUS, SQLCODE || SQLERRM AS MSG FROM MYTABLE WHERE ROWNUM = 1;
END;
Any Select statement inside a PL/SQL code needs an INTO clause, except the ones called from or within a cursor. In your case, You do not need to invoke any Select statement, but just assign static string values ('TRUE','FALSE') or pseudocolumns independent from SQL such as sqlcode or sqlerrm to your already defined variables.
So, consider using :
DECLARE
STATUS VARCHAR2(128) := 'TRUE';
MESSAGE VARCHAR2(128);
BEGIN
UPDATE MYTABLE
SET COL1 = 400
WHERE USERNAME = 'bigtunacan' AND pk = 12345;
INSERT INTO MYTABLE (username, col1, col2)
VALUES('bigtunacan', 400, 'foo');
-- SELECT 'TRUE' AS STATUS, '' AS MSG FROM MYTABLE WHERE ROWNUM = 1;
-- completely remove this above row, STATUS is already initialized as TRUE
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
STATUS := 'FALSE';
RAISE_APPLICATION_ERROR(-20333,'Caution : An error was encountered -
'||SQLCODE||' -ERROR- '||SQLERRM);
END;
A Commit/Rollback should not be ideally included inside a called procedure. From Tom Kyte's own words:
I wish PLSQL didn't support commit/rollback. I firmly believe transaction control MUST be done at the topmost, invoker level.
You should consider converting your anonymous block into a procedure and define the transaction control in the invoker's code.
CREATE OR REPLACE procedure yourprocedure
( p_status OUT VARCHAR2,
p_message OUT VARCHAR2
) AS
BEGIN
UPDATE mytable
SET
col1 = 400
WHERE username = 'bigtunacan' AND pk = 12345;
INSERT INTO MYTABLE (username, col1, col2)
VALUES('bigtunacan', 400, 'foo');
p_status := 'TRUE' ;
p_message := NULL;
EXCEPTION
WHEN OTHERS THEN
p_status := 'FALSE' ;
p_message := SQLERRM ;
END;
/
Invocation ( May be another block, procedure or application layer )
DECLARE
l_status VARCHAR2(20);
l_message VARCHAR2(400);
BEGIN
yourprocedure(l_status,l_message);
IF
l_status = 'TRUE'
THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END;
/
Only exception is if it's defined as an Autonomous procedure (mostly used for logging purposes) where you are supposed to commit inside the procedure.
I am running many procedures parallel through java thread code. I have used exception handling in my procedures in order to catch any error results. When i see java debugger log i can see few of the procedures throws an error ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired. I am using few tables which are in common and used by other procedures as well. I dont know the reason why this issue is comming.
PROCEDURE "EXT_10024_ACTIVATE_OPTION"(IN_KPI_DEF_ID IN NUMBER DEFAULT 0) AS
IN_EVENT_ID NUMBER;
err_code VARCHAR(100);
err_msg VARCHAR(100);
IN_OBJECT_NAME VARCHAR2(100);
CURSOR KPI_DEF_CUR IS
Select KPI_DEF_ID,BUSINESS_CHECK_PERIOD_ID,BUS_CHK_PRD_ID_1,
CASE WHEN BUSINESS_CHECK_PERIOD_UNIT_ID=11 THEN 'MINUTE'
WHEN BUSINESS_CHECK_PERIOD_UNIT_ID=12 THEN 'HOUR'
WHEN BUSINESS_CHECK_PERIOD_UNIT_ID=13 THEN 'DAY'
WHEN BUSINESS_CHECK_PERIOD_UNIT_ID IS NULL THEN 'MINUTE'
END AS BUSINESS_CHECK_PERIOD_UNIT_ID,
CASE WHEN BUSINESS_CHK_PERIOD_VAL IS NULL THEN 0
ELSE BUSINESS_CHK_PERIOD_VAL END AS BUSINESS_CHK_PERIOD_VAL,
CASE WHEN BUS_CHK_PRD_UNIT_ID_1=11 THEN 'MINUTE'
WHEN BUS_CHK_PRD_UNIT_ID_1=12 THEN 'HOUR'
WHEN BUS_CHK_PRD_UNIT_ID_1=13 THEN 'DAY'
WHEN BUS_CHK_PRD_UNIT_ID_1 IS NULL THEN 'MINUTE'
END AS BUS_CHK_PRD_UNIT_ID_1,
CASE WHEN BUS_CHK_PRD_VAL_1 IS NULL THEN 0
ELSE BUS_CHK_PRD_VAL_1 END AS BUS_CHK_PRD_VAL_1,
EVENT_ID FROM RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION where KPI_DEF_ID = IN_KPI_DEF_ID;
BEGIN
--delete the data from TEMP_SERVICE_OPTION and TEMP_SERVICE_OPTION_EXTRACTION
EXECUTE IMMEDIATE 'TRUNCATE TABLE TEMP_ACTIVATE_OPTION';
EXECUTE IMMEDIATE 'TRUNCATE TABLE TEMP_SERVICE_OPTION_EXTRACTION';
EXECUTE IMMEDIATE 'TRUNCATE TABLE TEMP_SERVICE_OPTION';
DELETE FROM CAPTURED_DATA_ERROR WHERE EVENT_TIMESTAMP < SYSDATE - 60 and EVENT_ID=10024;
-- removed, retrieve a new START_ID from source first, don't use the last id.
-- SELECT LAST_TASK_ID INTO LAST_SO_ID FROM CAPTURING where DB_TABLE='TEMP_SERVICE_OPTION';
--SELECT MIN(SO.ID) INTO LAST_SO_ID FROM SERVICE_OPTION#FONIC_RETAIL SO WHERE SO.ID >= to_char(SYSDATE -1, 'YYYYMMDDHH24MISS')||'0000';
Select EVENT_ID INTO IN_EVENT_ID FROM RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION where KPI_DEF_ID = IN_KPI_DEF_ID;
FOR KPI_DEF_ROW IN KPI_DEF_CUR
LOOP
BEGIN
INSERT INTO TEMP_ACTIVATE_OPTION(ID,ICC,ASSIGNED_ANUMBER_ID,SERVICE_ID,PRODUCT_OPTION_ID,STATUS_ID,END_DATE,PRODUCT_TYPE_KEY)
Select DISTINCT(SO.ID),SIM.ICC,SIM.ASSIGNED_ANUMBER_ID,SO.SERVICE_ID,SO.PRODUCT_OPTION_ID,SO.STATUS_ID,SO.END_DATE,SIM.PRODUCT_TYPE_KEY FROM
SIMCARD#FONIC_RETAIL SIM
JOIN SERVICE_OPTION#FONIC_RETAIL SO ON SO.SERVICE_ID=SIM.ASSIGNED_TO_SERVICE_ID
where SO.STATUS_ID IN (20,40)
and SO.ID < to_char(SYSDATE - numtodsinterval ( KPI_DEF_ROW.BUSINESS_CHK_PERIOD_VAL,KPI_DEF_ROW.BUSINESS_CHECK_PERIOD_UNIT_ID ), 'YYYYMMDDHH24MISS')||'0000'
and SO.ID > to_char(SYSDATE - numtodsinterval ( KPI_DEF_ROW.BUS_CHK_PRD_VAL_1, KPI_DEF_ROW.BUS_CHK_PRD_UNIT_ID_1 ), 'YYYYMMDDHH24MISS')||'0000'
and NOT EXISTS(SELECT ID from TEMP_ACTIVATE_OPTION T WHERE T.ID = SO.ID );
EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND exception in EXT_10024_ACTIVATE_OPTION - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID));
RAISE;
END;
commit;
BEGIN
INSERT INTO TEMP_SERVICE_OPTION_EXTRACTION(ID,ICC,ASSIGNED_ANUMBER_ID,SERVICE_ID,PRODUCT_OPTION_ID,STATUS_ID,END_DATE,A_NUMBER,PRODUCT_TYPE_KEY)
Select DISTINCT(SO.ID),SO.ICC,SO.ASSIGNED_ANUMBER_ID,SO.SERVICE_ID,SO.PRODUCT_OPTION_ID,SO.STATUS_ID,SO.END_DATE,AN.A_NUMBER,SO.PRODUCT_TYPE_KEY FROM
TEMP_ACTIVATE_OPTION SO JOIN
PRODUCT_OPTION#FONIC_RETAIL PO ON SO.PRODUCT_OPTION_ID = PO.ID JOIN
PRODUCT_CONFIG#FONIC_RETAIL PC ON PO.OPTION_KEY=PC.DEFAULT_PRODUCT_OPTIONS
JOIN PRODUCT_TYPE#FONIC_RETAIL PT ON PC.ID = PT.PRODUCT_CONFIG_ID
JOIN TEMP_ACTIVATE_OPTION SO ON SO.PRODUCT_TYPE_KEY=PT.KEY
JOIN
A_NUMBER#FONIC_RETAIL AN ON SO.ASSIGNED_ANUMBER_ID = AN.ID
where SO.STATUS_ID IN (20,40)
and NOT EXISTS(SELECT ID from TEMP_SERVICE_OPTION_EXTRACTION T WHERE T.ID = SO.ID );
EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND exception in EXT_10024_ACTIVATE_OPTION - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID));
RAISE;
END;
commit;
BEGIN
--SELF_REGISTRATION ACTIVATE OPTION
INSERT INTO TEMP_SERVICE_OPTION(ID,SERVICE_ID,PRODUCT_OPTION_ID,STATUS_ID,EVENT_TIMESTAMP,END_DATE,EVENT_ID,SUBSCRIPTION_ID,ORDER_NUMBER,A_NUMBER)
Select DISTINCT(SO.ID),SO.SERVICE_ID,SO.PRODUCT_OPTION_ID,SO.STATUS_ID,to_date(substr(SO.ID, 1, 14), 'YYYYMMDDHH24MISS'),SO.END_DATE,
IN_EVENT_ID
,TSM.SUBSCRIPTION_ID,TSM.ORDER_NUMBER,SO.A_NUMBER
from TEMP_SERVICE_OPTION_EXTRACTION SO JOIN TMP_SOAP_MONITORING_IDS TSM
ON SO.A_NUMBER = TSM.MSISDN
where SO.STATUS_ID IN (20,40) and TSM.ORDER_TYPE='SELF_REGISTRATION' and
TSM.CREATE_DATE < SYSDATE - numtodsinterval ( KPI_DEF_ROW.BUSINESS_CHK_PERIOD_VAL,KPI_DEF_ROW.BUSINESS_CHECK_PERIOD_UNIT_ID )
and TSM.CREATE_DATE > SYSDATE - numtodsinterval ( KPI_DEF_ROW.BUS_CHK_PRD_VAL_1, KPI_DEF_ROW.BUS_CHK_PRD_UNIT_ID_1 )
and NOT EXISTS(SELECT ID from TEMP_SERVICE_OPTION T WHERE T.ID = SO.ID )
and TSM.WEB_SERVICE_NAME ='RatorWebShopService' and TSM.WEB_METHOD_NAME ='placeShopOrder';
EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND exception in EXT_10024_ACTIVATE_OPTION - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID));
RAISE;
END;
END LOOP;
commit;
--INSERT TEMP DATA INTO CAPTURED_DATA_01 TABLE
Insert into CAPTURED_DATA_01(SUBSCRIPTION_ID,ENV_ID,BRAND_ID,BP_ID,EVENT_ID,ORDER_ID,STATUS_DESCRIPTION,STATUS_CODE,EVENT_TIMESTAMP)
Select DISTINCT(DCR.SUBSCRIPTION_ID),BBE.ENV_ID,TSM.BRAND_ID,BBE.BP_ID,DCR.EVENT_ID,
DCR.ORDER_NUMBER,
CASE WHEN DCR.STATUS_ID=20 THEN 'OK'
WHEN DCR.STATUS_ID=40 THEN 'ERROR'
END,DCR.STATUS_ID,
DCR.EVENT_TIMESTAMP from TEMP_SERVICE_OPTION DCR JOIN TMP_SOAP_MONITORING_IDS TSM ON TSM.SUBSCRIPTION_ID=DCR.SUBSCRIPTION_ID
JOIN
RATOR_MONITORING_CONFIGURATION.ENV_BRAND_BP_EVENT BBE ON BBE.EVENT_ID = DCR.EVENT_ID JOIN
RATOR_MONITORING_CONFIGURATION.ENVIRONMENT ENV on BBE.ENV_ID=ENV.ENV_ID
JOIN RATOR_MONITORING_CONFIGURATION.BRAND BR ON BBE.BRAND_ID = BR.BRAND_ID
JOIN RATOR_MONITORING_CONFIGURATION.BUSINESS_PROCESS BP ON BBE.BP_ID = BP.BP_ID
AND NOT EXISTS(SELECT CD.SUBSCRIPTION_ID FROM CAPTURED_DATA_01 CD WHERE CD.EVENT_ID = DCR.EVENT_ID AND CD.SUBSCRIPTION_ID = DCR.SUBSCRIPTION_ID);
EXCEPTION WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
DBMS_OUTPUT.PUT_LINE('OTHERS exception in EXT_10072_REQ_SENT_SPAIN - KPI_DEF_ID:'||to_char(IN_KPI_DEF_ID) || err_code || '----' || err_msg || 'OBJECT_NAME->');
RAISE;
COMMIT;
END EXT_10024_ACTIVATE_OPTION;
The only thing in your code that can cause this is the TRUNCATE.
TRUNCATE is not DML. It's a DDL operation. It acquires a full table lock. Because you are doing some DML in other sessions (inserting particular rows), the session performing TRUNCATE cannot acquire the table lock. Somewhere internally NOWAIT is specified, so the exception is raised.
I believe you should reconsider using TRUNCATE here. It is DDL, it performs commit so it's not transactional. Obviously, it is not safe to use it in multi user environment.
You could use TEMPORARY TABLES. All the data you store in them only exists in your current session. This way you don't need to use TRUNCATE.
DDL will look something like this.
CRATE GLOBAL TEMPORARY TABLE TEMP_ACTIVATE_OPTION(
ID NUMBER,
... -- your columns
)
ON COMMIT DELETE ROWS;
TRUNCATE TABLE is a DDL command, and if unable to lock the table to perform the truncate, Oracle will raise ORA-00054. So if one session is using the table, another session cannot truncate it.