How to fix "ORA-00950: invalid DROP option"? - sql

ORA-00950: invalid DROP option
Above is the error that I am getting. I have written this procedure to remove all indexes from the emp_1 table. So can anyone please help me to find out the error and to fix this error?
CREATE OR REPLACE NONEDITIONABLE PROCEDURE sp_drop_indexes (
p_table_name IN VARCHAR2,
p_errormsg OUT VARCHAR2 )
IS
v_sql VARCHAR2(1000);
CURSOR get_indexes IS
SELECT index_name
FROM user_indexes
WHERE table_name = 'EMP_1';
BEGIN
FOR rec IN get_indexes LOOP
v_sql := 'DROP INDEX' || rec.index_name;
EXECUTE IMMEDIATE v_sql;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
p_errormsg := sqlerrm;
END sp_drop_indexes;

You are missing a space after the DROP INDEX (but still inside the quotes) in your code:
v_sql := 'DROP INDEX ' || rec.index_name;

Make sure you include a space after the DROP INDEX keyword:
v_sql := 'DROP INDEX ' || rec.index_name;

You need a space after drop index and, if you can have case-sensitive index names, you need double quotes:
CREATE OR REPLACE NONEDITIONABLE PROCEDURE sp_drop_indexes (
p_table_name IN VARCHAR2,
p_errormsg OUT VARCHAR2 )
IS
v_sql VARCHAR2(1000);
CURSOR get_indexes IS
SELECT index_name
FROM user_indexes
WHERE table_name = 'EMP_1';
BEGIN
FOR rec IN get_indexes LOOP
v_sql := 'DROP INDEX "' || rec.index_name || '"';
EXECUTE IMMEDIATE v_sql;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
p_errormsg := sqlerrm;
END sp_drop_indexes;
/

Related

How to drop and create table again and again

