PLSQL - exception in a procedure - oracle

Use exception in a procedure.
Procedure for insert into statement.
CREATE OR REPLACE PROCEDURE pSaveProductGroup (p_parentCode VARCHAR2, p_nameGroup VARCHAR2) IS
v_var "ProductGroups"."code"%type;
BEGIN
select p."code" into v_var
from "ProductGroups" p
where p."code"=p_parentCode;
if v_var is not null then
INSERT INTO "ProductGroups"
("parentCode","nameGroup")
VALUES(p_parentCode,p_nameGroup);
end if;
EXCEPTION
WHEN v_var is null then
dbms_output.put_line('Undefined group.');
END;
It should print exception when needed.
Error: Error(18,12): PLS-00103: Encountered the symbol "IS" when expecting one of the following: . then or

You can do something like this to catch the exception.
CREATE OR REPLACE PROCEDURE pSaveProductGroup (p_parentCode VARCHAR2,
p_nameGroup VARCHAR2)
IS
v_var "ProductGroups"."code"%TYPE;
myex EXCEPTION;
PRAGMA EXCEPTION_INIT (myex, -20016);
BEGIN
SELECT p."code"
INTO v_var
FROM "ProductGroups" p
WHERE p."code" = p_parentCode;
IF v_var IS NOT NULL
THEN
INSERT INTO "ProductGroups" ("parentCode", "nameGroup")
VALUES (p_parentCode, p_nameGroup);
ELSE
IF (v_var IS NULL)
THEN
RAISE myex;
END IF;
END IF;
EXCEPTION
WHEN myex
THEN
DBMS_OUTPUT.put_line (
'ERROR_STACK: "Undefined group --> ' || DBMS_UTILITY.format_error_stack);
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (
'ERROR_STACK: NO_DATA_FOUND --> ' || DBMS_UTILITY.format_error_stack);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'ERROR_STACK: OTHERS --> ' || DBMS_UTILITY.format_error_stack);
END;
The modified version of the procedure
CREATE OR REPLACE PROCEDURE pSaveProductGroup (p_parentCode VARCHAR2,
p_nameGroup VARCHAR2)
IS
v_var "ProductGroups"."code"%TYPE;
myex EXCEPTION;
PRAGMA EXCEPTION_INIT (myex, -20016);
BEGIN
SELECT p."code"
INTO v_var
FROM "ProductGroups" p
WHERE p."code" = p_parentCode;
IF v_var IS NOT NULL
THEN
INSERT INTO "ProductGroups" ("parentCode", "nameGroup")
VALUES (p_parentCode, p_nameGroup);
ELSE
RAISE myex;
END IF;
EXCEPTION
WHEN myex
THEN
DBMS_OUTPUT.put_line (
'ERROR_STACK: Undefined group --> ' || DBMS_UTILITY.format_error_stack);
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (
'ERROR_STACK: NO_DATA_FOUND --> ' || DBMS_UTILITY.format_error_stack);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'ERROR_STACK: OTHERS --> ' || DBMS_UTILITY.format_error_stack);
END;

Related

how to catch the error of execute immediate (open for)?

