Drop a Temp Table If Exists In Oracle - oracle

I am a new user to Oracle but have advanced knowledge of SQL Server. When working with temp tables in SQL Server we would always check to see if the table existed and drop it if it did before creating a new one. This would allow for the SQL script to be executed over and over without an error.
IF OBJECT_ID(N'tempdb..#CnsmrHstRwNm', N'U') IS NOT NULL
DROP TABLE #CnsmrHstRwNm;
CREATE TABLE #CnsmrHstRwNm;
I cannot seem to be able to do the same in Oracle. I have researched several ideas, including one who said it was a bad idea, but none of them have worked. Here is one scenario that I have tried. Does someone have any ideas?
I've referenced Oracle: If Table Exists and it seems like this could work, but I cannot figure out how to create the table after dropping it.
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || 'MY_TEMP_TABLE';
EXCEPTION
WHEN OTHERS THEN NULL;
CREATE GLOBAL TEMPORARY TABLE MY_TEMP_TABLE (a varchar2(1), b varchar2(1));
END;
Can anyone help?

I'd like to second anyone who said that - in Oracle - we don't drop/create tables within PL/SQL. That's just a bad idea. Create table once, use it as many times as you want. Delete (or truncate) its contents, insert/update rows, but don't (re)create it over and over again.
Anyway, here's how; I included message so that you could follow what's going on.
At first, table doesn't exist:
SQL> desc test
ERROR:
ORA-04043: object test does not exist
Run the script:
SQL> set serveroutput on
SQL> begin
2 begin
3 dbms_output.put_line('Trying to drop a table');
4 execute immediate 'drop table test';
5 dbms_output.put_line('Table dropped');
6 exception
7 when others then
8 dbms_output.put_line('Error when dropping the table: ' || sqlerrm);
9 null;
10 end;
11 dbms_output.put_line('Creating a table');
12 execute immediate 'create table test (a varchar2(1))';
13 dbms_output.put_line('Table created');
14 end;
15 /
Trying to drop a table
Error when dropping the table: ORA-00942: table or view does not exist
Creating a table
Table created
PL/SQL procedure successfully completed.
SQL> desc test
Name Null? Type
----------------------------------------- -------- ----------------------------
A VARCHAR2(1)
Right; table now exists. You'd use it and - later - run the script once again:
SQL> begin
2 begin
3 dbms_output.put_line('Trying to drop a table');
4 execute immediate 'drop table test';
5 dbms_output.put_line('Table dropped');
6 exception
7 when others then
8 dbms_output.put_line('Error when dropping the table: ' || sqlerrm);
9 null;
10 end;
11 dbms_output.put_line('Creating a table');
12 execute immediate 'create table test (a varchar2(1))';
13 dbms_output.put_line('Table created');
14 end;
15 /
Trying to drop a table
Table dropped
Creating a table
Table created
PL/SQL procedure successfully completed.
SQL>

Rather than using a GLOBAL TEMPORARY TABLE, if you use a PRIVATE TEMPORARY TABLE then it automatically drops when the transaction is completed:
CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp (
a varchar2(1), b varchar2(1)
);
Then when you COMMIT the table is automatically dropped (and you can recreate it in the next transaction without having to drop and recreate it).
However, if you do want a permanent table then use EXECUTE IMMEDIATE to drop and create it and catch (and ignore) the exception if the table does not exist:
DECLARE
does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(does_not_exist, -942);
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE MY_TEMP_TABLE';
EXCEPTION
WHEN does_not_exist THEN
NULL;
END;
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE MY_TEMP_TABLE (a varchar2(1), b varchar2(1))';
END;
/

Related

ORA-00942 error when referencing table after EXECUTE IMMEDIATE create table

