Oracle Create Table if it does not exist - java

Can anyone point me to the right syntax to use in order to create a table only if it does not currently exist in the database?
I'm currently programming a Java GUI in order to connect to Oracle and execute statements on my database and I'm wondering if I would implement this as a Java constraint or a SQLPlus constraint.

Normally, it doesn't make a lot of sense to check whether a table exists or not because objects shouldn't be created at runtime and the application should know what objects were created at install time. If this is part of the installation, you should know what objects exist at any point in the process so you shouldn't need to check whether a table already exists.
If you really need to, however,
You can attempt to create the table and catch the `ORA-00955: name is already used by an existing object" exception.
You can query USER_TABLES (or ALL_TABLES or DBA_TABLES depending on whether you are creating objects owned by other users and your privileges in the database) to check to see whether the table already exists.
You can try to drop the table before creating it and catch the `ORA-00942: table or view does not exist" exception if it doesn't.

#Archie I would like to answer your question.
#Piyas De Sorry for stealing your code :).
Just a little update of #Piyas De answer.
BEGIN
BEGIN
EXECUTE IMMEDIATE '<<Your table creation Statement>>';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE == -955 THEN
RAISE;
END IF;
END;
END;

You can do this with the Following Procedure -
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE <<Your Table Name>>';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
EXECUTE IMMEDIATE '<<Your table creation Statement>>';
END;
Hope this may help you.

try
{
// insert query for insert new record in your table
}
catch(Exception Ex)
{
//if it throw exception then catch it
int s=Ex.getErrorCode(); // check it for 903 error
//903 is table not existing error in oracle11g
// then create your new table here otherwise if table present then record get stored in database
}

Related

Spring Boot schema.sql, initializing database using PL/SQL

