Delete Stored Procedure through remote - java

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

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

Liquibase run store procedure returns error

I try to set up the sql file from changeset to run a store procedure that is saved into my project but it returns sql error.
Here I declared the sqlfile:
<sqlFile path="/db/FindAllFriends.sql" endDelimiter="//" relativeToChangelogFile="true" splitStatements="true" stripComments="true" />
Here is my procedure:
DELIMITER //
CREATE PROCEDURE aaa()
BEGIN
END //
DELIMITER ;
If I let the "delimiter" in script it will return an sql error (you have an error in your sql syntax; check the manual....). If I remove it, it will be ok but it works only with ";" delimiter.
If I tried to drop and then create the procedure (or multiple statements):
Drop procedure if exists aaa;
CREATE PROCEDURE aaa()
BEGIN
END;
I receive: Error executing sql drop procedure if exists aaa;
My problem is that I need first to "drop procedure if exists" and after to create it, and I'm forced to use "delimiter" inside of script.
I don't know if it is a problem with the mysql parser, liquibase error or I made a mistake in my script.
I'm struggling with procedures (on Oracle) for some time now, and I start to believe that Liquibase was not made with procedures in mind ;)
Anyway - maybe dropProcedure and createProcedure changes would be sufficient for you?
I find executeCommand change with sqlplus to be the best solution to run scripts on Oracle...
Finally I was able run all scripts; I don't know what I made wrong when I tried first time, but now works. I had to declare the endDelimiter in sqlFile and to use this delimiter into script, also I deleted the declaration of "Delimiter //" from script

Retrieving Hive Table Location using Java

Is there a way to retrieve hdfs location of a hive table using
Java jdbc.
For example:
I have a temporary table t1.
at location '/user/tables_list/t1';
I want to retrieve this location using java code.
As far as I've tried, there isn't a direct way to do this. But, once you've set up your JDBC connection you can execute a "DESCRIBE EXTENDED ", which (in the test I did) will list the table columns for:
res = stmt.executeQuery("DESCRIBE EXTENDED tweets");
while(res.next()){
System.out.println(res.getString(1));
}
but, for the last row, you'll need to use:
res.getString(2)
which will give you a detailed table description that you'll need to parse, but somewhere in there there's a a location field
location:hdfs://localhost:8020/user/hive/warehouse/social.db/tweets
The problem with this, is that is a lot of handwork, because methods like:
res.last()
or
res.isLast()
are not supported, and they would be of a lot of help.
I had the same requirement and I used HiveMetaStoreClient API and it makes it as easy as typing:
srcTable.getSd().getLocation();
srcTable should be the table object which is retrieved from Hive metastore by giving the table specifications.

Procedure in DB not working when called from Java

I have an Java application running on a Weblogic Server and Connecting to Oracle 11g DB server.
In the application i make a call to a DB Procedure and pass a parameter to it which communicates and calls multiple other procedures.
When i test the Procedure independently, it works perfectly and as expected.
The issue comes when i call the Procedure from Java Application.
The Procedure gives an error:
ORA-06508: PL/SQL: could not find program unit being called
The Backtrace leads to a call to a procedure that exists in another Schema and has a synonym in my current schema.
Please help if anybody else has faced the same issue or a similar one.
Edit#1:
Sample Code for Calling DB Proc
CallableStatement cstmt = null;
private Connection dbConn = null;
HashMap hashMap = new HashMap();
hashMap.put(DBDRIVER, driverType);
hashMap.put(USERID, userName);
hashMap.put(PASSWORD, password);
hashMap.put(SID, dbName);
hashMap.put(IPADDRESS, intDBServer);
hashMap.put(PORT, dbPort);
dbConn = (Connection)cmmObj.connect(hashMap);
cstmt = dbConn.prepareCall(queryToRun);
cstmt.setString(1, ReqId);
cstmt.executeUpdate();
Proc Call is { call Proc_CALL(?) }
It sounds to me as though your synonym is the wrong way round - the calling schema needs a synonym for the called procedure + permissions to execute.
I have probably found the issue. Although it seams weird to hear it but it seems to work:
The system i was working on has 3 Schema in connection.
One is the Staging Schema from which all the calls are made.
Second is the Main Schema to which calls were made. The Called Procedure existed in this Schema.
The third is another schema where a procedure existed that was being called from Main Schema Procedure.
Simplified:
StageSchema.Caller(Synonym)-->>
MainSchema.Proc_Call(Procedure)-->>
CoSchema.insideCall(Procedure).
The Grants to the CoSchema were available to the Main Schema, but not to the Stage Schema.
Although as per theory if Any Procedure is being granted to a schema then all inside calls to any other procedures should not matter.
but in this case when i gave the grant to Stage Schema, then everything seemed to work perfectly.
If any one has a solution to this then please share the reason for the same.

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