I try to run the following snippet in PL/SQL Developer, but the last command throws an ORA-00942: table or view does not exist error message.
DECLARE
sqlCommandABC varchar2(30000) := 'create table ABC_TMP
tablespace &TBS_NORMAL_TABLES initrans 32 AS (SELECT ABC_ID from ABC where ID <=400000)';
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ABC_TMP';
EXCEPTION
WHEN OTHERS THEN NULL;
END;
EXECUTE IMMEDIATE sqlCommandABC;
COMMIT;
END;
/
DECLARE
sqlCommandDEF varchar2(30000) := 'create table DEF_TMP
tablespace &TBS_NORMAL_TABLES initrans 32 AS (SELECT DEF_ID from DEF where ID <=15000)';
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE DEF_TMP';
EXCEPTION
WHEN OTHERS THEN NULL;
END;
EXECUTE IMMEDIATE sqlCommandDEF;
COMMIT;
END;
/
DECLARE
sqlCommandXYZ varchar2(30000) := 'create table XYZ_TMP
tablespace &TBS_NORMAL_TABLES initrans 32 AS (select ID from XYZ where ABC_1 in (SELECT ABC_ID from ABC_TMP) or DEF_1 in (SELECT DEF_ID from DEF_TMP))';
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE XYZ_TMP';
EXCEPTION
WHEN OTHERS THEN NULL;
END;
EXECUTE IMMEDIATE sqlCommandXYZ;
COMMIT;
END;
/
I want to create two temporary tables by selecting data from the original table, with some condition according to the logic.
After the ABC_TMP and the DEF_TMP created, I need to use them in a condition for the select of the third temporary table.
The XYZ_TMP table has two conditions, one for the ABC_TMP records and another for the DEF_TMP records.
This third create table clause throws the error.
I know i could use the original selects here, but those are pretty complex and has a relatively high cost, so if it is possible i want to use the filtered tables. I also know that if I open a new session after the first two tables created it will work, but I want to execute these in one script.
according to the provided info, I understood that DEF_TMP and ABC_TMP is successfully created and thus available. in that case, there are two possibilities here.
First is XYZ table is not exists
Second is the user trying to execute this command does not have select grant.

Table exists in stored procedure while used in select but not when Used in Insert statement

My stored procedure is like this:
create or replace procedure tpk.sp_Test_proc
IS
err_code NUMBER;
err_msg VARCHAR (500);
v_tbl_cnt NUMBER;
v_tbl_valid NUMBER;
Begin
SELECT COUNT(*) INTO v_tbl_cnt FROM USER_TABLES
WHERE TABLE_NAME IN (UPPER('Tbl1'),UPPER('tbl2'),UPPER('tbl3'));
IF(v_tbl_cnt =3) THEN
EXECUTE IMMEDIATE 'TRUNCATE TABLE Tbl1';
EXECUTE IMMEDIATE 'TRUNCATE TABLE Tbl2';
EXECUTE IMMEDIATE 'TRUNCATE TABLE Tbl3';
EXECUTE IMMEDIATE 'DROP TABLE Tbl1';
EXECUTE IMMEDIATE 'DROP TABLE Tbl2';
EXECUTE IMMEDIATE 'DROP TABLE Tbl3';
EXECUTE IMMEDIATE
'CREATE global temporary TABLE tbl1
( Id Integer... )'
Insert into tbl1
Select * from another_schema.Dw_table /* In this line it throws error Table does not exist */
end if;
end;
I tired same table with store procedure only to fetch the data its working there but when I used in Insert statement it throws an error
PL/SQL: ORA-00942 table or view does not exist.
I am totally confused - what's wrong here?
Select * from another_schema.Dw_table
You don't have a privilege to select from that table. Even if you think you do (granted via a role), it won't work in stored procedures - you have to grant it directly to user you're connected to.
Besides, there's no point in truncating tables first, and dropping them next. Just drop them.
Furthermore, there's rarely need to create tables dynamically (the way you do it), especially global temporary tables. Create them once, use them many times. No dropping. No (re)creating them in PL/SQL.

Oracle create trigger error (bad bind variable)