I am working on a project where I have to use Oracle Database 12c and I have to write all queries manually (so I can't use Spring Data).
For creating all tables and relationships, I use schema.sql and for template data I use data.sql.
And I have a problem with checking if table or data already exists.
In MySQL creating table would be like "create table if not exists".
In PL/SQL unfortunately, there is no equivalent for "if not exists". I replaced this functionality by:
begin
execute immediate
'CREATE TABLE user_data (
some data
)';
exception when others then if SQLCODE = -955 then null; else raise; end if;
end;
And it works when I run this script in SQL Developer or in Intellij's SQL console but the problem occurs when I want to run an application and Spring Boot tries to execute a script from schema.sql.
Output in terminal tells that:
nested exception is java.sql.SQLException: ORA-06550: line 8, column 4:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
* & = - + ; < / > at in is mod remainder not rem return
returning <an exponent (**)> <> or != or ~= >= <= <> and or
like like2 like4 likec between into using || multiset bulk
member submultiset
So it looks like Spring Boot doesn't know that it should run statement between "begin" and "end".
Any idea how can I manage the problem with database initialization ?
As a workaround, I could drop tables with every application run but it is not an optimal solution (and it wouldn't work when someone run the application for the first time).
Firstly, I would like to share two topics that seem to be relevant to this problem:
Unable to use "DROP TABLE IF EXISTS" in schema.sql for a Spring Boot application
executeSqlScript fails with Spring for PL/SQL block
There you will find a solution that should work: create a stored procedure and use in your schema.sql statement like
call recreate_table('USER_DATA','CREATE TABLE USER_DATA (SOME DATA)');
CALL statement is widely used across different databases, shortened to statement with only one semicolon and thus works well.
Secondly, I may only suppose, that the main problem is that anonymous blocks in PL/SQL (as well as other complex enough statements that may contain more than one semicolon) should be finished by a / character. I would recommend you to try to append this character to the end of your script, take a look at this and this answers, and if it does not work, create a stored procedure.
Also note that there is another way to check existence of the table (that comes over this wait for an exception pattern):
select count(*)
from user_tables t
where t.table_name = 'USER_DATA'
and rownum < 2

Checking for existing record in the SQL database

i have made a car rental management system in JAVA and SQL. The data base is working fine with no problems. i am stuck at checking if the data already exists in the database? like if a person enters NIC of 355353553.. it shouldn't be entered again.. Any suggestions about what i should do? thanks for any help!
You can set unique columns in mysql:
CREATE TABLE Cars
(
car_id int NOT NULL,
NIC int NOT NULL,
...
...
....
UNIQUE (car_id, NIC)
)
for more info, have a look here: Unique - sql syntax
Since you already have the database set to be unique, it sounds like you just want a method for handling errors in this case. I would use something like this personally, however I would bet that there is a more effective solution.
Create a method to get the count of the results from a query. In my example, I just called it countMethod. Have it return the number of rows from the query. You could alternatively use COUNT(*) from MySQL if you want to avoid using the java code. Here is some sudo code to get you started if you decided to try to implement.
int total = countMethod("SELECT id FROM the_table WHERE id=" + inputID);
if(total > 0) {
//Throw a warning message, it already exists
} else {
//Insert it into the database
}

How to suppress JDBC SQLWarnings?

I'm trying to convert a MySQL stored procedure to java code. It's pretty simple SQL. It creates three temporary tables and then does a select based on them. However, I'm having trouble with SQLWarnings related to Data Truncation being thrown while creating the last temp table.
I'm not looking for an explanation of the warnings themselves. I was getting the same warnings during execution of the stored procedure (due to improperly formatted datetime fields), only there it didn't cause me any problems. In the java version, after Statement.executeUpdate() throws an SQLWarning, the temp table I was attempting to create doesn't exist.
How can I suppress the SQLWarnings? I'd prefer to be able to log a message noting the warning text, but I want my temp table to successfully be created as well.
My code looks something like this:
sqlStatement = "create temporary table mytemptable as (select ...) ;";
try {
stmt.executeUpdate(sqlStatement);
// Throws SQLWarning about Data Truncation
} catch (SQLWarning sqlW) {
logInfo("SQLWarning Caught: " + sqlW.getMessage());
}
stmt.executeQuery("select * from mytemptable ");
// Throws SQLException because mytemptable doesn't exist
To me it's a little strange but the equivalent of this worked:
create temporary table mytemptable ignore select ...;
This way, no exception is thrown by jdbc, but you can still call getWarnings() on the Statement object to get a list of warnings that were ignored.
Thanks Norbert van Nobelen for helping me figure this out in the comments of the OP.

Delete Stored Procedure through remote

I am creating and testing a stored procedure through remote using JUnit , my user name is test and this is my code,
String sql = "create procedure test.firstProc3 AS select GETDATE()";
cursor.execute(sql);
cursor.executeQuery("firstProc3");
ANd to drop the procedure:
String dropSQL = "DROP PROCEDURE test.firstProc3";
cursor.execute(dropSQL);
Since the Drop Procedure is not working, I am unable to run the same SP for the second time ( new session) My error is:
There is already an object named 'firstProc3' in the database.
When I gave sp_help on the server side,
the table had the row with the value
firstProc3 test stored procedure
However when I give
DROP PROCEDURE test.firstProc3 in the Query analyzer, the row is getting deleted from the table.
What could be the issue in trying to do the same operation through Junit?
Are there any permissions to be set?
PS - the user test has the db_ddladmin enabled.
I managed to finally solve the problem by using the following :
declare #object_id int
select #object_id = object_id('test.firstProc5')
EXEC sp_MSdrop_object #object_id
GO
This is removing the data from the table too.And I am able to successfully run the Testcase multiple times !
Thanks for your help :)
The link I referred to is here, hope it helps someone:
http://www.mssqlcity.com/Articles/Undoc/SQL2000UndocSP.htm
Based upon the error message, I doubt it is a permissions issue. It looks like your cursor object is running the create again when you're trying to drop, or you're never really dropping the proc before running your unit test again, or the tests are running out of logical order in some fashion. Can you instantiate a new cursor object and try the drop with that, or verify the SQL being run against the database using profiler or some debug output?
Beyond that, I would be curious to see if changing your SQL commands to check for proc existence makes the error go away (not that this is the right answer):
if object_id('test.firstProc3') is null begin
-- Dynamic SQL because create must be first in a batch
exec ('create procedure test.firstProc3 as select getdate()')
end
if object_id('test.firstProc3') is not null begin
drop procedure test.firstProc3
end
Maybe something small, and maybe it is even not the case, but have you tried to use escaping in your drop statement?
something like
drop procedure [test].[firstProc3]
I can remember that i had an issue with this when i called a drop table from c# code...

Getting an exception ORA-00942: table or view does not exist - when inserting into an existing table