when i use this code first time ,it create the table but i want to use this code again and again but second time when i use it ,it will drop the table but does not create table again . kindly help me to correct the code according to my requirement.
set serverout on
DECLARE
table_or_view_does_not_exist exception;
pragma exception_init(table_or_view_does_not_exist,-00942);
ddl_qry VARCHAR2 (200);
ddl_table varchar2(200);
r_emp SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
v_array SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST('ACCT_ID',
'PARENT_ACCT_ID',
'CUST_ID',
'ACCT_NAME',
'BILLING_CYCLE_TYPE',
'PAID_FLAG',
'BILL_DELIVER_METHOD');
BEGIN
ddl_qry:='Drop Table Accnt_Profile_Spcl';
EXECUTE IMMEDIATE ddl_qry;
exception
when table_or_view_does_not_exist then
dbms_output.put_line('There is no error');
GOTO end_point;
<<end_point>>
ddl_table := 'create table Accnt_Profile_Spcl(
column_name varchar2(50),
spcl_char_count number)';
EXECUTE IMMEDIATE ddl_table;
dbms_output.put_line('Table has been created');
---------DBMS_OUTPUT.ENABLE;
FOR i IN 1..v_array.COUNT LOOP
r_emp.EXTEND;
EXECUTE IMMEDIATE
'SELECT /*+parallel(16)*/ COUNT(*) FROM account_profile WHERE NOT REGEXP_LIKE('||v_array(i)||',''[A-Za-z0-9.]'')'
INTO r_emp(i);
if r_emp(i)<>0 then
-----------dbms_output.put_line(v_array(i) || ': ' || r_emp(i));
execute immediate 'insert into Accnt_Profile_Spcl values (:param1,:param2)' using v_array(i), r_emp(i);
end if;
END LOOP;
END;
That's bad practice. You should really avoid dropping and creating tables that way, that's not how Oracle is supposed to work. Create table once, at SQL level, and reuse it as many times as you want. Just remove its contents, if you want / have to.
Anyway: here's how you could do that:
SQL> declare
2 l_cnt number;
3 begin
4 select count(*) into l_cnt
5 from user_tables
6 where table_name = 'ACCNT_PROFILE_SPCL';
7
8 if l_cnt = 1 then
9 execute immediate 'drop table ACCNT_PROFILE_SPCL';
10
11 dbms_output.put_line('Table dropped');
12 end if;
13
14 execute immediate 'create table ACCNT_PROFILE_SPCL ' ||
15 ' (column_name varchar2(50),' ||
16 ' spcl_char_count number)';
17
18 dbms_output.put_line('Table created');
19 end;
20 /
Table dropped
Table created
PL/SQL procedure successfully completed.
SQL> /
Table dropped
Table created
PL/SQL procedure successfully completed.
SQL>
Use a nested block to handle the exception and not the main block:
DECLARE
ddl_qry VARCHAR2 (200);
ddl_table varchar2(200);
r_emp SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
v_array SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST('ACCT_ID',
'PARENT_ACCT_ID',
'CUST_ID',
'ACCT_NAME',
'BILLING_CYCLE_TYPE',
'PAID_FLAG',
'BILL_DELIVER_METHOD');
BEGIN
DECLARE
table_or_view_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_or_view_does_not_exist,-00942);
BEGIN
ddl_qry:='Drop Table Accnt_Profile_Spcl';
EXECUTE IMMEDIATE ddl_qry;
EXCEPTION
WHEN table_or_view_does_not_exist THEN
dbms_output.put_line('There is no error');
END;
ddl_table := 'create table Accnt_Profile_Spcl(
column_name varchar2(50),
spcl_char_count number)';
EXECUTE IMMEDIATE ddl_table;
dbms_output.put_line('Table has been created');
FOR i IN 1..v_array.COUNT LOOP
r_emp.EXTEND;
EXECUTE IMMEDIATE
'SELECT /*+parallel(16)*/ COUNT(*) FROM account_profile WHERE NOT REGEXP_LIKE('||v_array(i)||',''[A-Za-z0-9.]'')'
INTO r_emp(i);
if r_emp(i)<>0 then
execute immediate 'insert into Accnt_Profile_Spcl values (:param1,:param2)' using v_array(i), r_emp(i);
end if;
END LOOP;
END;
/
fiddle

parameter i PL/SQL procedure

I am trying to execute a PL/SQL procedure without success.
It shows me "inexistent table". What can I do?
CREATE OR REPLACE PROCEDURE INTEGRATION(tableName varchar2) IS
BEGIN
MERGE INTO tableName alert
USING ...
you can try with execute immediate statement and concatenate the tablename passed from procedure
see example from oracle site
CREATE OR REPLACE PROCEDURE delete_rows (
table_name IN VARCHAR2,
condition IN VARCHAR2 DEFAULT NULL) AS
where_clause VARCHAR2(100) := ' WHERE ' || condition;
v_table VARCHAR2(30);
BEGIN
-- first make sure that the table actually exists; if not, raise an exception
SELECT OBJECT_NAME INTO v_table FROM USER_OBJECTS
WHERE OBJECT_NAME = UPPER(table_name) AND OBJECT_TYPE = 'TABLE';
IF condition IS NULL THEN where_clause := NULL; END IF;
EXECUTE IMMEDIATE 'DELETE FROM ' || v_table || where_clause;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Invalid table: ' || table_name);
END;
/
BEGIN
delete_rows('employees_temp', 'employee_id = 111');
END;
/
for other info see oracle site
execute immediate

Dynamically Identify Table (Table Identified by Variable)

