Anonymous PL/SQL block checked exception - plsql

I'm trying to catch an exception within my anonymous PL/SQL block
DECLARE
...
BEGIN
FOR herstell_row IN (
...
)
LOOP
...
DECLARE
table_does_not_exists exception;
pragma exception_init( table_does_not_exists, -942 );
BEGIN
INSERT INTO SMART_MONITORING_MACHINE_NAV_B (
MACHINE,
NAVIGATION_LEVEL_ID
)
SELECT
old_binding.MACHINE,
pv_id
FROM
SMART_MACHINE_NAV_BINDING old_binding
WHERE
old_binding.NAVIGATION_LEVEL_ID = herstell_row.HENAME1;
EXCEPTION
WHEN table_does_not_exists THEN null;
END;
END LOOP;
END;
I know the table SMART_MACHINE_NAV_BINDING doesn't exist in my case, so I need the nested anonymous block to ignore its code. But I always get this error:
Error report -
ORA-06550: line 41, column 14:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 33, column 10:
PL/SQL: SQL Statement ignored

You can't compile code with non-existent table, but you can try to execute it using EXECUTE EMMEDIATE:
DECLARE
...
BEGIN
FOR herstell_row IN (
...
)
LOOP
...
DECLARE
table_does_not_exists exception;
pragma exception_init( table_does_not_exists, -942 );
BEGIN
execute immediate
'INSERT INTO SMART_MONITORING_MACHINE_NAV_B (
MACHINE,
NAVIGATION_LEVEL_ID
)
SELECT
old_binding.MACHINE,
pv_id
FROM
SMART_MACHINE_NAV_BINDING old_binding
WHERE
old_binding.NAVIGATION_LEVEL_ID = :P' using herstell_row.HENAME1;
EXCEPTION
WHEN table_does_not_exists THEN null;
END;
END LOOP;
END;
Also you don't need exceptions here, you can check existence of a table using system view:
declare
table_created number;
begin
select count(*)
into table_created
from all_tables
where table_name = ...
and owner = ...;
if table_created > 0 then
execute immediate 'insert into ...';
end if;
end;
More information about EXECUTE IMMEDIATE statement: http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/executeimmediate_statement.htm#LNPLS01317

Oracle does not know this error table_does_not_exists it is user defined, so you should handle in when others then, for eg.
Exception
When Others then
null;
-- or at this time you can raise your error table_does_not_exists
raise table_does_not_exists;
-- and handle it in another parent block
end;
Exception
when table_does_not_exists then
null;
end;

Related

Returning table results from a dynamic PL/SQL query

Trying to dynamically generate and execute a PL/SQL statement. It doesn't return results, but executing okay. What I am trying is to get the table name from the schema in first statement (got it right!), and append that to a select statement, and then execute it to return the table results.
DECLARE
LATEST_TABLE VARCHAR2(256);
PostalCode ADM.POSTAL_CODE_201801%ROWTYPE;
BEGIN
SELECT TO_CHAR(max(table_name)) INTO LATEST_TABLE FROM all_tables WHERE owner = 'ADM' AND table_name LIKE 'POSTAL_CODE_%';
LATEST_TABLE := 'begin Select POSTALCODE,LONGITUDE,LATITUDE,MUNICIPALITY_FULL_NAME,LOCAL_NAME,SZONE_NAME,ZONE_NAME,RHA_CODE,RHA_NAME,URBAN,ZONE_RURAL from ADM.'||LATEST_TABLE||' ;end;';
execute immediate LATEST_TABLE into PostalCode;
Exception
When others then
Null;
END;
Why am I not getting any results? Adding
dbms_output.put_line(PostalCode.LONGITUDE || PostalCode.LATITUDE); after execute immediate is also not generating results!
I see a couple of issues here; your code is something like:
declare
vSQL varchar2(1000);
vTabName varchar2(30);
vResult number;
begin
select table_name into vTabName from user_tables;
vSQL := 'begin select a from ' || vTabName || '; end;';
execute immediate vSQL into vResult;
dbms_output.put_line('REsult: ' || vResult);
exception
when others then
null
end;
If you run this, you see nothing, because the dynamic part gives error, but the (dangerous) exception handling hides it; if you would edit the null; into something like
dbms_output.put_line('Error: ' || sqlerrm);
you would get:
Error: ORA-06550: line 1, column 7:
PLS-00428: an INTO clause is expected in this SELECT statement
In fact you dynamic code is like
begin select a from someTable; end;
and this gives error.
A way to do what you need could be:
...
vSQL := 'select a from ' || vTabName;
execute immediate vSQL into vResult;
...

