sql exception handling - sql

CREATE OR REPLACE PROCEDURE p_createLocaltable
IS
table_already_exist EXCEPTION;
PRAGMA EXCEPTION_INIT (table_already_exist, -00955);
BEGIN
create table local_table as
select * from supplied_table
where rownum < 1;
EXCEPTION
when table_already_exist then
DBMS_OUTPUT.put_line('Table already exists , does not need to recreate it');
END;
can anyone see any problem of the above code?

You cannot do DDL in a PL/SQL block like that. You'll need to use execute immediate.
You would need to do it like this
CREATE OR REPLACE PROCEDURE p_createLocaltable
IS
table_already_exist EXCEPTION;
PRAGMA EXCEPTION_INIT (table_already_exist, -00955);
BEGIN
execute immediate 'create table local_objects as select * from all_objects where 1=0';
EXCEPTION
when table_already_exist then
DBMS_OUTPUT.put_line('Table already exists , does not need to recreate it');
END;
Check the orafaq page on this

Related

Oracle rename partition if exists

I need to create a statement that can be run to rename a partition only if specific partition name exists and if not then continue on to execute other code.
basic command = ALTER TABLE TEST RENAME PARTITION P1 TO P2:
I have looked at the following but have not come up with a solution
Using IF ELSE in Oracle
https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/controlstructures.htm
You could check whether the partition exists within the table USER_TAB_PARTITIONS:
DECLARE
v_p1_exists AS NUMBER;
v_p2_exists AS NUMBER;
BEGIN
SELECT COUNT(*)
INTO v_p1_exists
FROM user_tab_partitions
WHERE table_name = 'TEST'
AND partition_name = 'P1';
SELECT COUNT(*)
INTO v_p2_exists
FROM user_tab_partitions
WHERE table_name = 'TEST'
AND partition_name = 'P2';
IF (v_p1_exists <> 0) AND (v_p2_exists = 0) THEN
EXECUTE IMMEDIATE 'ALTER TABLE TEST RENAME PARTITION P1 TO P2';
END;
END;
I depends on your requirements but a basic procedure would be this one:
DECLARE
PARTITION_DOES_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT(PARTITION_DOES_NOT_EXIST, -2149);
BEGIN
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE TEST RENAME PARTITION P1 TO P2';
EXCEPTION
WHEN PARTITION_DOES_NOT_EXIST THEN NULL;
END;
... ohter commands
END;
One option is to enclose ALTER TABLE into its own BEGIN-END block, with appropriate exception handling section. Mine is kind of stupid (WHEN OTHERS, eh?); feel free to rewrite it to be meaningful - it is just to show how to do it.
So: if ALTER TABLE fails, it'll raise some error; it'll be captured, handled, and code will continue its execution.
begin
begin
execute immediate 'alter table test rename partition p1 to p2';
exception
when others then
-- ignore errors
null;
end;
-- continue to execute other code
...
end;

Oracle not able to insert exception into table

I have below procedure where i am trying to track the exceptions into I_Log table.To test whether its working or not I have made a ORA-00933: SQL command not properly ended error in my query where I am trying to insert into I_OPTION table. When i run this procedure the dbms output line is printing the error below but its not getting inserted into I_Log table:
OTHERS exception in EXT_I_OPTION - ID:1000196-933----ORA-00933: SQL command not properly ended
Below is my procedure:
CREATE OR REPLACE PROCEDURE
"EXT_I_OPTION"(in_id IN NUMBER DEFAULT 0)
AS
err_code VARCHAR(100);
err_msg VARCHAR(100);
in_event_id NUMBER;
in_db_link VARCHAR2(50);
in_env_id NUMBER;
l_sql VARCHAR2(5000);
l_sql1 VARCHAR2(5000);
BEGIN
FOR I_row IN I_cur
LOOP
l_sql2 := INSERT INTO I_OPTION(ID)
select DISTINCT(SO.ID)
)
from Icard I;
END LOOP;
EXCEPTION WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
INSERT INTO I_log (I_ID)
VALUES (i_id);
RAISE;
COMMIT;
END ext_I_option;
It seems that you have a RAISE before COMMIT; this way, the error will be raised before doing COMMIT, so you don't find data in your log table.
According to suggestions, you should define a procedure to handle your log table:
CREATE OR REPLACE procedure i_LOG (...) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
Insert into I_LOG(...);
COMMIT;
END;
/
This procedure runs in a separate transaction, so it only does commit of log data, with no conflict with data you modify in your main procedure.
Then you should modify your error handling in this way, avoiding COMMIT statement, that can be really dangerous, saving partial, unconsistent data:
DBMS_OUTPUT.PUT_LINE('OTHERS exception in EXT_I_OPTION - ID:'||to_char(ID) || err_code || '----' || err_msg );
ins_I_LOG(...);
RAISE;

