问题
I need to create an oracle table if it doesn't exists in the Oracle Database and if the table exists then don't do anything, So for that I wrote an anonymous block that works in SQL Developer if I fire that query twice or thrice I don't get any exception in sql developer. This is the below query I wrote-
public static final String DATABASE_TABLE = "LnPData";
public static final String CREATE_SQL = "DECLARE " +
"t_count INTEGER; " +
"v_sql VARCHAR2(1000) := 'create table " +DATABASE_TABLE +
"(ID number(10,0), " +
"CGUID VARCHAR(255), " +
"PGUID VARCHAR(255), " +
"SGUID VARCHAR(255), " +
"USERID VARCHAR(255), " +
"ULOC VARCHAR(255), " +
"SLOC VARCHAR(255), " +
"PLOC VARCHAR(255), " +
"ALOC VARCHAR(255), " +
"SITEID VARCHAR(255), " +
"PRIMARY KEY ( ID ))'; " +
"BEGIN " +
"SELECT COUNT(*) " +
"INTO t_count " +
"FROM user_tables " +
"WHERE table_name = '" +DATABASE_TABLE + "'; " +
"IF t_count = 0 THEN " +
"EXECUTE IMMEDIATE v_sql; " +
"END IF; " +
"END; ";
I execute the above sql query like this in my java code- First time when I run my program, table gets created, but the second time when I try to run the same program, I always get the below exception.
// get the connection
LnPDataConstants.DB_CONNECTION = getDBConnection();
LnPDataConstants.STATEMENT = LnPDataConstants.DB_CONNECTION.createStatement();
LnPDataConstants.STATEMENT.executeUpdate(LnPDataConstants.CREATE_SQL);
And I always get sql exception as-
SQL Error: ORA-00955: name is already used by an existing object
00955. 00000 - "name is already used by an existing object"
Any suggestions why is it happening in the Java Code?
P.S. I don't want to drop the table
Updated Code:-
public static final String CREATE_SQL = "CREATE TABLE IF NOT EXISTS " +DATABASE_TABLE +
"(ID number(10,0), " +
" CGUID VARCHAR(255), " +
" PGUID VARCHAR(255), " +
" SGUID VARCHAR(255), " +
" USERID VARCHAR(255), " +
" ULOC VARCHAR(255), " +
" SLOC VARCHAR(255), " +
" PLOC VARCHAR(255), " +
" ALOC VARCHAR(255), " +
" SITEID VARCHAR(255), " +
" PRIMARY KEY ( ID ))";
回答1:
I also answered your other thread. Seems like that here you already figured out that you had one bracket to much in your query.
Your problem here is easy to solve:
If you check user_tables you will see that tables which were not created by using double quotes are always upper case - if you want a table that is case sensitive use CREATE TABLE "tAbLeNamE"(test number)
. You select the table as "LnPData" and the table contains an entry which is LNPDATA.
Solution would be to change LnPData into upper case or just change the where clause of your query:
"WHERE table_name = UPPER('" +DATABASE_TABLE + "'); " +
Answer also belongs to your other question java.sql.SQLException: ORA-00904.
回答2:
Use this script in PL/SQL:
DECLARE cnt NUMBER;
BEGIN
SELECT count(*) INTO cnt FROM all_tables WHERE table_name = '<TABLE-NAME>';
IF cnt = 0 THEN
EXECUTE IMMEDIATE 'CREATE TABLE <TABLE-NAME>(<COLUMN-DEFINITIONS>)';
END IF;
END;
Replacing <TABLE-NAME>
and <COLUMN-DEFINITIONS>
with the appropriate values.
回答3:
Firstly why do you need to do this at all? Your code implies that you are creating multiple identical tables all with different names. This sounds like my worst nightmare.
If I'm wrong and you're only creating one table then don't do it in code. Do it in the database first and then you're done. If I'm correct then normalise the table. Add an extra-column username
(you already have userid
?) or something like it and insert all your data that has this format into a single table. This table, once again, can already be created and there's no need to do it dynamically.
You might need more indexes if you normalise but it appears as though you might be missing some anyway are you really always going to have id
when you select from this table?
If you feel that you really have to do this in the application code then, as Matt suggests, don't do this in your application code. You'll need to grant create table privileges to the schema you're operating in.
Create a user that does have these privileges and add a stored procedure to do this to that user. Then grant your application schema execute privileges on that schema.
You should also be using the dbms_assert package to sanitize the input.
Lastly, Eggi is correct you need to uppercase object names, though dbms_assert
does this by default.
You should also note that calls to user_tables
or all_tables
will have a performance impact. Another reason not to do it in the application.
Putting this all together you get a stored procedure that looks something like this:
create or replace procedure create_the_table
( pTableName varchar2 ) is
declare
-- Sanitize the input.
l_table_name := dbms_assert.simple_sql_name(pTableName);
l_exists number;
begin
select count(*)
into l_exists
from all_tables
where owner = 'MY_APPLICATION_SCHEMA'
and table_name = l_table_name
;
if l_exists = 0 then
execute immediate 'create table ' || l_table_name ||
' ( ID number(10,0),
CGUID VARCHAR(255),
PGUID VARCHAR(255),
SGUID VARCHAR(255),
USERID VARCHAR(255),
ULOC VARCHAR(255),
SLOC VARCHAR(255),
PLOC VARCHAR(255),
ALOC VARCHAR(255),
SITEID VARCHAR(255),
PRIMARY KEY ( ID )
)';
-- need to grant permissions so that we can check if this
-- is run again.
execute immediate 'grant select on ' || l_table_name ||
' to my_application_user';
end if;
end;
/
Then
grant execute on create_the_table to my_application_user;
and to call...
begin
my_create_table_user.create_the_table(table_name);
end;
Basically my advice is:
- Don't do this at all
- If you have to do it do it in the database.
回答4:
in case anyone came with similar issue, this should help:
Oracle version:
DECLARE
NCOUNT NUMBER;
V_SQL LONG;
BEGIN
SELECT COUNT(*)
INTO NCOUNT
FROM USER_OBJECTS
WHERE OBJECT_NAME = 'tableName';
IF (NCOUNT <= 0) THEN
V_SQL := ' CREATE TABLE tableName(
column1,
column2,
column3,
column4,
column5,
column6 VARCHAR2(2))';
EXECUTE IMMEDIATE V_SQL;
END IF;
END;
Java version:
String sqlStanging = "DECLARE "
+"NCOUNT NUMBER; "
+"V_SQL LONG; "
+"BEGIN "
+"SELECT COUNT(*) INTO NCOUNT FROM USER_OBJECTS WHERE OBJECT_NAME = 'tableName' ;"
+"IF(NCOUNT <= 0) "
+"THEN "
+"V_SQL:=' "
+"CREATE TABLE tableName"
+"("
+" column1, "
+" column2, "
+" column3, "
+" column4, "
+" column5, "
+" column6 VARCHAR2(2))';"
+"EXECUTE IMMEDIATE V_SQL ;"
+"END IF; "
+"END; ";
来源:https://stackoverflow.com/questions/10771346/create-a-table-if-doesnt-exists-in-the-oracle-using-java