creating table if not exist pl/sql with oracle 12c - oracle

i need to create a script that do this thing:
check if the table exists, if exists truncate(or drop and create) table else create that table. i try to search on internet but some code work for half or not work at all.
this is one of script i found on internet
DECLARE
val INTEGER := 0;
BEGIN
SELECT COUNT(*) INTO val FROM user_tables WHERE table_name = 'tabella';
IF val = 1 THEN
EXECUTE IMMEDIATE ('TRUNCATE TABLE tabella');
ELSE
EXECUTE IMMEDIATE ('CREATE TABLE tabella(idTabella INTEGER NOT NULL, campo VARCHAR(50)');
END IF;
END;

You don't need to check if the table exists; just try to truncate the table and if the table does not exist then catch the exception and create the table:
DECLARE
table_not_exists EXCEPTION;
PRAGMA EXCEPTION_INIT( table_not_exists, -942 );
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE tabella';
DBMS_OUTPUT.PUT_LINE( 'truncated' );
EXCEPTION
WHEN table_not_exists THEN
EXECUTE IMMEDIATE 'CREATE TABLE tabella ( idTabella INTEGER NOT NULL, campo VARCHAR(50) )';
DBMS_OUTPUT.PUT_LINE( 'created' );
END;
/
db<>fiddle

Since table names are saved as upper case strings, you should check them the same case. There are to ways you can do this:
You can write your table name in upper case like:
SELECT COUNT(*) INTO val FROM user_tables WHERE table_name = 'TABELLA';
You can lower case your table_name column so you can input it lower case all the time:
SELECT COUNT(*) FROM user_tables WHERE LOWER(table_name) = 'tabella';
Hope this helps.