I have this procedure:
PROCEDURE proc_with_cursor( P_PARAM1_IN NUMBER, P_PARAM2_IN NUMBER, P_CURSOR_OUT OUT SYS_REFCURSOR)
IS
v_sql VARCHAR2 (32767);
v_script VARCHAR2 (32767);
v_bind_vars VARCHAR2 (32767);
BEGIN
v_sql := 'BEGIN OPEN :1 FOR :2 ';
v_bind_vars := P_PARAM1_IN||', '||P_PARAM2_IN;
v_sql := v_sql||' USING '||v_bind_vars||'; ';
--tried also following but also couldn't catch the error!
--v_sql := v_sql ||'EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(''error: ''||SQLCODE||'' - ''||SQLERRM); END;';
v_sql := v_sql||' END;';
v_script := 'select sysdate from dual where 1= :bind_first and 2 = :bindsecond';
EXECUTE IMMEDIATE v_sql using P_CURSOR_OUT, v_script;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error: '||SQLCODE||' - '||SQLERRM); -- this part is not catching the error!!!!!
END;
Sometimes, the script will throw an error like:
ORA-12847: retry parsing due to concurrent DDL operation
[Error] Execution (1: 1): ORA-12847: retry parsing due to concurrent DDL operation
My question is: how to catch that error?
You cannot bind object names (e.g. cursor names) and variable names into dynamic SQL, only values. I think this may do what you intend:
PROCEDURE proc_with_cursor( p_param1_in NUMBER, p_param2_in NUMBER, p_cursor_out OUT SYS_REFCURSOR)
IS
v_script VARCHAR2 (32767);
BEGIN
v_script := 'select sysdate from dual where 1= :bind_first and 2 = :bindsecond';
OPEN p_cursor_out FOR v_script USING p_param1_in, p_param2_in;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('error: '||sqlcode||' - '||sqlerrm);
END;
I don't understand your problem. If you have this procedure
CREATE OR REPLACE PROCEDURE proc_with_cursor( p_param1_in NUMBER, p_param2_in NUMBER, p_cursor_out OUT SYS_REFCURSOR)
IS
v_script VARCHAR2 (32767);
BEGIN
v_script := 'select sysdate fromM dual where 1= :bind_first and 2 = :bindsecond';
OPEN p_cursor_out FOR v_script USING p_param1_in, p_param2_in;
END;
Then you get this:
DECLARE
cur SYS_REFCURSOR;
BEGIN
proc_with_cursor(1, 2, cur);
end;
/
Error at line 1
ORA-00923: FROM keyword not found where expected
ORA-06512: at "xxx.PROC_WITH_CURSOR", line 6
ORA-06512: at line 4
What else would you like to get? Your (poor) code is working:
CREATE OR REPLACE PROCEDURE proc_with_cursor( P_PARAM1_IN NUMBER, P_PARAM2_IN NUMBER, P_CURSOR_OUT OUT SYS_REFCURSOR) IS
v_sql VARCHAR2 (32767);
v_script VARCHAR2 (32767);
v_bind_vars VARCHAR2 (32767);
BEGIN
v_sql := 'BEGIN OPEN :1 FOR :2 ';
v_bind_vars := P_PARAM1_IN||', '||P_PARAM2_IN;
v_sql := v_sql||' USING '||v_bind_vars||'; ';
v_sql := v_sql||' END;';
v_script := 'select sysdate fromm dual where 1= :bind_first and 2 = :bindsecond';
EXECUTE IMMEDIATE v_sql USING P_CURSOR_OUT, v_script;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error: '||SQLCODE||' - '||SQLERRM);
END;
DECLARE
cur SYS_REFCURSOR;
BEGIN
proc_with_cursor(1,2, cur);
END;
Prints error: -923 - ORA-00923: FROM keyword not found where expected on the DBMS_OUTPUT.
If you like to get the exception then do
CREATE OR REPLACE PROCEDURE proc_with_cursor( P_PARAM1_IN NUMBER, P_PARAM2_IN NUMBER, P_CURSOR_OUT OUT SYS_REFCURSOR) IS
v_sql VARCHAR2 (32767);
v_script VARCHAR2 (32767);
v_bind_vars VARCHAR2 (32767);
BEGIN
...
EXECUTE IMMEDIATE v_sql USING P_CURSOR_OUT, v_script;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error: '||SQLCODE||' - '||SQLERRM);
RAISE;
END;

how can i substr in oracle procedure