I at trying to create trigger with the following code.
CREATE OR REPLACE TRIGGER MYTABLE_TRG
BEFORE INSERT ON MYTABLE
FOR EACH ROW
BEGIN
select MYTABLE_SEQ.nextval into :new.id from dual;
END;
I am getting error
Error(2,52): PLS-00049: bad bind variable 'NEW.ID'
Any ideas? Thanks.
It seems like the error code is telling you there's no such column ID in your table...
Somehow your environment is treating your code as SQL instead of a DDL statement. This works for me (running in sqlplus.exe from a command prompt):
SQL> create sequence mytable_seq;
Sequence created.
SQL> create table mytable (id number);
Table created.
SQL> CREATE OR REPLACE TRIGGER MYTABLE_TRG
2 BEFORE INSERT ON MYTABLE
3 FOR EACH ROW
4 BEGIN
5 select MYTABLE_SEQ.nextval into :new.id from dual;
6 END;
7 /
Trigger created.
Note the trailing "/" - this might be important in the application you are compiling this with.
if one would use proper naming convention the spotting of this type
of errors would be much easier ( where proper means using pre- and postfixes )
for generic object names hinting about their purpose better
i.e. something like this would have spotted the correct answer
--START -- CREATE A SEQUENCE
/*
create table "TBL_NAME" (
"TBL_NAME_ID" number(19,0) NOT NULL
, ...
*/
--------------------------------------------------------
-- drop the sequence if it exists
-- select * from user_sequences ;
--------------------------------------------------------
declare
c int;
begin
select count(*) into c from user_sequences
where SEQUENCE_NAME = upper('SEQ_TBL_NAME');
if c = 1 then
execute immediate 'DROP SEQUENCE SEQ_TBL_NAME';
end if;
end;
/
CREATE SEQUENCE "SEQ_TBL_NAME"
MINVALUE 1 MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 1
CACHE 20 NOORDER NOCYCLE ;
-- CREATE
CREATE OR REPLACE TRIGGER "TRG_TBL_NAME"
BEFORE INSERT
ON "TBL_NAME"
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE
tmpVar NUMBER;
BEGIN
tmpVar := 1 ;
SELECT SEQ_TBL_NAME.NEXTVAL INTO tmpVar FROM dual;
:NEW.TBL_NAME_ID := tmpVar;
END TRG_TBL_NAME;
/
ALTER TRIGGER "TRG_TBL_NAME" ENABLE;
-- STOP -- CREATE THE TRIGGER
If you're like me and your code should be working, try dropping the trigger explicitly before you re-create it. Stupid Oracle.

dropping a global temporary table

