Fetching Indexnames from Table with Cursor - oracle

I would like to fetch all existing indexes (Bitmap Index Joins) from a table with a cursor and drop them. Well and the other way around, if and index does not exists, create them.
So far I was doing this with a procedure:
DECLARE
COUNT_INDEXES INTEGER;
BEGIN
SELECT COUNT(*)
INTO COUNT_INDEXES
FROM USER_INDEXES
WHERE INDEX_NAME = 'IDXNAME' ;
IF COUNT_INDEXES > 0 THEN
EXECUTE IMMEDIATE 'DROP INDEX IDXNAME';
END IF;
END;

here you go
declare
cursor c_idx is
select index_name
from user_indexes
where table_name = 'my_table_name';
begin
for x in c loop
execute immediate 'drop index '|| x.index_name;
end loop;
end;
/

Here is a script, that drops all the indexes of a chosen table. For re-creating them, you have to provide some more information. Do you want to create a index on every column?
DECLARE
l_table_name varchar2(20) := 'MY_TABLE';
BEGIN
FOR r_idx IN
SELECT INDEX_NAME
FROM USER_INDEXES
WHERE TABLE_NAME = l_table_name;
LOOP
EXECUTE IMMEDIATE 'DROP INDEX ' || r_idx.INDEX_NAME;
END;
END;

Related

execute immediate using cursor

I've number of tables that i want to drop some columns and add some another columns again. (oracle database)
All of tables are empty.
does it work??
DECLARE
CURSOR cursor_name
IS
SELECT TABLE_NAME
FROM SYS.ALL_TABLES
WHERE OWNER = 'username';
TN NVARCHAR2 (30);
TABLE_COUNT NUMBER (3);
TCDROP NVARCHAR2 (1000);
TCADD NVARCHAR2 (1000);
BEGIN
SELECT COUNT (1)
INTO TABLE_COUNT
FROM SYS.ALL_TABLES
WHERE OWNER = 'username';
OPEN cursor_name;
FOR i IN 1 .. TABLE_COUNT
LOOP
FETCH cursor_name INTO TN;
TCDROP := 'ALTER TABLE ' || TN || ' DROP (*columns list*);';
EXECUTE IMMEDIATE TCDROP;
TCADD :=
'ALTER TABLE ' || TN || ' ADD (*columns and datatype list*);';
EXECUTE IMMEDIATE TCADD;
EXIT WHEN cursor_name%NOTFOUND;
END LOOP;
CLOSE cursor_name;
END;
/
Yes, this will certainly work. I'd recommend to put in the owner/schema of the tables, though. Besides, it is unusual or unsafe to query the number of tables and the loop through the list. I'd put it in a simple for loop:
DECLARE
stmt VARCHAR2(1000);
BEGIN
FOR t IN (SELECT table_name FROM all_tables WHERE owner='XYZ') LOOP
stmt := 'ALTER TABLE '||owner||'.'||table_name||' DROP (*columns list*);';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE (stmt);
stmt:= 'ALTER TABLE '||owner||'.'||table_name||' ADD (*columns and datatype list*);';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE (stmt);
END LOOP;
END;
/

Oracle : Create Table as Select statement and Select query on created table in Single Stored Procedure