this is my procedure:
create or replace PROCEDURE testsub(factTName IN VARCHAR2)
IS
v_in_char VARCHAR2(100):='id,name,age,cjrq';
v_result VARCHAR2(200) :='';
begin
-- split v_in_char,expect cjrq
-- i want result like t.uuid=uuid and t.uuname=uuname and t.uuage=uuage
SYS.DBMS_OUTPUT.PUT_LINE(v_result);
end;
maybe something like this:
select substr(v_in_char,instr(v_in_char,',',1,3)+1) into v_result
from dual;
create or replace PROCEDURE testsub(factTName IN VARCHAR2)
IS
v_primy_keys VARCHAR2(200) :='';
cursor primy_key is
select field_en_name from BASE_FIELD_INFO where base_rpt_id=lower(factTName) and primy_key='true';
primy_key_row primy_key%ROWTYPE;
begin
for primy_key_row in primy_key loop
IF primy_key_row.field_en_name='CJRQ' THEN
DBMS_OUTPUT.PUT_LINE('');
ELSE
v_primy_keys:=v_primy_keys||'t.'||primy_key_row.field_en_name||'='||primy_key_row.field_en_name||' ';
END IF;
v_primy_keys:=v_primy_keys||' and ';
end loop;
v_primy_keys:=substr(v_primy_keys,1,length(v_primy_keys)-4);
dbms_output.put_line(v_primy_keys);
end;

Oracle Procedure compile error

Bellow is my procedure.
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;
/
When I compile it gives the error PLS-00103: Encountered the symbol ")" when expecting one of the following: current delete exists prior. Any suggestions?
You do not need () if function or procedure has no parameters.

Dynamic SQL and Bulk Insert

I want to use the execute immediate command, to insert collection below PROCEDURE
CREATE OR REPLACE PROCEDURE P_LOAD_HLD(
p_app_name IN VARCHAR2,
p_filename IN VARCHAR2,
p_rectype IN VARCHAR2,
p_tabname IN VARCHAR2,
o_status OUT Number)
IS
type t_tab is table of holding_template%rowtype;
v_tab t_tab;
process_size number := 10000;
dummy_cursor SYS_REFCURSOR;
BEGIN
o_status := 0;
null;
if p_rectype='my_test' THEN
OPEN dummy_cursor FOR
select *
from TAB_staging a
where a.record_type = p_filename;
end if;
LOOP
BEGIN
FETCH dummy_cursor BULK COLLECT INTO V_TAB LIMIT PROCESS_SIZE;
FORALL I IN V_TAB.FIRST .. V_TAB.LAST
execute immediate 'insert into '||p_tabname||' values v_tab(i))';
EXCEPTION WHEN OTHERS THEN
FOR I IN 1 .. V_TAB.COUNT
LOOP
BEGIN
EXECUTE IMMEDIATE ' INSERT INTO '||p_tabname || ' VALUES ( '||
'v_tab(i).k0,v_tab(i).k1,v_tab(i).k2,v_tab(i).k3,v_tab(i).k4';
COMMIT;
EXCEPTION WHEN OTHERS THEN
RAISE;
END;
END LOOP;
END;
END LOOP;
END P_LOAD_HLD ;
this gives me the error message.
[Error] PLS-00435 (742: 7): PLS-00435: DML statement without BULK
In-BIND cannot be used inside FORALL

ORA-06530: Reference to uninitialized composite

When I am executing the package I get an error message:
error in the emp_test ORA-06530: Reference to uninitialized composite
Can u explain how I can initialized an object type in a package?
CREATE OR REPLACE TYPE emp_obj AS OBJECT
(
emp_no number,
salary number,
job varchar2(20)
);
CREATE OR REPLACE PACKAGE BODY emp_dummy_pk IS
PROCEDURE emp_test IS
CURSOR emp_cur IS
SELECT empno, sal, job FROM emp;
l_emp_no emp_obj;
BEGIN
FOR emp_rec IN emp_cur LOOP
l_emp_no.emp_no := emp_rec.empno;
l_emp_no.salary := emp_rec.sal;
l_emp_no.job := emp_rec.job;
BEGIN
emp_pk.emp_chk( p_emp_no => l_emp_no );
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line( 'error in the emp_pk.emp_no ' || SQLERRM );
END;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line( 'error in the emp_test ' || SQLERRM );
END;
END;
BEGIN
emp_dummy_pk.emp_test;
END;
You can initialize it using the constructor:
l_emp_no := NEW emp_obj( emp_rec.empno, emp_rec.sal, emp_rec.job );

Resources