The database defaults all names to UPPER_CASE. When you execute
CREATE TABLE tabella(...
the database actually creates the table with a name of TABELLA. This is fine - unless you quote the name of an object, by surrounding it in double-quotes, the database will automatically convert all names to upper case, and everything will work just fine. The only time you need to remember to use UPPER_CASE names is when you're accessing system tables or views, such as USER_TABLES. If you change the query in your script to
SELECT COUNT(*) INTO val FROM user_tables WHERE table_name = 'TABELLA';
I think you'll find it works just fine.

Related

What is the solution for the errors in this PL/SQL code? [duplicate]

The database-schema (Source and target) are very large (each has over 350 tables). I have got the task to somehow merge these two tables into one. The data itself (whats in the tables) has to be migrated. I have to be careful that there are no double entries for primary keys before or while merging the schemata. Has anybody ever done that already and would be able to provide me his solution or could anyone help me get a approach to the task? My approaches all failed and my advisor just tells me to get help online :/
To my approach:
I have tried using the "all_constraints" table to get all pks from my db.
SELECT cols.table_name, cols.column_name, cols.position, cons.status, cons.owner
FROM all_constraints cons, all_cons_columns cols
WHERE cols.owner = 'DB'
AND cons.constraint_type = 'P'
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner
ORDER BY cols.table_name, cols.position;
I also "know" that there has to be a sequence for the primary keys to add values to it:
CREATE SEQUENCE seq_pk_addition
MINVALUE 1
MAXVALUE 99999999999999999999
START WITH 1
INCREMENT BY 1
CACHE 20;
Because I am a noob if it comes to pl/sql (or sql in general)
So how/what I should do next? :/
Here is a link for an ERD of the database: https://ufile.io/9tdoj
virus scan: https://www.virustotal.com/#/file/dbe5f418115e50313a2268fb33a924cc8cb57a43bc85b3bbf5f6a571b184627e/detection
As promised to help in my comment, i had prepared a dynamic code which you can try to get the data merged with the source and target tables. The logic is as below:
Step1: Get all the table names from the SOURCE schema. In the query below you can you need to replace the schema(owner) name respectively. For testing purpose i had taken only 1 table so when you run it,remove the table name filtering clause.
Step2: Get the constrained columns names for the table. This is used to prepared the ON clause which would be later used for MERGE statement.
Step3: Get the non-constrainted column names for the table. This would be used in UPDATE clause while using MERGE.
Step4: Prepare the insert list when the data doesnot match ON conditon of MERGE statement.
Read my inline comments to understand each step.
CREATE OR REPLACE PROCEDURE COPY_TABLE
AS
Type OBJ_NME is table of varchar2(100) index by pls_integer;
--To hold Table name
v_obj_nm OBJ_NME ;
--To hold Columns of table
v_col_nm OBJ_NME;
v_othr_col_nm OBJ_NME;
on_clause VARCHAR2(2000);
upd_clause VARCHAR2(4000);
cntr number:=0;
v_sql VARCHAR2(4000);
col_list1 VARCHAR2(4000);
col_list2 VARCHAR2(4000);
col_list3 VARCHAR2(4000);
col_list4 varchar2(4000);
col_list5 VARCHAR2(4000);
col_list6 VARCHAR2(4000);
col_list7 VARCHAR2(4000);
col_list8 varchar2(4000);
BEGIN
--Get Source table names
SELECT OBJECT_NAME
BULK COLLECT INTO v_obj_nm
FROM all_objects
WHERE owner LIKE 'RU%' -- Replace `RU%` with your Source schema name here
AND object_type = 'TABLE'
and object_name ='TEST'; --remove this condition if you want this to run for all tables
FOR I IN 1..v_obj_nm.count
loop
--Columns with Constraints
SELECT column_name
bulk collect into v_col_nm
FROM user_cons_columns
WHERE table_name = v_obj_nm(i);
--Columns without Constraints remain columns of table
SELECT *
BULK COLLECT INTO v_othr_col_nm
from (
SELECT column_name
FROM user_tab_cols
WHERE table_name = v_obj_nm(i)
MINUS
SELECT column_name
FROM user_cons_columns
WHERE table_name = v_obj_nm(i));
--Prepare Update Clause
FOR l IN 1..v_othr_col_nm.count
loop
cntr:=cntr+1;
upd_clause := 't1.'||v_othr_col_nm(l)||' = t2.' ||v_othr_col_nm(l);
upd_clause:=upd_clause ||' and ' ;
col_list1:= 't1.'||v_othr_col_nm(l) ||',';
col_list2:= col_list2||col_list1;
col_list5:= 't2.'||v_othr_col_nm(l) ||',';
col_list6:= col_list6||col_list5;
IF (cntr = v_othr_col_nm.count)
THEN
--dbms_output.put_line('YES');
upd_clause:=rtrim(upd_clause,' and');
col_list2:=rtrim( col_list2,',');
col_list6:=rtrim( col_list6,',');
END IF;
dbms_output.put_line(col_list2||col_list6);
--dbms_output.put_line(upd_clause);
End loop;
--Update caluse ends
cntr:=0; --Counter reset
--Prepare ON clause
FOR k IN 1..v_col_nm.count
loop
cntr:=cntr+1;
--dbms_output.put_line(v_col_nm.count || cntr);
on_clause := 't1.'||v_col_nm(k)||' = t2.' ||v_col_nm(k);
on_clause:=on_clause ||' and ' ;
col_list3:= 't1.'||v_col_nm(k) ||',';
col_list4:= col_list4||col_list3;
col_list7:= 't2.'||v_col_nm(k) ||',';
col_list8:= col_list8||col_list7;
IF (cntr = v_col_nm.count)
THEN
--dbms_output.put_line('YES');
on_clause:=rtrim(on_clause,' and');
col_list4:=rtrim( col_list4,',');
col_list8:=rtrim( col_list8,',');
end if;
dbms_output.put_line(col_list4||col_list8);
-- ON clause ends
--Prepare merge Statement
v_sql:= 'MERGE INTO '|| v_obj_nm(i)||' t1--put target schema name before v_obj_nm
USING (SELECT * FROM '|| v_obj_nm(i)||') t2-- put source schema name befire v_obj_nm here
ON ('||on_clause||')
WHEN MATCHED THEN
UPDATE
SET '||upd_clause ||
' WHEN NOT MATCHED THEN
INSERT
('||col_list2||','
||col_list4||
')
VALUES
('||col_list6||','
||col_list8||
')';
dbms_output.put_line(v_sql);
execute immediate v_sql;
end loop;
End loop;
END;
/
Execution:
exec COPY_TABLE
Output:
anonymous block completed
PS: i have tested this with a table with 2 columns out of which i was having unique key constraint .The DDL of table is as below:
At the end i wish you could understand my code(you being a noob) and implement something similar if the above fails for your requirement.
CREATE TABLE TEST
( COL2 NUMBER,
COLUMN1 VARCHAR2(20 BYTE),
CONSTRAINT TEST_UK1 UNIQUE (COLUMN1)
) ;
Oh dear! Normally, such a question would be quickly closed as "too broad", but we need to support victims of evil advisors!
As for the effort, I would need a week full time for an experienced expert plus two days quality checking for an experierenced QA engineer.
First of all, there is no way that such a complex data merge will work on the first try. That means that you'll need test copies of both schemas that can be easily rebuild. And you'll need a place to try it out. Normally this is done with an export of both schemas and an empty dev database.
Next, you need both schemas close enough to be able to compare the data. I'd do it with an import of the export files mentione above. If the schema names are identical than rename one during import.
Next, I'd doublecheck if the structure is really identical, with queries like
SELECT a.owner, a.table_name, b.owner, b.table_name
FROM all_tables a
FULL JOIN all_tables b
ON a.table_name = b.table_name
AND a.owner = 'SCHEMAA'
AND b.owner = 'SCHEMAB'
WHERE a.owner IS NULL or b.owner IS NULL;
Next, I'd check if the primary and unique keys have overlaps:
SELECT id FROM schemaa.table1
INTERSECT
SELECT id FROM schemab.table1;
As there are 300+ tables, I'd generate those queries:
DECLARE
stmt VARCHAR2(30000);
n NUMBER;
schema_a CONSTANT VARCHAR2(128 BYTE) := 'SCHEMAA';
schema_b CONSTANT VARCHAR2(128 BYTE) := 'SCHEMAB';
BEGIN
FOR c IN (SELECT owner, constraint_name, table_name,
(SELECT LISTAGG(column_name,',') WITHIN GROUP (ORDER BY position)
FROM all_cons_columns c
WHERE s.owner = c.owner
AND s.constraint_name = c.constraint_name) AS cols
FROM all_constraints s
WHERE s.constraint_type IN ('P')
AND s.owner = schema_a)
LOOP
dbms_output.put_line('Checking pk '||c.constraint_name||' on table '||c.table_name);
stmt := 'SELECT count(*) FROM '||schema_a||'.'||c.table_name
||' JOIN '||schema_b||'.'||c.table_name
|| ' USING ('||c.cols||')';
--dbms_output.put_line('Query '||stmt);
EXECUTE IMMEDIATE stmt INTO n;
dbms_output.put_line('Found '||n||' overlapping primary keys in table '||c.table_name);
END LOOP;
END;
/
1st of all, for 350 tables, most probably, would need an dynamic SQL.
Declare a CURSOR or a COLLECTION - table of VARCHAR2 with all table names.
Declare a string variable to build the dynamic SQL.
loop through the entire list of the tables name and, for each table generates a string which will be executed as SQL with EXECUTE IMMEDIATE command.
The dynamic SQL which will be built, should insert the values from source table into the target table. In case the PK already exists, in target table, should be checked the field which represents the last updated date and if in source table it is bigger than in target table, then perform an update in target table, else, do nothing.

Create 'TABLE AS' in PL/SQL block

My query is simple but PL/SQL code block is expecting 'INTO' statement.
Here is my query:
DECLARE
yesterdays_date DATE := SYSDATE-1;
start_date DATE :='01/JAN/2013';
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE P2P_DATA';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
--if table not found DO NOTHING AND MOVE ON
--dbms_output.put_line('HELLO');
NULL;
END IF;
---------------------------create new table here-------------------
CREATE TABLE P2P_DATA AS
SELECT
GM_NAME,
NEW_SKILL,
WEEK_DATE,
TOR_MWF
FROM TEST_TABLE
WHERE WEEK_DATE BETWEEN start_date AND yesterdays_date;
END;
it gives the COMPILE time error:
FOUND CREATE: EXPECTING END SELECT or (BEGIN CASE CLOSE CONTINUE DECLARE ... ETC)
I am simply setting the dates in the declaration block and then creating a new table as a result of the select statement. any ideas how to accomplish this task?
This does the same thing but avoids the execute immediate and overhead of creating and dropping tables.
DECLARE
yesterdays_date DATE := SYSDATE-1;
start_date DATE :='01/JAN/2013';
BEGIN
--clear out old data------
DELETE from P2P_DATA;
---------------------------insert new data here-----------------
INSERT INTO P2P_DATA
SELECT
GM_NAME,
CASE WHEN SUBSTR(CST_NAME,0,5) = 'A'
THEN 'BVG1' ELSE SUBSTR(CST_NAME,0,5) END AS CST_NAME,
NEW_SKILL,
WEEK_DATE,
TOR_MWF,
TOR_MA,
TOR_DL
FROM TEST_TABLE
WHERE WEEK_DATE BETWEEN start_date AND yesterdays_date;
END;
--do your commit outside the transaction just in case
Even better just create a view and avoid the whole table thing when all you want is a subset.
CREATE VIEW VW_P2P_DATA
AS
SELECT
GM_NAME,
CASE WHEN SUBSTR(CST_NAME,0,5) = 'A'
THEN 'BVG1' ELSE SUBSTR(CST_NAME,0,5) END AS CST_NAME,
NEW_SKILL,
WEEK_DATE,
TOR_MWF,
TOR_MA,
TOR_DL
FROM TEST_TABLE
WHERE WEEK_DATE BETWEEN TO_DATE('01/JAN/2013','DD/MON/YYYY') AND SYSDATE-1;
You can not do DDL queries within a PL/SQL block; if you need to do so, you have to use dinamic SQL; for example, you could use:
execute immediate '
CREATE TABLE P2P_DATA AS
SELECT
GM_NAME,
NEW_SKILL,
WEEK_DATE,
TOR_MWF
FROM TEST_TABLE
WHERE WEEK_DATE BETWEEN start_date AND yesterdays_date;
';
However, please consider solutions different from create/drop tables on the fly if you can
Actually, I'll put this as an answer instead of a comment ...
I'd recommend avoiding the PL/SQL entirely ... just do the following:
truncate table P2P_DATA;
insert into P2P_DATA
SELECT
GM_NAME,
NEW_SKILL,
WEEK_DATE,
TOR_MWF
FROM TEST_TABLE
WHERE WEEK_DATE BETWEEN to_date('01/JAN/2013','dd/MON/yyyy') AND SYSDATE-1;
Simpler, cleaner, and faster. ;)

Can I directly define a trigger in all_triggers table on a table?

I am performing an archival process on a huge database and it involves deleting the production active table and renaming another table to be the new production table. When dropping the production active table, the triggers also get deleted. So I am just taking a backup of the triggers defined on my table using
select * from all_triggers where table_name=mytablename;
My question is, can I directly copy these triggers in to the all_triggers table after I rename my other table to be the new production active table? Will the triggers still work?
Same question for defining indexes and constraints too.
Copying the triggers from one table to another can be done by copying DDL, and not updating all_triggers table. This can be done by using DBMS_METADATA.
The closest practical example I found here: Copy Triggers when you Copy a Table
The following script can be amended as per your need:
declare
p_src_tbl varchar2(30):= 'PERSONS'; --your table name
p_trg_tbl varchar2(30):= 'PSN2'; --your trigger name
l_ddl varchar2(32000);
begin
execute immediate 'create table '||p_trg_tbl||' as select * from '||p_src_tbl||' where 1=2';
for trg in (select trigger_name from user_triggers where table_name = p_src_tbl) loop
l_ddl:= cast(replace(replace(dbms_metadata.get_ddl( 'TRIGGER', trg.trigger_name),p_src_tbl,p_trg_tbl),trg.trigger_name,substr(p_trg_tbl||trg.trigger_name, 1, 30)) as varchar2);
execute immediate substr(l_ddl, 1, instr(l_ddl,'ALTER TRIGGER')-1);
end loop;
end;
/
No, you cannot directly manipulate data dictionary tables. You can't insert data directly into all_triggers (the same goes for any data dictionary table). I guess you probably could given enough hacking. It just wouldn't work and would render your database unsupported.
The correct way to go is to script out your triggers and reapply them later. If you want to do this programmatically, you can use the dbms_metadata package. If you want to get the DDL for each of the triggers on a table, you can do something like
select dbms_metadata.get_ddl( 'TRIGGER', t.trigger_name, t.owner )
from all_triggers t
where table_owner = <<owner of table>>
and table_name = <<name of table>>
To replicate your scenario i have prepared below snippet. Let me know if this helps.
--Simple example to copy Trigger from one table to another
CREATE TABLE EMP_V1 AS
SELECT * FROM EMP;
--Creating Trigger on Old Table for Example purpose
CREATE OR REPLACE TRIGGER EMP_OLD_TRIGGER
AFTER INSERT OR UPDATE ON EMP FOR EACH ROW
DECLARE
LV_ERR_CODE_OUT NUMBER;
LV_ERR_MSG_OUT VARCHAR2(2000);
BEGIN
dbms_output.put_line('Your code for data Manipulations');
--Like Insert update or DELETE activities
END;
-- To replace this trigger for emp_v2 table
set serveroutput on;
DECLARE
lv_var LONG;
BEGIN
FOR i IN (
SELECT OWNER,TRIGGER_NAME,DBMS_METADATA.GET_DDL('TRIGGER','EMP_OLD_TRIGGER') ddl_script FROM all_triggers
WHERE OWNER = 'AVROY') LOOP
NULL;
lv_var:=REPLACE(i.ddl_script,'ON EMP FOR EACH ROW','ON EMP_V1 FOR EACH ROW');
dbms_output.put_line(substr(lv_var,1,INSTR(lv_var,'ALTER TRIGGER',1)-1));
EXECUTE IMMEDIATE 'DROP TRIGGER '||I.TRIGGER_NAME;
EXECUTE IMMEDIATE lv_var;
END LOOP;
END;
--Check if DDL manipulation has been done for not
SELECT OWNER,TRIGGER_NAME,DBMS_METADATA.GET_DDL('TRIGGER','EMP_OLD_TRIGGER') ddl_script FROM all_triggers
WHERE OWNER = 'AVROY';
---------------------------------OUTPUT----------------------------------------
"
CREATE OR REPLACE TRIGGER "AVROY"."EMP_OLD_TRIGGER"
AFTER INSERT OR UPDATE ON EMP_V1 FOR EACH ROW
DECLARE
LV_ERR_CODE_OUT NUMBER;
LV_ERR_MSG_OUT VARCHAR2(2000);
BEGIN
dbms_output.put_line('Your code for data Manipulations');
--Like Insert update or DELETE activities
END;
"
-----------------------------OUTPUT----------------------------------------------

Oracle - drop multiple table in a single query

I have fifty tables in a database, in that I need only six tables.
How can I delete remaining tables by one single query?
You can generate a list of DROP TABLE commands with the query below:
SELECT 'DROP TABLE ' || table_name || ';' FROM user_tables;
After that you remove your six tables you want to keep and execute the other commands. Or you add a WHERE table_name NOT IN (...) clause to the query.
Hope it helps.
Use something like this, as there is no direct command or way in oracle to do this
begin
for rec in (select table_name
from all_tables
where table_name like '%ABC_%'
)
loop
execute immediate 'drop table '||rec.table_name;
end loop;
end;
/
To expand on the answer,
for Oracle 10 versions and later, dropped tables are not deleted permanently, but moved to recycled bin. To truly delete tables need to add optional parameter PURGE.
Expanding on the accepted answer :
SELECT 'DROP TABLE ' || table_name || ' PURGE ;' DB_DEATH FROM user_tables;
First Run this query with table names that you want to keep.
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_schema = 'mydatabase' AND table_name not in ('table1', 'table2', 'table3');
This query will give you DROP table query.
Select from the list on the left all the tables you want to drop. Drag and drop them in your worksheet. Select Object Name from the pop-up window
Press the Edit menu and select Replace.
Type in the find field the comma symbol ,
Type in the replace field the following text ;\ndrop table . Note that there is a space after the word table. Replace all.
Type drop table before your first table and ; after your last one.
You are ready to drop your tables.
DECLARE
TYPE bulk_array is table of ALL_TABLES.TABLE_NAME%type;
array bulk_array;
BEGIN
SELECT OWNER ||'.'|| TABLE_NAME BULK COLLECT
INTO array
FROM ALL_TABLES
WHERE TABLE_NAME LIKE '%%';--HERE U WILL PUT YOUR CONDITIONS.
FOR i IN array.FIRST..array.LAST LOOP
EXECUTE IMMEDIATE 'DROP TABLE '|| array(i) || ' PURGE'; --Specify PURGE if you want to drop the table and release the space associated
END LOOP;
END;
If the tables you want to keep are keep_tab1, keep_tab2, etc. or start with ASB..
use regexp_like. Here just to show an example with regexp_like
The loop continues even when an error occurs dropping one of the tables.You may
have to run this script multiple times as errors may occur when dropping a primary table without having dropped the referential tables first.
begin
for rec in (
select table_name from user_tables
where not
regexp_like(table_name, 'keep_tab1|keep_tab2|^ASB')
)
loop
begin
execute immediate 'drop table '||rec.table_name;
exception when others then
dbms_output.put_line(rec.table_name||':'||sqlerrm);
end;
end loop;
end;

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