2 Separate questions.
I am using this script to drop a table [SOLVED]
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE_NAME';
DBMS_OUTPUT.PUT_LINE ('Global table TABLE_NAME Dropped');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ('Global table TABLE_NAME Doesn''t exist.');
END;
/
Is there anyway I can differentiate if table "doesn't exist" or it is being used in some other sessions (in that case it would locked and couldn't be deleted). I am not sure if I can see that table exists in user_tables. I am not fully aware of permissions.
I have added this code now
WHEN OTHERS THEN
i_code := SQLCODE;
v_errm := SUBSTR(SQLERRM, 1, 64);
if i_code = -942 THEN
DBMS_OUTPUT.PUT_LINE ('TABLE_NAME doesn''t exist. Script will continue to create it');
ELSE
DBMS_OUTPUT.PUT_LINE ('Error dropping temporary table. The error code is ' || i_code || '- ' || v_errm);
END IF ;
2. I see . at the end of each procedure like this
END PROCEDURE_NAME;
.
/
sho err;
I just don't understand why . is here. Is it syntax or what?
-- First Truncate temporary table
SQL> TRUNCATE TABLE test_temp1;
-- Then Drop temporary table
SQL> DROP TABLE test_temp1;
Step 1. Figure out which errors you want to trap:
If the table does not exist:
SQL> drop table x;
drop table x
*
ERROR at line 1:
ORA-00942: table or view does not exist
If the table is in use:
SQL> create global temporary table t (data varchar2(4000));
Table created.
Use the table in another session. (Notice no commit or anything after the insert.)
SQL> insert into t values ('whatever');
1 row created.
Back in the first session, attempt to drop:
SQL> drop table t;
drop table t
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
So the two errors to trap:
ORA-00942: table or view does not exist
ORA-14452: attempt to
create, alter or drop an index on temporary table already in use
See if the errors are predefined. They aren't. So they need to be defined like so:
create or replace procedure p as
table_or_view_not_exist exception;
pragma exception_init(table_or_view_not_exist, -942);
attempted_ddl_on_in_use_GTT exception;
pragma exception_init(attempted_ddl_on_in_use_GTT, -14452);
begin
execute immediate 'drop table t';
exception
when table_or_view_not_exist then
dbms_output.put_line('Table t did not exist at time of drop. Continuing....');
when attempted_ddl_on_in_use_GTT then
dbms_output.put_line('Help!!!! Someone is keeping from doing my job!');
dbms_output.put_line('Please rescue me');
raise;
end p;
And results, first without t:
SQL> drop table t;
Table dropped.
SQL> exec p;
Table t did not exist at time of drop. Continuing....
PL/SQL procedure successfully completed.
And now, with t in use:
SQL> create global temporary table t (data varchar2(4000));
Table created.
In another session:
SQL> insert into t values (null);
1 row created.
And then in the first session:
SQL> exec p;
Help!!!! Someone is keeping from doing my job!
Please rescue me
BEGIN p; END;
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
ORA-06512: at "SCHEMA_NAME.P", line 16
ORA-06512: at line 1
yes - the engine will throw different exceptions for different conditions.
you will change this part to catch the exception and do something different
EXCEPTION
WHEN OTHERS THEN
here is a reference
http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/07_errs.htm
The DECLARE GLOBAL TEMPORARY TABLE statement defines a temporary table for the current connection.
These tables do not reside in the system catalogs and are not persistent.
Temporary tables exist only during the connection that declared them and cannot be referenced outside of that connection.
When the connection closes, the rows of the table are deleted, and the in-memory description of the temporary table is dropped.
For your reference http://docs.oracle.com/javadb/10.6.2.1/ref/rrefdeclaretemptable.html
Down the apache server by running below in putty
cd $ADMIN_SCRIPTS_HOME
./adstpall.sh
Drop the Global temporary tables
drop table t;
This will workout..

How do I use CREATE OR REPLACE?

Am I correct in understanding that CREATE OR REPLACE basically means "if the object exists, drop it, then create it either way?"
If so, what am I doing wrong? This works:
CREATE TABLE foo (id NUMBER,
title VARCHAR2(4000) DEFAULT 'Default Title')
And this doesn't (ORA-00922: missing or invalid option):
CREATE OR REPLACE TABLE foo (id NUMBER,
title VARCHAR2(4000) DEFAULT 'Default Title')
Am I doing something stupid? I don't seem to be able to find much documentation about this syntax.
This works on functions, procedures, packages, types, synonyms, trigger and views.
Update:
After updating the post for the third time, I'll reformulate this:
This does not work on tables :)
And yes, there is documentation on this syntax, and there are no REPLACE option for CREATE TABLE.
One of the nice things about the syntax is that you can be sure that a CREATE OR REPLACE will never cause you to lose data (the most you will lose is code, which hopefully you'll have stored in source control somewhere).
The equivalent syntax for tables is ALTER, which means you have to explicitly enumerate the exact changes that are required.
EDIT:
By the way, if you need to do a DROP + CREATE in a script, and you don't care for the spurious "object does not exist" errors (when the DROP doesn't find the table), you can do this:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE owner.mytable';
EXCEPTION
WHEN OTHERS THEN
IF sqlcode != -0942 THEN RAISE; END IF;
END;
/
There is no create or replace table in Oracle.
You must:
DROP TABLE foo;
CREATE TABLE foo (....);
CREATE OR REPLACE can only be used on functions, procedures, types, views, or packages - it will not work on tables.
Following script should do the trick on Oracle:
BEGIN
EXECUTE IMMEDIATE 'drop TABLE tablename';
EXCEPTION
WHEN OTHERS THEN
IF sqlcode != -0942 THEN RAISE;
END IF;
END;
-- To Create or Replace a Table we must first silently Drop a Table that may not exist
DECLARE
table_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT (table_not_exist , -00942);
BEGIN
EXECUTE IMMEDIATE('DROP TABLE <SCHEMA>.<TABLE NAME> CASCADE CONSTRAINTS');
EXCEPTION WHEN table_not_exist THEN NULL;
END;
/
Does not work with Tables, only functions etc.
Here is a site with some examples.
A usefull procedure for oracle databases without using exeptions (under circumstances you have to replace user_tables with dba_tables and/or constrain the tablespace in the query):
create or replace procedure NG_DROP_TABLE(tableName varchar2)
is
c int;
begin
select count(*) into c from user_tables where table_name = upper(tableName);
if c = 1 then
execute immediate 'drop table '||tableName;
end if;
end;
If you are doing in code then first check for table in database
by using query
SELECT table_name
FROM user_tables
WHERE table_name = 'XYZ'
if record found then truncate table otherwise create Table
Work like Create or Replace.
You can use CORT (www.softcraftltd.co.uk/cort). This tool allows to CREATE OR REPLACE table in Oracle.
It looks like:
create /*# or replace */ table MyTable(
... -- standard table definition
);
It preserves data.
So I've been using this and it has worked very well: - it works more like a DROP IF EXISTS but gets the job done
DECLARE
VE_TABLENOTEXISTS EXCEPTION;
PRAGMA EXCEPTION_INIT(VE_TABLENOTEXISTS, -942);
PROCEDURE DROPTABLE(PIS_TABLENAME IN VARCHAR2) IS
VS_DYNAMICDROPTABLESQL VARCHAR2(1024);
BEGIN
VS_DYNAMICDROPTABLESQL := 'DROP TABLE ' || PIS_TABLENAME;
EXECUTE IMMEDIATE VS_DYNAMICDROPTABLESQL;
EXCEPTION
WHEN VE_TABLENOTEXISTS THEN
DBMS_OUTPUT.PUT_LINE(PIS_TABLENAME || ' NOT EXIST, SKIPPING....');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
END DROPTABLE;
BEGIN
DROPTABLE('YOUR_TABLE_HERE');
END DROPTABLE;
/
Hope this helps
Also reference:
PLS-00103 Error in PL/SQL Developer
'Create or replace table' is not possible. As others stated, you can write a procedure and/or use begin execute immediately (...). Because I don't see an answer with how to (re)create the table, I putted a script as an answer.
PS: in line of what jeffrey-kemp mentioned: this beneath script will NOT save data that is already present in the table you are going to drop. Because of the risk of loosing data, at our company it is only allowed to alter existing tables on the production environment, and it is not allowed to drop tables. By using the drop table statement, sooner or later you will get the company police standing at your desk.
--Create the table 'A_TABLE_X', and drop the table in case it already is present
BEGIN
EXECUTE IMMEDIATE
'
CREATE TABLE A_TABLE_X
(
COLUMN1 NUMBER(15,0),
COLUMN2 VARCHAR2(255 CHAR),
COLUMN3 VARCHAR2(255 CHAR)
)';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -955 THEN -- ORA-00955: object name already used
EXECUTE IMMEDIATE 'DROP TABLE A_TABLE_X';
END IF;
END;
I would do something like this
begin
for i in (select table_name from user_tables where table_name = 'FOO') loop
execute immediate 'drop table '||i.table_name;
end loop;
end;
execute immediate 'CREATE TABLE FOO (id NUMBER,
title VARCHAR2(4000)) ';
If this is for MS SQL.. The following code will always run no matter what if the table exist already or not.
if object_id('mytablename') is not null //has the table been created already in the db
Begin
drop table mytablename
End
Create table mytablename (...

Resources