Oracle: If Table Exists - sql

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

Related

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

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;
/

For loop fetching data from a cursor is getting skipped

This is the code I'm using. I'm a newbie to PL/SQL making some modifications to existing pl/sql code.
There is a cursor C_GET_REFERENCED_USER_GROUPS which is storing data from sec_user_group table based on user input which is stored inside variable r_username.
So I'm giving some input which will be taken as the value for variable used inside cursor C_GET_REFERENCED_USER_GROUPS and it has output with few rows. During the execution of the cursor inside a for loop, the for loop is getting completely skipped despite the fact that output is there and I haven't given any lines to exit out of the code.
This is how for loop has been created which loops through the cursor and adds to a table.
FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
LOOP
BEGIN
add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
dbms_output.put_line(add_user_to_group_cmd||';');
execute immediate (add_user_to_group_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);
END;
END LOOP;
COMMIT;
I don't get any errors while I'm executing this code, it's just the the execution finishes after the looping through the execution of for loop which loops through cursor C_GET_ROLE_DETAIL and just skips the above mentioned cursor execution which is executed last.
I had also printed the cursor during the beginning of the execution of PL/SQL block just to verify that the output exists by using simple for loop:
FOR rec IN C_GET_REFERENCED_USER_GROUPS
LOOP
DBMS_OUTPUT.put_line (rec.group_id);
END LOOP;
The above does print couple of rows yet the same rows are not being inserted during the last part of pl/sql insertion.
Please see below for the Full code:
SET lines 200
SET trimspool ON
SET echo OFF
SET verify OFF
--SET serveroutput ON size 1000000
SET serveroutput ON size unlimited
DECLARE
l_cmd VARCHAR2(4000);
l_rmsschema VARCHAR2(5000) := trim('&&rmsschema');
l_username VARCHAR2(5000);
l_password VARCHAR2(5000);
l_name VARCHAR2(5000);
l_email VARCHAR2(5000);
l_user_id VARCHAR2(5000) :=trim('&&userid');
l_pwd VARCHAR2(5000) :=trim('&&password');
l_new_username VARCHAR2(5000) :=trim('&&new_user_name');
l_user_email VARCHAR2(5000) :=trim('&&emailid');
r_username VARCHAR2(5000) :=trim('&&referenced_schema_name');
insert_new_user_cmd VARCHAR2(5000);
add_user_to_group_cmd VARCHAR2(5000);
l_granted_roles VARCHAR2(5000);
l_granted_groups VARCHAR2(5000);
RMS_SCHEMA_ERROR EXCEPTION;
CURSOR C_GET_NEW_USER_DETAIL
IS
select distinct nuc.user_id,nuc.pwd,nuc.user_name,nuc.user_email from PROD.NEW_USER_CREATION nuc
where not exists ( select 1 from dba_users du where du.username=nuc.user_id );
CURSOR C_GET_ROLE_DETAIL
IS
select distinct nuc.user_id,nuc.granted_role from PROD.NEW_USER_CREATION nuc order by 1;
CURSOR C_GET_REFERENCED_USER_ROLES
IS
select GRANTED_ROLE from dba_role_privs where grantee=r_username;
CURSOR C_GET_REFERENCED_USER_GROUPS
IS
select group_id from prod.sec_user_group where user_id=r_username;
BEGIN
----Testing the cursor values by printing it-----
FOR rec IN C_GET_REFERENCED_USER_GROUPS
LOOP
DBMS_OUTPUT.put_line (rec.group_id);
END LOOP;
------Insert into NEW_USER_CREATION_TABLE----------
OPEN C_GET_REFERENCED_USER_ROLES;
dbms_output.put_line('TRUNCATE TABLE PROD.NEW_USER_CREATION');
EXECUTE immediate 'TRUNCATE TABLE PROD.NEW_USER_CREATION';
LOOP
FETCH C_GET_REFERENCED_USER_ROLES into l_granted_roles;
EXIT when C_GET_REFERENCED_USER_ROLES%NOTFOUND;
insert_new_user_cmd := 'insert into PROD.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('''|| l_user_id ||''','''||l_pwd||''','''||l_new_username||''','''||l_user_email||''','''||l_granted_roles||''')';
dbms_output.put_line(insert_new_user_cmd||';');
execute immediate (insert_new_user_cmd);
commit;
END LOOP;
CLOSE C_GET_REFERENCED_USER_ROLES;
-- User Creation-------------------------------------------------------------------------
FOR A_REC IN C_GET_NEW_USER_DETAIL
LOOP
BEGIN
l_username := A_REC.USER_ID;
l_password := A_REC.PWD;
l_name := A_REC.USER_NAME;
l_email := A_REC.USER_EMAIL;
BEGIN
dbms_output.put(CHR(10));
dbms_output.put_line('Creating RMS');
BEGIN
l_cmd := 'CREATE USER "'||l_username||'" identified by "'||l_password||'" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01';
dbms_output.put_line(l_cmd||';');
EXECUTE immediate (l_cmd);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : CREATE USER : '||SQLERRM);
END;
BEGIN
--l_cmd := 'INSERT INTO '||l_rmsschema||'.USER_ATTRIB(USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
l_cmd := 'MERGE INTO '||l_rmsschema||'.USER_ATTRIB TGT';
l_cmd := l_cmd || ' USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM '||l_rmsschema||'.NEW_USER_CREATION WHERE user_id=''' || A_REC.USER_ID || ''') SRC';
l_cmd := l_cmd || ' ON (TGT.USER_ID = SRC.USER_ID )';
l_cmd := l_cmd || ' WHEN NOT MATCHED THEN';
l_cmd := l_cmd || ' INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL)';
l_cmd := l_cmd || ' VALUES ('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
dbms_output.put_line(l_cmd||';');
EXECUTE immediate(l_cmd);
COMMIT;
--CR_SYNONYMS
BEGIN
declare
missing_object varchar2(128);
prefix1 varchar2(128);
prefix2 varchar2(128);
cursor c_get_missing_object is
select object_name
from dba_objects
where owner = upper(l_rmsschema)
and object_type in ('TABLE', 'VIEW', 'CLUSTER', 'FUNCTION', 'PACKAGE', 'PROCEDURE', 'SEQUENCE', 'TYPE')
and object_name not like 'DBC_%'
and object_name not like 'BIN$%'
MINUS
select object_name
from dba_objects
where owner = upper(l_username)
order by 1;
begin
if l_username <> '&_USER' then
prefix1:='"' || l_username || '".';
else
prefix1:='';
end if;
if l_rmsschema <> '&_USER' then
prefix2:='"' || l_rmsschema || '".' ;
else
prefix2:='';
end if;
open c_get_missing_object;
LOOP
fetch c_get_missing_object into missing_object;
--When at end of objects, exit
if c_get_missing_object%NOTFOUND then
exit;
end if;
BEGIN
execute immediate 'CREATE SYNONYM '||prefix1||'"'||missing_object||'" FOR '||prefix2||'"'||missing_object||'"';
dbms_output.put_line('Created synonym '||prefix1||missing_object||' pointing to '||prefix2||missing_object);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Create synonym FAILED '||missing_object||' '||SQLCODE||' - '||SQLERRM);
END;
END LOOP;
close c_get_missing_object;
end;
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR RMS: INSERT USER_ATTRIB: '||SQLERRM);
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
END;
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT ;
END;
END LOOP;
-- RMS Role Assignment-------------------------------------------------------------------------
FOR A_REC IN C_GET_ROLE_DETAIL
LOOP
-- RMS Role Assignment-------------------------------------------------------------------------
begin
l_cmd := 'grant '|| A_REC.GRANTED_ROLE ||' to "'||A_REC.USER_ID||'"';
dbms_output.put_line(l_cmd||';');
execute immediate (l_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : GRANT PRIVILEGES : '||SQLERRM);
end;
end loop;
commit;
EXCEPTION
WHEN utl_file.invalid_path THEN
raise_application_error(-20000, 'Invalid path. Create directory or set UTL_FILE_DIR.');
WHEN OTHERS THEN
dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
-----Adding user to groups-----------------------------------------------------------------------
FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
LOOP
BEGIN
add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
dbms_output.put_line(add_user_to_group_cmd||';');
execute immediate (add_user_to_group_cmd);
exception
when others then
dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);
END;
END LOOP;
COMMIT;
END;
/
I had spooled the output into a log file:Here is part of the log file:
Enter value for rmsschema: prod
Enter value for userid: SCOTT
Enter value for password: scott
Enter value for new_user_name: scott
Enter value for emailid: scott#test
Enter value for referenced_schema_name: 23093
1404
8322//These are the two values that are returned by the cursor and after that should be inserted into the table SEC_USER_GROUP but it's somehow getting skipped.////
TRUNCATE TABLE prod.NEW_USER_CREATION
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('SCOTT','scott','scott','scott#test','TEST_USER_ROLE');
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE) VALUES('SCOTT','scott','scott','scott#test','CUSTOMER_ROLE');
Creating RMS
CREATE USER "SCOTT" identified by "scott" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01;
MERGE INTO prod.USER_ATTRIB TGT USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM prod.NEW_USER_CREATION WHERE user_id='SCOTT') SRC ON (TGT.USER_ID = SRC.USER_ID ) WHEN NOT
MATCHED THEN INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES ('SCOTT','scott','1','scott#test');
//Synonyms for the user created
Created synonym "SCOTT".AA_XX_ITEM pointing to "prod".AA_XX_ITEM
Created synonym "SCOTT".ACC_VALIDATE_API pointing to "prod".ACC_VALIDATE_API
Created synonym "SCOTT".ADDR pointing to "prod".ADDR
Created synonym "SCOTT".ADDRESS_SQL pointing to "prod".ADDRESS_SQL
.................................................................
grant TEST_USER_ROLE to "SCOTT";
grant CUSTOMER_ROLE to "SCOTT";
PL/SQL procedure successfully completed.
As seen above the last part of the code doesn't get executed even though the cursor returns rows.

Drop table having name: <table_name>_(sysdate-1) only if the table exist

I need to drop a table only if the table exist, can do it using plsql block
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE <table_name>;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END
But in my case the table name has sysdate (02062017) eg table001_02072017 and i need to delete all such tables with sysdate-1.
How can i do so?
You can find the table with the given pattern from user_tables dictionary table and loop on the result to drop each one by one.
begin
for t in (select table_name from user_tables
where table_name like '%\_'||to_char(sysdate-1,'mmddyyyy') escape '\')
loop
execute immediate 'drop table ' || t.table_name;
end loop;
exception
/* Handle your exceptions here. */
end;
/
Using WHEN OTHERS in your exception handling is discouraged. You should explicitly handle the errors.
Dynamic sql will help you here just use
execute immediate 'drop table ' || table_name;
inside your procedure

How to create a procedure in an oracle sql script and use it inside the script?

I want to create a script for my oracle DB, which drops tables. If the table does not exist, the script won't exit as fail, just print a text: "does not exists".
The script is the following:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE mytable';
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
END;
I want to drop a lot of table in one script, and I don't want to write these lines more than once.
Is there any way, to write it to a procedure or function which gets a parameter (the name of the table), and call this procedure in that script?
Maybe something like this:
drop_table_procedure('mytableA');
drop_table_procedure('mytableB');
Or maybe a procedure, which gets an undefined size list (like in java: String ... table names):
drop_tables_procedure('mytableA','mytableB');
Please give me some examples.
Thanks!
Yes, you can declare a "temporary" procedure in an anonymous PL/SQL block:
DECLARE
PROCEDURE drop_if_exists(p_tablename VARCHAR)
IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE '||p_tablename;
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
END;
BEGIN
drop_if_exists('TABLE_1');
drop_if_exists('TABLE_2');
END;
/
in execute immediate you need add name of database object.
here's the script
create table t1 (col1 int);
create table t2 (col1 int);
create procedure drop_my_table(av_name varchar2)
as
begin
EXECUTE IMMEDIATE 'DROP TABLE '||av_name;
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
end drop_my_table;
declare
type array_t is varray(2) of varchar2(30);
atbls array_t := array_t('t1', 't2');
begin
for i in 1..atbls.count loop
drop_my_table(atbls(i));
end loop;
end;
You can use below one also
create or replace PROCEDURE drop_if_exists(p_tablename in VARCHAR)
IS
v_var1 number;
begin
select 1 into v_var1 from user_tables where table_name=upper(p_tablename);
if v_var1=1
then
EXECUTE IMMEDIATE 'DROP TABLE '||p_tablename;
DBMS_Output.Put_Line(' table dropped');
else
DBMS_Output.Put_Line(' table not exist');
end if;
exception
when others then
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
end;
Call procedure
begin
drop_if_exists('emp');
end;
/

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;