I want Stored Procedure which create Temporary table using Create Table ... Select ... Statement.
And then select the records from same created table.
And finally drop that created table...
I want all these functionality in same stored procedure.
I have create the following stored procedure. But i got the below error
PL/SQL: ORA-00942: table or view does not exist
This one is my Procedure
DECLARE
TEMP_TBL VARCHAR2(4000);
TBL_NAME VARCHAR2(200) := 'ABC_TEST';
BEGIN
TEMP_TBL := 'CREATE TABLE MY_TAB_COL AS(SELECT TABLE_NAME,COLUMN_NAME,DATA_TYPE,to_lob(DATA_DEFAULT) AS DATA_DEFAULT,NULLABLE FROM ALL_TAB_COLS WHERE TABLE_NAME=''' || TBL_NAME || ''')';
DBMS_OUTPUT.PUT_LINE(TEMP_TBL);
EXECUTE IMMEDIATE TEMP_TBL;
FOR DD_COLUMNS IN
(SELECT TABLE_NAME FROM MY_TAB_COL)
LOOP
DBMS_OUTPUT.PUT_LINE('DD_COLUMNS.TABLE_NAME');
END LOOP;
END;
I'm not sure why you want scenario like that, and not reccomend to use this code in production. I'm pretty sure in the 99% of the cases, this approach can be written in other way. But you can try the code bellow(Everything in your procedure should use dynamic sql)
declare
TBL_NAME varchar2(200) := 'ABC_TEST';
lv_Sql varchar2(4000);
begin
lv_Sql := 'CREATE TABLE MY_TAB_COL AS(SELECT TABLE_NAME,COLUMN_NAME,DATA_TYPE,to_lob(DATA_DEFAULT) AS DATA_DEFAULT,NULLABLE FROM ALL_TAB_COLS WHERE TABLE_NAME=''' ||
TBL_NAME || ''')';
DBMS_OUTPUT.PUT_LINE(lv_Sql);
execute immediate lv_Sql;
lv_Sql := 'begin
for DD_COLUMNS in (select TABLE_NAME from MY_TAB_COL) loop
DBMS_OUTPUT.PUT_LINE(DD_COLUMNS.TABLE_NAME);
end loop;
end;';
DBMS_OUTPUT.PUT_LINE(lv_Sql);
execute immediate lv_Sql;
for R in (select *
from user_objects
where object_name = 'MY_TAB_COL'
and object_type = 'TABLE') loop
DBMS_OUTPUT.PUT_LINE('drop table ' || R.Object_Name);
execute immediate 'drop table ' || R.Object_Name;
end loop;
end;

Oracle, drop table if it exists AND empty

I need to drop an Oracle table only if it 1) exists AND 2) Is NOT Empty
I wrote this code but if the table does not exist the code does not work:
DECLARE
rec_cnt1 NUMBER :=0;
rec_cnt2 NUMBER :=0;
BEGIN
SELECT COUNT(*) INTO rec_cnt1 FROM ALL_TABLES WHERE TABLE_NAME = 'MyTable';
SELECT num_rows INTO rec_cnt2 FROM USER_TABLES WHERE TABLE_NAME = 'MyTable';
IF rec_cnt1 = 1 THEN
BEGIN
IF rec_cnt2 < 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE MyTable cascade constraints';
END IF;
END;
END IF;
END;
/
What am I doing wrong? Please help.
Many thanks in advance
If you want to drop a table if it exists and empty(as the title of the question states) you could do this as follows:
create or replace procedure DropTableIfEmpty(p_tab_name varchar2)
is
l_tab_not_exists exception;
pragma exception_init(l_tab_not_exists, -942);
l_is_empty number;
l_query varchar2(1000);
l_table_name varchar2(32);
begin
l_table_name := dbms_assert.simple_sql_name(p_tab_name);
l_query := 'select count(*)
from ' || l_table_name ||
' where rownum = 1';
execute immediate l_query
into l_is_empty;
if l_is_empty = 0
then
execute immediate 'drop table ' || l_table_name;
dbms_output.put_line('Table "'|| p_tab_name ||'" has been dropped');
else
dbms_output.put_line('Table "'|| p_tab_name ||'" exists and is not empty');
end if;
exception
when l_tab_not_exists
then dbms_output.put_line('Table "'|| p_tab_name ||'" does not exist');
end;
When you are trying to drop a table, or query a table, which does not exist, Oracle will raise ORA-00942 exception and execution of a pl/sql block halts. We use pragma exception_init statement to associate ORA-00942 exception with our locally defined exception l_tab_not_exists in order to handle it appropriately.
Test case:
SQL> exec droptableifempty('tb_test'); -- tb_test table does not exists
Table "tb_test" does not exist
SQL> create table tb_test(
2 col number
3 );
table TB_TEST created.
SQL> exec droptableifempty('tb_test');
Table "tb_test" has been dropped
As a side note. Before querying num_rows column of [dba][all][user]_tables in order to determine number of rows a table has, you need to gather table statistic by executing dbms_stats.gather_table_stats(user, '<<table_name>>');, otherwise you wont get the actual number of rows.
In PL/SQL it is 'normal' to catch the exception.
If it is the correct exception then continue with the next part of your code.
DECLARE
rec_cnt1 NUMBER :=0;
rec_cnt2 NUMBER :=0;
BEGIN
SELECT COUNT(*) INTO rec_cnt1 FROM ALL_TABLES WHERE TABLE_NAME = 'MyTable';
SELECT num_rows INTO rec_cnt2 FROM USER_TABLES WHERE TABLE_NAME = 'MyTable';
IF rec_cnt1 = 1 THEN
BEGIN
IF rec_cnt2 < 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE MyTable cascade constraints';
END IF;
END;
END IF;
EXCEPTION
DBMS_OUTPUT.PUT_LINE('OH DEAR AN EXCEPTION WAS THROWN DUE TO' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('THE ORACLE CODE IS ' || SQLCODE);
-- if it is the oracle code for no such table, or no data selected
-- everything is fine.
END;
Of course it won't work if the table doesn't exist. Your second select would get a "No data found" exception, and you're not doing any exception handling. At least you should move the second select inside the first IF block. Best to add exception handling.
here is an easy way to solve this problem:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE [sssss]';
EXCEPTION WHEN OTHERS THEN NULL;
END;

anonymous block in 11g

I need a help on this.
I am trying to create a pl/sql anonymous block and when I run that it shows its completed but it don't run the code. It should give me an error saying name is already used by an existing object. Can someone help me on this.
I am actually creating procedures but just trying this code as a sample.
DECLARE
V_REF_TBL VARCHAR2(100);
V_SQL LONG;
begin
V_REF_TBL :='My_TABLE';
v_SQL :='truncate table '||V_REF_TBL ;
EXECUTE IMMEDIATE V_SQL;
EXECUTE IMMEDIATE 'CREATE TABLE '|| V_REF_TBL ||' parallel 9 nologging pctfree 0 as
select * from dual';
End;
Possibly you're looking for this:
<<my_block>>
Declare
table_name varchar2(30);
counter number;
Begin
table_name := 'my_table';
select count(*)
into counter
from user_tables
where table_name = Upper(Trim(my_block.table_name)) and
dropped = 'NO';
if counter = 0
then
execute immediate 'create table '||table_name||' as ... etc';
else
execute immediate 'truncate table '||table_name;
execute immediate 'insert into '||table_name' select ... etc';
end if;
end my_block;

If I drop a table and the table doesn't exist, I get an error

I need to drop a table and make a new one. If I drop the table and the table doesn't exist, I get an error
How can I check if the table exists?
I'm working on Oracle 11g
Thanks in advance.
You could do something like this:
DECLARE v_exist PLS_INTEGER;
BEGIN
SELECT COUNT(*) INTO v_exist
FROM user_tables
WHERE table_name = 'YOURTABLEHERE';
IF v_exist = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE YOURTABLEHERE';
END IF;
DECLARE
eTABLE_OR_VIEW_DOES_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT(eTABLE_OR_VIEW_DOES_NOT_EXIST, -942);
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SCHEMA.WHATEVER';
EXCEPTION
WHEN eTABLE_OR_VIEW_DOES_NOT_EXIST THEN
NULL;
END;
Share and enjoy.
something like
select count(*) from user_tables
where table_name= :table name
or
select count(*) from dba_tables
where owner = :table owner
and table_name = :table name
or a heavy-handed alternative:
begin execute immediate 'drop table table_name';
exception when others then null;
end;
I have been using the following procedure to take care of this:
create or replace procedure drop_table_if_exists ( p_table_name varchar2 )
is
it_exist number;
begin
select count(*)
into it_exists
from user_tables
where table_name = p_table_name
;
if it_exists >= 1 then
execute immediate 'drop table '||p_table_name;
end if;
end;
/
exec drop_table_if_exists ( 'TABLE_TO_DROP' );

Resources