Oracle - drop synonym IF EXISTS

Using MSSQL - I can drop synonym only if it exist:
DROP SYNONYM (Transact-SQL)
But in Oracle (11g) drop synonym causes my script to error if it doesn't exit, is there a way to mimic the MSSQL it exist?
You can use a PLSQL anonymous block:
begin
execute immediate 'drop synonym YOUR_SYNONYM';
exception
when others then
if sqlcode != -1434 then
raise;
end if;
end;
/
It will drop your synonym if it exists. If it doesn't exist, it will just suppress the error. It will raise any error other than "synonym does not exist" to the caller.
Apparently you can write: CREATE OR REPLACE SYNONYM
You can use a pragma to define an exception which you can then handle.
Assuming you are doing something in a loop...
declare
NOSYN exception;
pragma exception_init ( NOSYN, -1434 );
/* 1434 is the Oracle error for synonym does not exist */
begin
/*
* Loop here where you synonym name gets assigned to the variable mysyn
*/
begin
execute immediate 'drop synonym '||mysyn;
exception
when NOSYN then
dbms_output.put_line( 'Synonym does not exist... skipping' );
end;
end loop;
end;
/

Rollback an entire block while executing the rest in plsql

I have a package which is executing different inserts and updates for job position and location tables.Something like :
Create or replace package body pack_name
as
procedure proc
as
----Posistion Block
Begin
Begin
insert into xx_pos_table
select *
from xx_i_pos_table;
exception when others then
end;
Begin
insert into xx_pos_tl_table
select * from xx_i_pos_tl_table;
exception when others then
end;
Begin
Update xx_pos_extra
set err_msg =Null
exception when others then
end;
end;
---Job block
Begin
Update xx_job_extra
set err_msg =Null
exception when others then
end;
-- Loc block
Begin
Update xx_loc_extra
set err_msg =Null
exception when others then
end;
end;
end;
Now i want that if in position block for example there is an error while insertin data in xx_pos_extra then only position block should be rolled back and data from xx_pos_table,xx_pos_tl_table and xx_pos_extra should not be entered. But the rest of the blocks (Job and location)should be executed.
Create a savepoint to rollback to if an exception occurs like this:
---Job block
begin
SAVEPOINT p_rollback;
Update xx_job_extra
set err_msg =Null
exception when others then
rollback to p_rollback;
end;
-- Loc block

"Identifier must be declared" when using a function

