dropping a global temporary table - oracle

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..

Related

Drop a Temp Table If Exists In 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;
/

DELETE FROM inside a PL/SQL Procedure Block

I am currently trying to delete all rows of a table that is linked to another one via foreign key.
My Code looks kinda like this:
CREATE OR REPLACE Procedure test
BEGIN
DELETE FROM person;
End;
/
The Errors says: ora-02292 integrity constraint violated - child record found
When I try to just diable the constraints then it says i cant 'ALTER' the table.
What do i have to do/change?
You shouldn't just disable constraint, because you'll leave child records orphans (there will be NO parent record for them). What will you do, then?
Correct way to handle it is to
delete children first
delete parents last
If foreign key constraint was created with the on delete cascade option, database would handle it for you.
P.S. As of "you can't ALTER the table" - that's not an Oracle error message. They have their codes, such as ORA-06550. It is difficult to guess what you actually did, and - if I had to guess - I'd say that you tried to do that within the procedure:
SQL> create table temp (id number constraint pkt primary key);
Table created.
SQL> begin
2 alter table temp disable constraint pkt;
3 end;
4 /
alter table temp disable constraint pkt;
*
ERROR at line 2:
ORA-06550: line 2, column 3:
PLS-00103: Encountered the symbol "ALTER" when expecting one of the following:
( begin case declare exit for goto if loop mod null pragma
raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
continue close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe purge
You'll need dynamic SQL to do that:
SQL> begin
2 execute immediate 'alter table temp disable constraint pkt';
3 end;
4 /
PL/SQL procedure successfully completed.
SQL>
But, once again, that's not the way you should handle this situation.

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.

Why EXECUTE IMMEDIATE is needed here?

I am a SQL Server user and I have a small project to do using Oracle, so I’m trying to understand some of the particularities of Oracle and I reckon that I need some help to better understand the following situation:
I want to test if a temporary table exists before creating it so I had this code here:
DECLARE
table_count INTEGER;
var_sql VARCHAR2(1000) := 'create GLOBAL TEMPORARY table TEST (
hello varchar(1000) NOT NULL)';
BEGIN
SELECT COUNT(*) INTO table_count FROM all_tables WHERE table_name = 'TEST';
IF table_count = 0 THEN
EXECUTE IMMEDIATE var_sql;
END IF;
END;
It works normally, so after I executed it once, I added an else statement on my IF:
ELSE
insert into test (hello) values ('hi');
Executed it again and a line was added to my test table.
Ok, my code was ready and working, so I dropped the temp table and tried to run the entire statement again, however when I do that I get the following error:
ORA-06550: line 11, column 19:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 11, column 7:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Then I changed my else statement to this and now it works again:
ELSE
EXECUTE IMMEDIATE 'insert into test (hello) values (''hi'')';
My question is why running individually I can simply use the insert instead of the EXECUTE IMMEDIATE and also why my SELECT statement right after BEGIN still works when all the rest appears to need EXECUTE IMMEDIATE to run properly?
The whole PL/SQL block is parsed at compile time, but the text within a dynamic statement isn't evaluated until runtime. (They're close to the same thing for an anonymous block, but still distinct steps).
Your if/else isn't evaluated until runtime either. The compiler doesn't know that the table will always exist by the time you do your insert, it can only check whether or not it exists at the point it parses the whole block.
If the table does already exist then it's OK; the compiler can see it, the block executes, your select gets 1, and you go into the else to do the insert. But if it does not exist then the parsing of the insert correctly fails with ORA-00942 at compile time and nothing in the block is executed.
Since the table creation is dynamic, all references to the table have to be dynamic too - your insert as you've seen, but also if you then query it. Basically it makes your code much harder to read and can hide syntax errors - since the dynamic code isn't parsed until run-time, and it's possible you could have a mistake in a dynamic statement in a branch that isn't hit for a long time.
Global temporary tables should not be created on-the-fly anyway. They are permanent objects with temporary data, specific to each session, and should not be created/dropped as part of your application code. (No schema changes should be made by your application generally; they should be confined to upgrade/maintenance changes and be controlled, to avoid errors, data loss and unexpected side effects; GTTs are no different).
Unlike temporary tables in some other relational databases, when you create a temporary table in an Oracle database, you create a static table definition. The temporary table is a persistent object described in the data dictionary, but appears empty until your session inserts data into the table. You create a temporary table for the database itself, not for every PL/SQL stored procedure.
Create the GTT once and make all your PL/SQL code static. If you want something closer to SQL Server's local temporary tables then look into PL/SQL collections.
PL/SQL: ORA-00942: table or view does not exist
It is compile time error, i.e. when the static SQL is parsed before even the GTT is created.
Let's see the difference between compile time and run time error:
Static SQL:
SQL> DECLARE
2 v number;
3 BEGIN
4 select empno into v from a;
5 end;
6 /
select empno into v from a;
*
ERROR at line 4:
ORA-06550: line 4, column 26:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 4, column 1:
PL/SQL: SQL Statement ignored
Dynamic SQL:
SQL> DECLARE
2 v number;
3 BEGIN
4 execute immediate 'select empno from a' into v;
5 end;
6 /
DECLARE
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at line 4
In the 1st PL/SQL block, there was a semantic check at compile time, and you could see the PL/SQL: ORA-00942: table or view does not exist. In the 2nd PL/SQL block, you do not see the PL/SQL error.
Bottomline,
At compile time it is not known if the table exists, as it is
only created at run time.
In your case, to avoid this behaviour, you need to make the INSERT also dynamic and use EXECUTE IMMEDIATE. In that way, you can escape the compile time error and get the table created dynamically and also do an insert into it dynamically at run time.
Having said that, the basic problem is that you are trying to create GTT on the fly which is not a good idea. You should create it once, and use it the way you want.
I have modified your code a litle bit and it works as far as logic is concerned. But as exp[lained in earlier posts creating GTT on the fly at run time is not at all is a goood idea.
--- Firstly by dropping the table i.e NO TABLE EXISTS in the DB in AVROY
SET serveroutput ON;
DECLARE
table_count INTEGER;
var_sql VARCHAR2(1000) := 'create GLOBAL TEMPORARY table TEST (
hello varchar(1000) NOT NULL)';
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE AVROY.TEST'; --Added the line just to drop the table as per your comments
SELECT COUNT(*)
INTO table_count
FROM all_tables
WHERE table_name = 'TEST'
AND OWNER = 'AVROY';
IF table_count = 0 THEN
EXECUTE IMMEDIATE var_sql;
dbms_output.put_line('table created');
ELSE
INSERT INTO AVROY.test
(hello
) VALUES
('hi'
);
END IF;
END;
--------------------OUTPUT-----------------------------------------------
anonymous block completed
table created
SELECT COUNT(*)
-- INTO table_count
FROM all_tables
WHERE table_name = 'TEST'
AND OWNER = 'AVROY';
COUNT(*)
------
1
--------
-- Second option is without DROPPING TABLE
SET serveroutput ON;
DECLARE
table_count INTEGER;
var_sql VARCHAR2(1000) := 'create GLOBAL TEMPORARY table TEST (
hello varchar(1000) NOT NULL)';
BEGIN
--EXECUTE IMMEDIATE 'DROP TABLE AVROY.TEST';
SELECT COUNT(*)
INTO table_count
FROM all_tables
WHERE table_name = 'TEST'
AND OWNER = 'AVROY';
IF table_count = 0 THEN
EXECUTE IMMEDIATE var_sql;
dbms_output.put_line('table created');
ELSE
INSERT INTO AVROY.test
(hello
) VALUES
('hi'
);
dbms_output.put_line(SQL%ROWCOUNT||' Rows inserted into the table');
END IF;
END;
-------------------------------OUTPUT-------------------------------------
anonymous block completed
1 Rows inserted into the table
---------------------------------------------------------------------------

How to use Oracle global temporary table?

I am attempting to use an Oracle global temporary table without physically creating a table in the database. The following code is not working. Can someone please explain the proper way to use global temporary tables?
declare
global temporary table my_temp_table(column1 number) on commit preserve rows;
begin
insert into my_temp_table (column1) values (1);
select * from my_temp_table;
end;
Try the below using execute immediate: it uses exception handler to bypass if table already exists; also note that you cannot use SQL select inside PLSQL
DECLARE
l_column1 number;
begin
begin
execute immediate 'create global temporary table my_temp_table(column1 number)
on commit preserve rows';
exception when others
then
dbms_output.put_line(sqlerrm);
end;
insert into my_temp_table (column1) values (1);
select * into l_column1 from my_temp_table where column1=1;
dbms_output.put_line('the temp value is '||l_column1);
end;
Unless you use EXECUTE IMMEDIATE you cannot create the table inside PL/SQL. Try this:
create global temporary table my_temp_table(column1 number) on commit preserve rows;
insert into my_temp_table (column1) values (1);
select * from my_temp_table;
Oracle global temp tables are a bit different than you might be expecting.
You need to create the table and declare it as a global temp table.
Here is a good resource:
http://www.oracle-base.com/articles/misc/temporary-tables.php

Resources