I am getting below exception, when trying to insert a batch of rows to an existing table
ORA-00942: table or view does not exist
I can confirm that the table exists in db and I can insert data to that table using oracle
sql developer. But when I try to insert rows using preparedstatement in java, its throwing table does not exist error.
Please find the stack trace of error below
java.sql.SQLException: ORA-00942: table or view does not exist
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)
at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:573)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1889)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:1093)
at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:2047)
at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:1940)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout>>(OracleStatement.java:2709)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:589)
at quotecopy.DbConnection.insertIntoDestinationDb(DbConnection.java:591)
at quotecopy.QuoteCopier.main(QuoteCopier.java:72)
Can anyone suggest the reasons for this error ?
Update : Issue solved
There was no problem with my database connection properties or with my table or view name. The solution to the problem was very strange. One of the columns that I was trying insert was of Clob type. As I had a lot of trouble handling clob data in oracle db before, gave a try by replacing the clob setter with a temporary string setter and the same code executed with out any problems and all the rows were correctly inserted!!!.
ie. peparedstatement.setClob(columnIndex, clob)
was replaced with
peparedstatement.setString(columnIndex, "String")
Why an error table or view does exist error was throws for error in inserting clob data. Could anyone of you please explain ?
Thanks a lot for your answers and comments.
Oracle will also report this error if the table exists, but you don't have any privileges on it. So if you are sure that the table is there, check the grants.
There seems to be some issue with setCLOB() that causes an ORA-00942 under some circumstances when the target table does exist and is correctly privileged. I'm having this exact issue now, I can make the ORA-00942 go away by simply not binding the CLOB into the same table.
I've tried setClob() with a java.sql.Clob and setCLOB() with an oracle.jdbc.CLOB but with the same result.
As you say, if you bind as a string the problem goes away - but this then limits your data size to 4k.
From testing it seems to be triggered when a transaction is open on the session prior to binding the CLOB. I'll feed back when I've solved this...checking Oracle support.
There was no problem with my database connection properties or with my table or view name. The solution to the problem was very strange. One of the columns that I was trying insert was of Clob type. As I had a lot of trouble handling clob data in oracle db before, gave a try by replacing the clob setter with a temporary string setter and the same code executed with out any problems and all the rows were correctly inserted!!!.
ie. peparedstatement.setClob(columnIndex, clob)
was replaced with
peparedstatement.setString(columnIndex, "String")
#unbeli is right. Not having appropriate grants on a table will result in this error. For what it's worth, I recently experienced this. I was experiencing the exact problem that you described, I could execute insert statements through sql developer but would fail when using hibernate. I finally realized that my code was doing more than the obvious insert. Inserting into other tables that did not have appropriate grants. Adjusting grant privileges solved this for me.
Note: Don't have reputation to comment, otherwise this may have been a comment.
We experienced this issue on a BLOB column. Just in case anyone else lands on this question when encountering this error, here is how we resolved the issue:
We started out with this:
preparedStatement.setBlob(parameterIndex, resultSet.getBlob(columnName)); break;
We resolved the issue by changing that line to this:
java.sql.Blob blob = resultSet.getBlob(columnName);
if (blob != null) {
java.io.InputStream blobData = blob.getBinaryStream();
preparedStatement.setBinaryStream(parameterIndex, blobData);
} else {
preparedStatement.setBinaryStream(parameterIndex, null);
}
I found how to solve this problem without using JDBC's setString() method which limits the data to 4K.
What you need to do is to use preparedStatement.setClob(int parameterIndex, Reader reader). At least this is what that worked for me. Thought Oracle drivers converts data to character stream to insert, seems like not. Or something specific causing an error.
Using a characterStream seems to work for me. I am reading tables from one db and writing to another one using jdbc. And i was getting table not found error just like it is mentioned above. So this is how i solved the problem:
case Types.CLOB: //Using a switch statement for all columns, this is for CLOB columns
Clob clobData = resultSet.getClob(columnIndex); // The source db
if (clobData != null) {
preparedStatement.setClob(columnIndex, clobData.getCharacterStream());
} else {
preparedStatement.setClob(columnIndex, clobData);
}
clobData = null;
return;
All good now.
Is your script providing the schema name, or do you rely on the user logged into the database to select the default schema?
It might be that you do not name the schema and that you perform your batch with a system user instead of the schema user resulting in the wrong execution context for a script that would work fine if executed by the user that has the target schema set as default schema. Your best action would be to include the schema name in the insert statements:
INSERT INTO myschema.mytable (mycolums) VALUES ('myvalue')
update: Do you try to bind the table name as bound value in your prepared statement? That won't work.
It works for me:
Clob clob1;
while (rs.next()) {
rs.setString(1, rs.getString("FIELD_1"));
clob1 = rs.getClob("CLOB1");
if (clob1 != null) {
sta.setClob(2, clob1.getCharacterStream());
} else {
sta.setClob(2, clob1);
}
clob1 = null;
sta.setString(3, rs.getString("FIELD_3"));
}
Is it possible that you are doing INSERT for VARCHAR but doing an INSERT then an UPDATE for CLOB?
If so, you'll need to grant UPDATE permissions to the table in addition to INSERT.
See https://stackoverflow.com/a/64352414/1089967
Here I got the solution for the question. The problem is on glass fish if you are using it. When you create JNDI name make sure pool name is correct and pool name is the name of connection pool name that you are created.

Categories

Resources