I have the following function in a package body:
FUNCTION valida_salario(p_salary IN employees.salary%TYPE,
p_department_id IN employees.department_id%TYPE)
RETURN BOOLEAN IS
v_prom_depto NUMBER;
v_var_depto NUMBER;
BEGIN
SELECT AVG(salary), VARIANCE(SALARY) INTO v_prom_depto, v_var_depto
FROM employees
WHERE department_id=p_department_id;
-- GROUP BY department_id;
IF p_salary < v_prom_depto + 3* sqrt(v_var_depto) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END valida_salario;
And when I am using the function in a stored procedure (the procedure is in the body too), it show errors:
PROCEDURE crea_empleado(p_last_name IN employees.last_name%TYPE,
p_first_name IN employees.first_name%TYPE,
p_email IN employees.email%TYPE,
p_hire_date IN employees.hire_date%TYPE,
p_job_id IN employees.job_id%TYPE,
p_department_id IN employees.department_id%TYPE
DEFAULT 80,
p_resultado OUT NUMBER) AS
e_salario_no_valido EXCEPTION;
BEGIN
IF valida_salario(p_salary, p_department_id) THEN // Here is located the errors
NULL;
ELSE
RAISE e_salario_no_valido;
END IF;
INSERT INTO employees(employee_id, last_name, first_name, email, hire_date, job_id)
VALUES (emp_seq.NEXTVAL, p_last_name, p_first_name, p_email, p_hire_date, p_job_id);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
p_resultado := 2;
dbms_output.put_line('Datos duplicados');
WHEN e_salario_no_valido THEN
p_resultado := 1;
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
ROLLBACK;
END crea_empleado;
The following errors are :
PL/SQL: Statement ignored and
PLS-00201: the identifier 'P_SALARY' must be declared
But I can't see the error in my function, so I don't understand why it shows these errors.
Thanks in advance for your help
You need to pass p_salary into your crea_empleado() procedure. p_department_id is there but no p_salary.

PL/SQL: ORA-00942: table or view does not exist

Am getting this error 'PL/SQL: ORA-00942: table or view does not exist' in Oracle 11G when I try to runt his portion of my script. It seems the select statement isn't parsing the name of the variable from the cursor. Need help to ensure this can read the table name variable from the cursor.
DECLARE
ITEM_ERROR NUMBER;
CNT_SITE VARCHAR2(46);
CURSOR C_SITEID IS
SELECT OBJECTNAME,ATTRIBUTENAME FROM MAXATTRIBUTE WHERE ATTRIBUTENAME LIKE 'SITE%' GROUP BY OBJECTNAME,ATTRIBUTENAME, COLUMNNAME;
SITEIDRec C_SITEID%RowType;
BEGIN
BEGIN
OPEN C_SITEID;
LOOP
FETCH C_SITEID into SITEIDRec;
EXIT WHEN C_SITEID %NOTFOUND;
BEGIN
SELECT COUNT(SITEID) into CNT_SITE FROM SITEIDRec.OBJECTNAME
WHERE SITEID IN ('COLLEGE NANO SCI ENG-TGCM','FREESCALE-BALAZS','TGCM-GLOBAL FOUNDRIES','INTL RECTIFIER-TGM','TGCM-DMOS5','TGCM-IMFT','TGCM-TRIQUINT','GP-TRIQUINT');
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END LOOP;
--COMMIT;
CLOSE C_SITEID;
--COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
--COMMIT;
EXCEPTION
WHEN OTHERS THEN
MSG_TEXT := SUBSTR(SQLERRM,1,200);
--COMMIT;
raise;
END;
I think you have FROM TableName missing in your query and hence it's rightly complaining.
SELECT COUNT(SITEID) into SITEIDRec.OBJECTNAME
WHERE SITEID IN
('COLLEGE NANO SCI ENG-TGCM','FREESCALE-BALAZS',
'TGCM-GLOBAL FOUNDRIES','INTL RECTIFIER-TGM','TGCM-DMOS5',
'TGCM-IMFT','TGCM-TRIQUINT','GP-TRIQUINT');
Please correct your query by adding the From TableName.
EDIT: Try using EXECUTE IMMEDIATE as below
EXECUTE IMMEDIATE 'SELECT COUNT(SITEID) into CNT_SITE FROM '
|| SITEIDRec.OBJECTNAME ||
' WHERE SITEID IN (''COLLEGE NANO SCI ENG-TGCM'',''FREESCALE-BALAZS'',
''TGCM-GLOBAL FOUNDRIES'',''INTL RECTIFIER-TGM'',''TGCM-DMOS5'',
''TGCM-IMFT'',''TGCM-TRIQUINT'',''GP-TRIQUINT'')';

Resources