I'm trying to create a procedure that will allow me to write an existing row to another table dynamically but the row declaration and insert-statement in the following snippet don't work. The error message indicates that the view hasn't been identified although outputting the target_table.table_name works just fine.
More will be added to the block later on - such as a column with the operation (e.g. INSERT or UPDATE). This is just a simple example and the last procedure (pass_reference) is used to trigger the procedure.
Any help would be much appreciated.
CREATE OR REPLACE PROCEDURE denormalize (new_cursor sys_refcursor, target_table_name varchar)
IS
target_table user_tables%rowtype;
sql_target_table varchar(200) := 'select * from user_tables where table_name = :target_table_name';
row target_table%rowtype;
BEGIN
execute immediate sql_target_table into target_table using target_table_name;
LOOP
fetch new_cursor into row;
exit when new_cursor%notfound;
insert into target_table values row;
commit;
END LOOP;
END denormalize;
/
CREATE OR REPLACE PROCEDURE pass_reference
AS
new_cursor sys_refcursor;
BEGIN
open new_cursor for select * from sales where sales_id=1;
denormalize(new_cursor, 'NEW_SALES');
END;
/
please check this code, it's not working only as for example, as you see for working columns in your cursor should be named as columns in destination table.
I take this code from package that create html table in mail base on view, hope you found this example useful
good luck
declare
in_view_name varchar2(30);
in_table_name varchar2(30) := 'your_new_table';
out_rc number;
out_rc_txt varchar2(1000);
l_cursor number;
l_sql varchar2(50) := 'select * from ' || in_view_name;
l_col_cnt binary_integer;
l_col_tab dbms_sql.desc_tab;
l_column_value varchar2(4000);
l_is_empty boolean := true;
l_insert_header varchar2(1000);
l_insert varchar2(32000);
begin
out_rc := 0;
out_rc_txt := 'OK';
l_cursor := dbms_sql.open_cursor;
dbms_sql.parse(l_cursor, l_sql, dbms_sql.native);
l_col_cnt := dbms_sql.execute(l_cursor);
dbms_sql.describe_columns(l_cursor, l_col_cnt, l_col_tab);
l_insert_header := 'insert into '||in_table_name||'(';
if l_col_cnt > 0 then
-- header
for i in l_col_tab.first .. l_col_tab.last loop
dbms_lob.append(l_insert_header, l_col_tab(i).col_name);
if i != l_col_tab.last then
dbms_lob.append(l_insert_header, ',');
end if;
dbms_sql.define_column(l_cursor, i, l_column_value, 4000);
end loop;
l_insert_header := l_insert_header || ') values(';
-- data
while dbms_sql.fetch_rows(l_cursor) > 0 loop
l_is_empty := false;
l_insert := l_insert_header;
for i in l_col_tab.first .. l_col_tab.last loop
dbms_sql.column_value(l_cursor, i, l_column_value);
l_insert := l_insert || '''' || l_column_value || ''','
if not in_attachment then
dbms_lob.append(out_table, l_td);
end if;
if (not in_attachment) or (l_column_value is not null) then
dbms_lob.append(out_table, nvl(l_column_value, l_nbsp));
end if;
if (not in_attachment) or (i != l_col_tab.last) then
dbms_lob.append(out_table, l_tdc);
end if;
end loop;
l_insert := substr(l_insert, 1, length(l_insert) - 1) || ')';
execute immediate l_insert;
end loop;
end if;
dbms_sql.close_cursor(l_cursor);
end;

copy oracle sequence to test schema, convert to PL/Sql procedure

