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

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.

Related

Procedure to check if authorized

So I have this function:
create or replace function get_authorization(
p_pnr in bankcustomer.pnr%type,
p_knr in account.cnr%type)
return number
as
v_authorization bankcustomer.pnr%type;
begin
select count(*)
into v_authorization
from bankcustomer,account
where pnr = p_pnr
and cnr = p_cnr;
return v_authorization;
exception
when no_data_found then
return -1;
end;
This returns 1 or 0 if allowed. I need to do a procedure which adds a row in a table called withdraw and that procedure needs to call get_authorization to check if the customer is allowed. This is what i have so far:
create or replace procedure do_withdraw(
p_pnr in withdraw.pnr%type,
p_belopp in withdraw.belopp%type)
as
declare
authorization exception;
begin
insert into uttag(pnr,amount)
values((select pnr from account),p_amount); /*pnr is foreign key in withdraw*/
if user not in (select get_amount(p_pnr) from dual) then
raise authorization;
end if;
exception
when authorization then
raise_application_error(-20007,'Unauthorized!');
commit;
end;
I get alot of error messages and specifically on declare. I really cant wrap my head around this :(
You have few problems with your code -
create or replace procedure do_withdraw(
p_pnr in withdraw.pnr%type,
p_belopp in withdraw.belopp%type)
as
-- declare -- Declare keyword is not used in procedure
authorization exception;
begin
insert into uttag(pnr,amount)
values((select pnr from account), -- This might return multiple rows, So you have to add a where clause in this query.
p_amount); /*pnr is foreign key in withdraw*/
if user <> get_authorization(p_pnr) then -- You are checking current user with amount which should be corrected.
raise authorization;
end if;
commit; -- Commit should be last sattement of procedure
exception
when authorization then
raise_application_error(-20007,'Unauthorized!');
Rollback; -- In exception you should use Rollabck instead of Commit;
end;
So ive tried what you said and think i know what you mean:
create or replace procedure do_withdraw(
p_pnr in withdraw.pnr%type,
p_amount in withdraw.amount%type)
as
-- declare -- Declare keyword is not used in procedure
authorization exception;
begin
insert into withdraw(pnr,amount)
values((select pnr from account where pnr = p_pnr), -- This might return multiple rows, So you have to add a where clause in this query.
p_amount); /*pnr is foreign key in withdraw*/
if user not in (select get_authorization(p_pnr)) then -- You are checking current user with amount which should be corrected.
raise authorization;
end if;
commit; -- Commit should be last sattement of procedure
exception
when authorization then
raise_application_error(-20007,'Unauthorized!');
Rollback; -- In exception you should use Rollabck instead of Commit;
end;
Now i get error: Line/Col: 11/51 PLS-00103: Encountered the symbol ")" when expecting one of the following:. ( , * % & - + /

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 procedure stops running

I have an Oracle stored procedure that is called from a .NET application. It runs for over 15 minutes. It is very simple code that inserts into a big table from a smaller table, then clears the smaller table.
My issue is that it runs for like 15 minutes, then it dies. No error messages in the log. Nothing. Just stops running. I have done a SQL trace, no evidence of an issue. Sometimes it works, sometimes it doesn't.
Some consistencies exist - when it does fail, it never gets to the Data Moved Successfully or Exception section. Just appears to stop running.
PROCEDURE C_X_AllocInsertData(
p_AccountTable VARCHAR2,
p_AllocationTable VARCHAR2,
p_YearMonth NUMBER,
p_versionPK NUMBER,
p_returncode OUT NUMBER)
AS PRAGMA AUTONOMOUS_TRANSACTION;
v_OutputTableRowCntSql varchar(32767);
BEGIN
p_returncode:=0;
C_X_VERSIONINSERTLOG(
p_VersionPk
,'Now moving the data from temp table to big table'
,'Now moving the data from temp table to big table'
);
--Now that all operations are complete, delete from account table
v_OutputTableRowCntSql := 'BEGIN delete from '||p_AccountTable||' where YEARMONTH= '||p_YearMonth||'; ';
--Then insert from the TMP table
v_OutputTableRowCntSql := v_OutputTableRowCntSql || 'insert into '||p_AccountTable|| ' SELECT * FROM ' || p_AllocationTable||'; ';
--Then clear the temp table
v_OutputTableRowCntSql := v_OutputTableRowCntSql || 'delete from '||p_AllocationTable||'; END;';
EXECUTE IMMEDIATE v_OutputTableRowCntSql;
C_X_VERSIONINSERTLOG(
p_VersionPk
,'Data moved successfully.'
,'Data moved successfully.'
);
commit;
EXCEPTION
WHEN OTHERS THEN
p_returncode:=-1;
C_X_VERSIONINSERTLOG(
p_VersionPk
,'Insert into big table failed for version #'||p_versionPK||'... Error message was: '||SQLERRM
,'Insert into big table failed. Error message was: '||SQLERRM||' Statement was: '||v_OutputTableRowCntSql
);
END;
It seems that C_X_VERSIONINSERTLOG procedure lacks appropriate error handing...I will add that. Here it is in its original form...could this be the issue?
PROCEDURE C_X_VERSIONINSERTLOG
(
P_VERSIONPK NUMBER,
P_LOGTEXT VARCHAR2,
P_ERROR_MSG VARCHAR2)
AS PRAGMA AUTONOMOUS_TRANSACTION;
v_VersionLogPk C_X_VERSIONLOG.VersionLogPk%TYPE;
BEGIN
SELECT C_X_VERSIONLOG_SEQ.nextval INTO v_VersionLogPk FROM DUAL;
INSERT
INTO C_X_VERSIONLOG
(
VersionLogPk,
VERSIONPK,
VERSIONLOGTEXT,
VERSIONLOGTECHNICALTEXT,
VERSIONLOGDATE
)
VALUES
(
v_VersionLogPk,
P_VERSIONPK,
P_LOGTEXT,
P_ERROR_MSG ,
CURRENT_TIMESTAMP
);
COMMIT;
END C_X_VERSIONINSERTLOG;

ADD CONSTRAINT IF EXISTS (Oracle 11g, Postgres 8)

I'm having difficult to make one script to delete the old constraints from some databases and after, create new ones with new references.
The problem is that the databases are not equal.
eg.: the swpmnh database has the fk_cmp_solicitaca_rh_contrat constraint but the swpmcs database has not. So if I execute the script I would have an error and it won't commit.
I know that Postgres 9.x has the possibility to do DROP CONSTRAINT IF EXISTS, but neither Postgres 8.x nor Oracle 11g have this function.
I'm working and studying SQL about only 3 months, I know that this is a simple thing, but it's being a problem for me.
This is the error you will be getting:
SQL> alter table my_tab drop constraint my_cons;
alter table my_tab drop constraint my_cons
*
ERROR at line 1:
ORA-02443: Cannot drop constraint - nonexistent constraint
You can trap the ORA-02443 error in PL/SQL and ignore it (using dynamic SQL):
1 declare
2 e exception;
3 pragma exception_init (e, -2443);
4 begin
5 execute immediate 'alter table my_tab drop constraint my_cons';
6 exception
7 when e then null;
8* end;
SQL> /
PL/SQL procedure successfully completed.
That is a bit verbose, so you could create a handy procedure:
create or replace procedure drop_constraint (p_table varchar2, p_constraint varchar2) is
e exception;
pragma exception_init (e, -2443);
begin
execute immediate 'alter table ' || p_table || ' drop constraint '||p_constraint;
exception
when e then null;
end;
Then use it whenever you need it:
execute drop_constraint ('my_tab', 'my_cons1');
execute drop_constraint ('my_tab', 'my_cons2');
execute drop_constraint ('another_tab', 'another_cons');

sql exception handling

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