drop table If it exists in Oracle (IF EXIST) [duplicate]

This question already has answers here:
Oracle: If Table Exists
(16 answers)
Closed 6 years ago.
I am using Oracle 12c and I am not interesting to have an error while droping my table 'CONTINENT' in case it doesn't exist.
I did this
set echo on
set serveroutput on
alter session set current_schema=WORK_ODI;
set verify off
set pause off
begin
execute immediate 'drop table continent';
exception when others then null;
end;
This script is work with me well. and I use this script too :
declare
c int;
begin
select count(*) into c from user_tables where table_name = upper('continent');
if c = 1 then
execute immediate 'drop table continent';
end if;
end;
the both scripts work well but my boss wants something like IF EXIT. Anybody can help me please. how to use IF EXIT in this case ?
Sorry, there is no if exists in the Oracle's drop table syntax.
You can do two things
define the exception you want to ignore (here ORA-00942)
add an undocumented (and not implemented) hint /*+ IF EXISTS */ that will pleased you management.
.
declare
table_does_not_exist exception;
PRAGMA EXCEPTION_INIT(table_does_not_exist, -942);
begin
execute immediate 'drop table continent /*+ IF EXISTS */';
exception when table_does_not_exist then
DBMS_OUTPUT.PUT_LINE('Ignoring table or view does not exist')
;
end;
/
Additional note: the usage of
exception when others then null;
may be dangerous, as for example you ignore also errors such as tablespace offline, when the table is NOT DROPPED.
set echo on
set serveroutput on
alter session set current_schema=WORK_ODI;
set verify off
set pause off
WHENEVER OSERROR EXIT FAILURE ROLLBACK
drop table continent;
WHENEVER OSERROR CONTINUE
I had a similar problem - i needed a way how to repeat DDL scripts without modifying them. Imaging the following script:
create table tab1(...);
create table tab2(...);
create table tab3{...}; /* <--- this one fails*/
create table tab4(...);
so now we have the following situation: tables "tab1" and "tab2" have been successfully created, "tab3" and "tab4" are missing.
So after fixing statement for the "tab3" table we would have to comment out create statements for "tab1" and "tab2" - it might be very annoying when working with big SQL scripts containing many DDLs and many bugs.
So i came up with the following procedure which allows to re-run DDL statements:
create or replace procedure re_run_ddl (p_sql in varchar2)
AUTHID CURRENT_USER
as
l_line varchar2(500) default rpad('-',20,'-');
l_cr varchar2(2) default chr(10);
l_footer varchar2(500) default l_cr||rpad('*',20,'*');
l_ignore_txt varchar2(200) default 'IGNORING --> ';
ORA_00955 EXCEPTION;
ORA_01430 EXCEPTION;
ORA_02260 EXCEPTION;
ORA_01408 EXCEPTION;
ORA_00942 EXCEPTION;
ORA_02275 EXCEPTION;
ORA_01418 EXCEPTION;
ORA_02443 EXCEPTION;
ORA_01442 EXCEPTION;
ORA_01434 EXCEPTION;
ORA_01543 EXCEPTION;
ORA_00904 EXCEPTION;
ORA_02261 EXCEPTION;
ORA_04043 EXCEPTION;
ORA_02289 EXCEPTION;
PRAGMA EXCEPTION_INIT(ORA_00955, -00955); --ORA-00955: name is already used by an existing object
PRAGMA EXCEPTION_INIT(ORA_01430, -01430); --ORA-01430: column being added already exists in table
PRAGMA EXCEPTION_INIT(ORA_02260, -02260); --ORA-02260: table can have only one primary key
PRAGMA EXCEPTION_INIT(ORA_01408, -01408); --ORA-01408: such column list already indexed
PRAGMA EXCEPTION_INIT(ORA_00942, -00942); --ORA-00942: table or view does not exist
PRAGMA EXCEPTION_INIT(ORA_02275, -02275); --ORA-02275: such a referential constraint already exists in the table
PRAGMA EXCEPTION_INIT(ORA_01418, -01418); --ORA-01418: specified index does not exist
PRAGMA EXCEPTION_INIT(ORA_02443, -02443); --ORA-02443: Cannot drop constraint - nonexistent constraint
PRAGMA EXCEPTION_INIT(ORA_01442, -01442); --ORA-01442: column to be modified to NOT NULL is already NOT NULL
PRAGMA EXCEPTION_INIT(ORA_01434, -01434); --ORA-01434: private synonym to be dropped does not exist
PRAGMA EXCEPTION_INIT(ORA_01543, -01543); --ORA-01543: tablespace '<TBS_NAME>' already exists
PRAGMA EXCEPTION_INIT(ORA_00904, -00904); --ORA-00904: "%s: invalid identifier"
PRAGMA EXCEPTION_INIT(ORA_02261, -02261); --ORA-02261: "such unique or primary key already exists in the table"
PRAGMA EXCEPTION_INIT(ORA_04043, -04043); --ORA-04043: object %s does not exist
PRAGMA EXCEPTION_INIT(ORA_02289, -02289); --ORA-02289: sequence does not exist
procedure p(
p_str in varchar2
,p_maxlength in int default 120
)
is
i int := 1;
begin
dbms_output.enable( NULL );
while ( (length(substr(p_str,i,p_maxlength))) = p_maxlength ) loop
dbms_output.put_line(substr(p_str,i,p_maxlength));
i := i + p_maxlength;
end loop;
dbms_output.put_line(substr(p_str,i,p_maxlength));
end p;
begin
p( 'EXEC:'||l_cr||l_line||l_cr||p_sql||l_cr||l_line );
execute immediate p_sql;
p( 'done.' );
exception
when ORA_00955 or ORA_01430 or ORA_02260 or ORA_01408 or ORA_00942
or ORA_02275 or ORA_01418 or ORA_02443 or ORA_01442 or ORA_01434
or ORA_01543 or ORA_00904 or ORA_02261 or ORA_04043 or ORA_02289
then p( l_ignore_txt || SQLERRM || l_footer );
when OTHERS then
p( SQLERRM );
p( DBMS_UTILITY.FORMAT_ERROR_BACKTRACE );
p( l_footer );
RAISE;
end;
/
show err
Usage example:
set serveroutput on
begin
re_run_ddl('
create table test
(
id number,
s varchar2(30)
)
');
end;
/
exec re_run_ddl('drop table test');
exec re_run_ddl('drop table test');
exec re_run_ddl('drop table test');
Output:
EXEC:
--------------------
create table test
(
id number,
s varchar2(30)
)
--------------------
done.
PL/SQL procedure successfully completed.
EXEC:
--------------------
drop table test
--------------------
done.
PL/SQL procedure successfully completed.
stx11de2> EXEC:
--------------------
drop table test
--------------------
IGNORING --> ORA-00942: table or view does not exist
********************
PL/SQL procedure successfully completed.
stx11de2> EXEC:
--------------------
drop table test
--------------------
IGNORING --> ORA-00942: table or view does not exist
********************
PL/SQL procedure successfully completed.

Oracle SQL - If Exists, Drop Table & Create

Can some one please guide me what's wrong with this query? In SQL Server we just check the presence of the Object_ID of a table to drop it and re-create it. I am new to Oracle and wrote this query:
declare Table_exists INTEGER;
BEGIN
Select count(*) into Table_exists from sys.all_tables where table_name='TABLENAME1';
EXCEPTION
WHEN NO_DATA_FOUND
THEN
Table_Exists :=0;
if(table_exists)=1
Then
Execute Immediate 'Drop Table TABLENAME1;'
'Create Table TABLENAME1;';
DBMS_OUTPUT.PUT_LINE('Table Dropped and Re-Created!');
Else
Execute Immediate 'Create Table TABLENAME1;';
DBMS_OUTPUT.PUT_LINE('New Table Created!');
END IF;
END;
I get the output - ANONYMOUS BLOCK COMPLETED, but the table is not created. The table was previously existing, so I dropped it to check if the PL/SQL is actually creating the table, but NO. What is wrong here? What am I missing? Please guide.
When you are using all_tables filter the results for your
schema by adding where owner = 'your_schema'
or use sys.user_tables
ALL_TABLES describes the relational tables accessible to the current user
USER_TABLES describes the relational tables owned by the current user.
When use execute_emmidiate remove the ; from the query;
Modified query;
DECLARE
Table_exists INTEGER;
BEGIN
Select count(*) into Table_exists from sys.user_tables where table_name='TABLENAME1';
--or
--Select count(*) into Table_exists from sys.all_tables
--where table_name='TABLENAME1' and owner = 'your_DB';
if table_exists = 1 Then
Execute Immediate 'Drop Table TABLENAME1';
Execute Immediate 'Create Table TABLENAME1(num number)';
DBMS_OUTPUT.PUT_LINE('Table Dropped and Re-Created!');
Else
Execute Immediate 'Create Table TABLENAME1(num number)';
DBMS_OUTPUT.PUT_LINE('New Table Created!');
END IF;
END;
First note:
Select count(*) into Table_exists
from sys.all_tables
where table_name = 'TABLENAME1';
will always return one row. You don't need the exception handling.
My best guess is that you have more than one table called TABLENAME1. Run this query to find out:
Select *
from sys.all_tables
where table_name = 'TABLENAME1';
Oracle stores tables from all owners that you can access. You might also want to check OWNER_NAME in the where clause.
However, you seem to understand exception handling. So, just drop the table, ignore any errors, and then recreate the table.
The EXCEPTION clause lasts till the next END and not just the next statement. If you want to continue after catching the exception you need to add an additional BEGIN/END:
declare
Table_exists INTEGER;
BEGIN
BEGIN
Select count(*) into Table_exists from sys.all_tables where table_name='TABLENAME1';
EXCEPTION
WHEN NO_DATA_FOUND THEN
Table_Exists :=0;
END;
if(table_exists)=1 Then
Execute Immediate 'Drop Table TABLENAME1;'
Execute Immediate 'Create Table TABLENAME1;';
DBMS_OUTPUT.PUT_LINE('Table Dropped and Re-Created!');
Else
Execute Immediate 'Create Table TABLENAME1;';
DBMS_OUTPUT.PUT_LINE('New Table Created!');
END IF;
END;
As pointed out by Gordon, the EXCEPTION clause is not really needed in this case since count(*) will always return one row. So the following is sufficient:
declare
Table_exists INTEGER;
BEGIN
Select count(*) into Table_exists from sys.all_tables where table_name='TABLENAME1';
if(table_exists)=1 Then
Execute Immediate 'Drop Table TABLENAME1;'
Execute Immediate 'Create Table TABLENAME1;';
DBMS_OUTPUT.PUT_LINE('Table Dropped and Re-Created!');
Else
Execute Immediate 'Create Table TABLENAME1;';
DBMS_OUTPUT.PUT_LINE('New Table Created!');
END IF;
END;

checking if table exists function

Can you help me rectify this block of code plz?
`CREATE OR REPLACE FUNCTION TABLE_EXISTS(name VARCHAR(50))
RETURNS BOOLEAN
AS
BEGIN
DECLARE counttable INTEGER;
SELECT COUNT(1) INTO counttable FROM USER_TABLES WHERE TABLE_NAME=name;
if counttable=0 then
return false
else
return true
end if;
END;
/
IF (TABLE_EXISTS("LEADS_DELETED")) then
DROP TABLE LEADS_DELETED;
end if;
/
CREATE GLOBAL TEMPORARY TABLE LEADS_DELETED
(
ID NUMBER(19),
PRIMARY KEY (ID)
) ON COMMIT DELETE ROWS`
You can use a construct like this when you want to create or recreate a table (try to drop and catch the ORA-00942 exception that gets thrown when the object doesn't exist):
DECLARE
table_does_not_exist exception;
pragma exception_init(table_does_not_exist, -942);
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE LEADS_DELETED';
EXCEPTION
WHEN table_does_not_exist THEN
NULL;
END;
/
CREATE TABLE ...
You have double quotes aroung your table name "LEADS_DELETED" should be 'LEADS_DELETED'.
I'd also wrap the table_name in your query with UPPER(table_name) too.
You also need to put the DROP TABLE command inside an EXECUTE IMMEDIATE wrapper.
You declare your variable in the wrog place too, it needs to be declared before the BEGIN clause.
CREATE OR REPLACE
FUNCTION TABLE_EXISTS(name VARCHAR(50))
RETURNS BOOLEAN
AS
counttable INTEGER;
BEGIN
SELECT COUNT(1)
INTO counttable
FROM USER_TABLES
WHERE TABLE_NAME=UPPER(name);
if counttable=0
then
return false
else
return true
end if;
END;
/
-- I suggest you use a bind variable instead of the literal table name.
IF TABLE_EXISTS('LEADS_DELETED')
THEN
EXECUTE IMMEDIATE 'DROP TABLE LEADS_DELETED';
END IF;
/
-- Could be
IF table_exists(v_table_name)
THEN
EXECUTE IMMEDIATE 'DROP TABLE :tablename'
USING v_table_name;
END IF;