I have this sql which copies (actually recreates) a sequence from a productive scheme to a test scheme in Oracle, how do i make a procedure from this that i can use as follows ? Suppose all grants are ok and all names are the same in the test scheme.
desired syntax
copy_sequence <name_of_sequence> <connectstring_prod_scheme> <connectstring_test_scheme>
sql
connect test/testpw#db.srv;
declare
val number(21);
s_sql varchar2(200);
begin
--use the select on the productive db to get the current value
select prod.seq.nextval into val from dual;
s_sql := 'drop sequence seq';
execute immediate s_sql;
s_sql := 'create sequence seq minvalue 1 maxvalue 999999999999999999999 start with '||val||' increment by 1';
execute immediate s_sql;
end;
/
You could use DBMS_METADATA to extract the DDL for the sequence:
declare
procedure copy_sequence(p_SequenceName in varchar2,
p_SourceSchema in varchar2,
p_TargetSchema in varchar2) is
doc clob;
h number;
th number; -- handle
begin
-- Specify the object type.
h := DBMS_METADATA.OPEN('SEQUENCE');
-- Use filters to specify the particular object desired.
DBMS_METADATA.SET_FILTER(h,
'SCHEMA',
p_SourceSchema);
DBMS_METADATA.SET_FILTER(h,
'NAME',
p_SequenceName);
-- Request that the schema name be modified.
th := DBMS_METADATA.ADD_TRANSFORM(h,
'MODIFY');
DBMS_METADATA.SET_REMAP_PARAM(th,
'REMAP_SCHEMA',
p_SourceSchema,
p_TargetSchema);
-- Request that the metadata be transformed into creation DDL.
th := DBMS_METADATA.ADD_TRANSFORM(h,
'DDL');
-- Fetch the object.
doc := DBMS_METADATA.FETCH_CLOB(h);
-- Release resources.
DBMS_METADATA.CLOSE(h);
-- debug output
dbms_output.put_line(doc);
-- execute it
execute immediate doc;
end;
begin
copy_sequence(sequence_name, source_schema, target_schema);
end;
If you want to put this into a package, you'll probably need additional grants to make it work.
Assuming your test/test user has the proper privileges (select any table, create sequence) and the schemas are in the same database:
create procedure copy_sequence(seq VARCHAR2, prod_scheme VARCHAR2, test_scheme VARCHAR2)
as
val number(21);
s_sql varchar2(200);
begin
--either use the select on the productive db to get the current value + 1
execute immediate 'select '||prod_scheme||'.'||seq||'.nextval from dual' INTO val;
--or use the select on ALL_SEQUENCES.LAST_NUMBER to get the current value (from APC's comment)
execute immediate 'select last_number from all_sequences where sequence_owner = upper('''||prod_scheme||''') and sequence_name = upper('''||seq||''')' INTO val;
s_sql := 'drop sequence '||test_scheme||'.'||seq;
execute immediate s_sql;
s_sql := 'create sequence '||test_scheme||'.'||seq||' minvalue 1 maxvalue 999999999999999999999 start with '||val||' increment by 1';
execute immediate s_sql;
end;
/
But you wouldn't call this with connect strings but with schema names:
-- first connect
connect test/testpw#db.srv;
-- then execute procedure
exec copy_sequence( <name_of_sequence>, <prod_scheme>, <test_scheme>);
-- or execute procedure more than once
begin
copy_sequence( <name_of_sequence1>, <prod_scheme>, <test_scheme>);
copy_sequence( <name_of_sequence2>, <prod_scheme>, <test_scheme>);
end;
/
If you have the correct grants you can use:
CREATE PROCEDURE MIGRATE_SEQUENCE(
in_sequence_name IN ALL_SEQUENCES.SEQUENCE_NAME%TYPE,
in_current_owner IN ALL_SEQUENCES.SEQUENCE_OWNER%TYPE,
in_new_owner IN ALL_SEQUENCES.SEQUENCE_OWNER%TYPE
)
IS
p_sql VARCHAR2(4000);
BEGIN
SELECT 'CREATE SEQUENCE "' || in_new_owner || '"."' || sequence_name || '"'
|| ' MINVALUE ' || min_value
|| ' MAXVALUE ' || max_value
|| ' INCREMENT BY ' || increment_by
|| ' START WITH ' || ( last_number + 1 )
|| ' ' || CASE cycle_flag WHEN 'N' THEN 'NO' END || 'CYCLE'
|| ' ' || CASE order_flag WHEN 'N' THEN 'NO' END || 'ORDER'
|| ' ' || CASE cache_size WHEN 0 THEN 'NOCACHE' ELSE 'CACHE ' || cache_size END
INTO p_sql
FROM ALL_SEQUENCES
WHERE SEQUENCE_NAME = in_sequence_name
AND SEQUENCE_OWNER = in_current_owner;
-- DBMS_OUTPUT.PUT_LINE( p_sql );
/*
-- Delete the sequence if it already exists
DECLARE
SEQUENCE_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT( SEQUENCE_NOT_EXIST, -2289 );
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE "' ||in_new_owner|| '"."' ||in_sequence_name|| '"';
EXCEPTION
WHEN SEQUENCE_NOT_EXIST THEN
NULL;
END;
*/
EXECUTE IMMEDIATE p_sql;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(
in_current_owner || '.' || in_sequence_name || ' does not exist.'
);
END;
/
SHOW ERRORS;

Oracle: If Table Exists

I'm writing some migration scripts for an Oracle database, and was hoping Oracle had something similar to MySQL's IF EXISTS construct.
Specifically, whenever I want to drop a table in MySQL, I do something like
DROP TABLE IF EXISTS `table_name`;
This way, if the table doesn't exist, the DROP doesn't produce an error, and the script can continue.
Does Oracle have a similar mechanism? I realize I could use the following query to check if a table exists or not
SELECT * FROM dba_tables where table_name = 'table_name';
but the syntax for tying that together with a DROP is escaping me.
The best and most efficient way is to catch the "table not found" exception: this avoids the overhead of checking if the table exists twice; and doesn't suffer from the problem that if the DROP fails for some other reason (that might be important) the exception is still raised to the caller:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
ADDENDUM
For reference, here are the equivalent blocks for other object types:
Sequence
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE ' || sequence_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2289 THEN
RAISE;
END IF;
END;
View
BEGIN
EXECUTE IMMEDIATE 'DROP VIEW ' || view_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
Trigger
BEGIN
EXECUTE IMMEDIATE 'DROP TRIGGER ' || trigger_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -4080 THEN
RAISE;
END IF;
END;
Index
BEGIN
EXECUTE IMMEDIATE 'DROP INDEX ' || index_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1418 THEN
RAISE;
END IF;
END;
Column
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ' || table_name
|| ' DROP COLUMN ' || column_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -904 AND SQLCODE != -942 THEN
RAISE;
END IF;
END;
Database Link
BEGIN
EXECUTE IMMEDIATE 'DROP DATABASE LINK ' || dblink_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2024 THEN
RAISE;
END IF;
END;
Materialized View
BEGIN
EXECUTE IMMEDIATE 'DROP MATERIALIZED VIEW ' || mview_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -12003 THEN
RAISE;
END IF;
END;
Type
BEGIN
EXECUTE IMMEDIATE 'DROP TYPE ' || type_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -4043 THEN
RAISE;
END IF;
END;
Constraint
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ' || table_name
|| ' DROP CONSTRAINT ' || constraint_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2443 AND SQLCODE != -942 THEN
RAISE;
END IF;
END;
Scheduler Job
BEGIN
DBMS_SCHEDULER.drop_job(job_name);
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -27475 THEN
RAISE;
END IF;
END;
User / Schema
BEGIN
EXECUTE IMMEDIATE 'DROP USER ' || user_name;
/* you may or may not want to add CASCADE */
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1918 THEN
RAISE;
END IF;
END;
Package
BEGIN
EXECUTE IMMEDIATE 'DROP PACKAGE ' || package_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -4043 THEN
RAISE;
END IF;
END;
Procedure
BEGIN
EXECUTE IMMEDIATE 'DROP PROCEDURE ' || procedure_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -4043 THEN
RAISE;
END IF;
END;
Function
BEGIN
EXECUTE IMMEDIATE 'DROP FUNCTION ' || function_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -4043 THEN
RAISE;
END IF;
END;
Tablespace
BEGIN
EXECUTE IMMEDIATE 'DROP TABLESPACE ' || tablespace_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -959 THEN
RAISE;
END IF;
END;
Synonym
BEGIN
EXECUTE IMMEDIATE 'DROP SYNONYM ' || synonym_name;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1434 THEN
RAISE;
END IF;
END;
declare
c int;
begin
select count(*) into c from user_tables where table_name = upper('table_name');
if c = 1 then
execute immediate 'drop table table_name';
end if;
end;
That's for checking whether a table in the current schema exists.
For checking whether a given table already exists in a different schema, you'd have to use all_tables instead of user_tables and add the condition all_tables.owner = upper('schema_name')
I have been looking for the same but I ended up writing a procedure to help me out:
CREATE OR REPLACE PROCEDURE DelObject(ObjName varchar2,ObjType varchar2)
IS
v_counter number := 0;
begin
if ObjType = 'TABLE' then
select count(*) into v_counter from user_tables where table_name = upper(ObjName);
if v_counter > 0 then
execute immediate 'drop table ' || ObjName || ' cascade constraints';
end if;
end if;
if ObjType = 'PROCEDURE' then
select count(*) into v_counter from User_Objects where object_type = 'PROCEDURE' and OBJECT_NAME = upper(ObjName);
if v_counter > 0 then
execute immediate 'DROP PROCEDURE ' || ObjName;
end if;
end if;
if ObjType = 'FUNCTION' then
select count(*) into v_counter from User_Objects where object_type = 'FUNCTION' and OBJECT_NAME = upper(ObjName);
if v_counter > 0 then
execute immediate 'DROP FUNCTION ' || ObjName;
end if;
end if;
if ObjType = 'TRIGGER' then
select count(*) into v_counter from User_Triggers where TRIGGER_NAME = upper(ObjName);
if v_counter > 0 then
execute immediate 'DROP TRIGGER ' || ObjName;
end if;
end if;
if ObjType = 'VIEW' then
select count(*) into v_counter from User_Views where VIEW_NAME = upper(ObjName);
if v_counter > 0 then
execute immediate 'DROP VIEW ' || ObjName;
end if;
end if;
if ObjType = 'SEQUENCE' then
select count(*) into v_counter from user_sequences where sequence_name = upper(ObjName);
if v_counter > 0 then
execute immediate 'DROP SEQUENCE ' || ObjName;
end if;
end if;
end;
Hope this helps
just wanted to post a full code that will create a table and drop it if it already exists using Jeffrey's code (kudos to him, not me!).
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE tablename';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
EXECUTE IMMEDIATE 'CREATE TABLE tablename AS SELECT * FROM sourcetable WHERE 1=0';
END;
With SQL*PLUS you can also use the WHENEVER SQLERROR command:
WHENEVER SQLERROR CONTINUE NONE
DROP TABLE TABLE_NAME;
WHENEVER SQLERROR EXIT SQL.SQLCODE
DROP TABLE TABLE_NAME;
With CONTINUE NONE an error is reported, but the script will continue. With EXIT SQL.SQLCODE the script will be terminated in the case of an error.
see also: WHENEVER SQLERROR Docs
Another method is to define an exception and then only catch that exception letting all others propagate.
Declare
eTableDoesNotExist Exception;
PRAGMA EXCEPTION_INIT(eTableDoesNotExist, -942);
Begin
EXECUTE IMMEDIATE ('DROP TABLE myschema.mytable');
Exception
When eTableDoesNotExist Then
DBMS_Output.Put_Line('Table already does not exist.');
End;
I prefer following economic solution
BEGIN
FOR i IN (SELECT NULL FROM USER_OBJECTS WHERE OBJECT_TYPE = 'TABLE' AND OBJECT_NAME = 'TABLE_NAME') LOOP
EXECUTE IMMEDIATE 'DROP TABLE TABLE_NAME';
END LOOP;
END;
One way is to use DBMS_ASSERT.SQL_OBJECT_NAME :
This function verifies that the input parameter string is a qualified SQL identifier of an existing SQL object.
DECLARE
V_OBJECT_NAME VARCHAR2(30);
BEGIN
BEGIN
V_OBJECT_NAME := DBMS_ASSERT.SQL_OBJECT_NAME('tab1');
EXECUTE IMMEDIATE 'DROP TABLE tab1';
EXCEPTION WHEN OTHERS THEN NULL;
END;
END;
/
DBFiddle Demo
There is no 'DROP TABLE IF EXISTS' in oracle, you would have to do the select statement.
try this (i'm not up on oracle syntax, so if my variables are ify, please forgive me):
declare #count int
select #count=count(*) from all_tables where table_name='Table_name';
if #count>0
BEGIN
DROP TABLE tableName;
END
The following snippet worked for me
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE schema_name.table_name';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
And if you want to make it re-enterable and minimize drop/create cycles, you could cache the DDL using dbms_metadata.get_ddl and re-create everything using a construct like this:
declare
v_ddl varchar2(4000);
begin
select dbms_metadata.get_ddl('TABLE','DEPT','SCOTT') into v_ddl from dual;
[COMPARE CACHED DDL AND EXECUTE IF NO MATCH]
exception when others then
if sqlcode = -31603 then
[GET AND EXECUTE CACHED DDL]
else
raise;
end if;
end;
This is just a sample, there should be a loop inside with DDL type, name and owner being variables.
A block like this could be useful to you.
DECLARE
table_exist INT;
BEGIN
SELECT Count(*)
INTO table_exist
FROM dba_tables
WHERE owner = 'SCHEMA_NAME'
AND table_name = 'EMPLOYEE_TABLE';
IF table_exist = 1 THEN
EXECUTE IMMEDIATE 'drop table EMPLOYEE_TABLE';
END IF;
END;
You could always catch the error yourself.
begin
execute immediate 'drop table mytable';
exception when others then null;
end;
It is considered bad practice to overuse this, similar to empty catch()'es in other languages.
Regards
K
Sadly no, there is no such thing as drop if exists, or CREATE IF NOT EXIST
You could write a plsql script to include the logic there.
http://download.oracle.com/docs/cd/B12037_01/server.101/b10759/statements_9003.htm
I'm not much into Oracle Syntax, but i think #Erich's script would be something like this.
declare
cant integer
begin
select into cant count(*) from dba_tables where table_name='Table_name';
if count>0 then
BEGIN
DROP TABLE tableName;
END IF;
END;
I prefer to specify the table and the schema owner.
Watch out for case sensitivity as well. (see "upper" clause below).
I threw a couple of different objects in to show that is can be used in places besides TABLEs.
.............
declare
v_counter int;
begin
select count(*) into v_counter from dba_users where upper(username)=upper('UserSchema01');
if v_counter > 0 then
execute immediate 'DROP USER UserSchema01 CASCADE';
end if;
end;
/
CREATE USER UserSchema01 IDENTIFIED BY pa$$word
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON users;
grant create session to UserSchema01;
And a TABLE example:
declare
v_counter int;
begin
select count(*) into v_counter from all_tables where upper(TABLE_NAME)=upper('ORDERS') and upper(OWNER)=upper('UserSchema01');
if v_counter > 0 then
execute immediate 'DROP TABLE UserSchema01.ORDERS';
end if;
end;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE "IMS"."MAX" ';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
EXECUTE IMMEDIATE '
CREATE TABLE "IMS"."MAX"
( "ID" NUMBER NOT NULL ENABLE,
"NAME" VARCHAR2(20 BYTE),
CONSTRAINT "MAX_PK" PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SYSAUX" ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SYSAUX" ';
END;
// Doing this code, checks if the table exists and later it creates the table max. this simply works in single compilation