When I create Oracle's function in SQL Developer everything is ok, but when I create the same function via jdbc it is in invalid state
Here is the function sample:
create or replace function TEST_FUNC return number is
begin
return 100;
end;
Java code:
Connection con = ...;
Statement stmt = con.createStatement();
stmt.execute(sql);
When I execute function:
select TEST_FUNC() from dual;
I get error: ORA-06575: Package or function TEST_FUNC is in an invalid state
Can you explain what I'm doing wrong?
Function needed to be complied to use them. Not compiled function gives this exception. Also make sure you do not have any terminating CR/LF in your query. Copy it to a text editor (textpad) to see if you have any.
Related
I had migrated database from Oracle to AWS Aurora PostgreSQL. I saw that all the packages are migrated as Function in PostgreSQL. I used AWS SCT for the Oracle schema conversion to postgreSQL. Java is the application middleware.
for example,
A package and associated stored proc in Oracle pk_audit.sp_get_audit converted to postgreSQL as pk_audit$sp_get_audit with a $ symbol.
When I run the web application, I'm getting an error like method Name execute This statement does not declare an OUT parameter. Use { ?= call ... } to declare one .
I don't have access to the application, but App team provided weblogic log. It says,
Method Name execute org.postgresql.util.PSQLException:
This statement does not declare an OUT parameter.Use { ?= call ... } to declare one.
org.postgresql.jdbc.PgCallableStatement.registerOutParameter(PgCallableStatement.java:205) weblogic.jdbc.wrapper.CallableStatement_org_postgresql_jdbc_PgCallableStatement.registerOutParameter(Unknown Source
package name specified in the Java code is pk_audit.sp_get_audit
Renamed the Postgres function pk_audit$sp_get_audit to pk_audit.sp_get_audit still facing the issue.
Is there anything I need to do in PostgreSQL DB ?
I need advise and help,Thanks.
As documented in CallableStatement, the JDBC syntax for calling stored procedures is one of these
{call ProcedureName(?, ...)}
{? = call FunctionName(?, ...)}
Any of the parameters can be OUT parameters. The return value is of course a type of OUT parameter.
So, if you had a stored procedure with 2 parameters and the second parameter was an OUT parameter, you would code it as:
String sql = "{call MyProcedure(?, ?)}";
try (CallableStatement stmt = conn.prepareCall(sql)) {
stmt.setInt(1, p1);
stmt.registerOutParameter(2, Types.VARCHAR);
...
}
If that same procedure is converted into a function, you would code it as:
String sql = "{? = call MyFunction(?)}";
try (CallableStatement stmt = conn.prepareCall(sql)) {
stmt.registerOutParameter(1, Types.VARCHAR);
stmt.setInt(2, p1);
...
}
If you cannot change the Java code making the call, you need to convert your functions back to procedures.
I have some old C code I'm moving to Java and I have to port along existing SQL functions into JDBC. The commands are written like this (two of many examples):
RESULT:=1 + ?
IF ? > 0 THEN RESULT:=0 ELSE RESULT:= 1; END IF;
Those are two examples (separate commands).
Changing the syntax of the commands isn't an option, but some clever runtime replacement is valid. Note the ? are values that will get populated at runtime from other data.
I've tried this as statements, prepared statements, and callable statements, and I can't seem to get the syntax correct for getting "RESULT" back (actually, can't get it to execute() on any statement.
For test purposes I've been trying a simple command of either:
RESULT:=1+2
RESULT:=1+?
Just to see if I can get the type of statement working. But no luck.
The most common answer, from code that otherwise looks reasonable, is this:
String queryString = "declare result integer; begin RESULT:= 1 + 3; ? := RESULT; end";
try (CallableStatement cst = conn.prepareCall(queryString))
{
cst.registerOutParameter(1, Types.INTEGER);
cst.execute();
}
When I run that, on the execute (or executeUpdate, doesn't make a difference) I get back an Oracle 17002/08006 (Size Data Unit mismatch, network issue / invalid connection). But I have to believe that error is somewhat of a red herring, because the connection is definitely valid, and a trivially statement works fine.
Does anyone know the correct JDBC approach to calling that and getting a valid result (out of RESULT)?
I'm using Java 7 and Oracle 11g, if it matters.
Here's an example of calling a stored procedure that accepts an Integer argument and returns a single value (my Java method returns an Object and you can cast it to whatever you like).
public Object getResultFromStoredProcedure(String query,Integer param) {
Object obj=null;
ResultSet rs=null;
PreparedStatement stmt=null;
try{
stmt=conn.prepareStatement(query);
stmt.setInt(1,param);
rs = stmt.executeQuery();
if(rs.next()){
obj=rs.getObject(1);
}
}catch(SQLException e){
//catch exception and process it or log it
}finally{
rs.close();
stmt.close()
}
return obj;
}
Provided that you called your procedure OrclProc, you'd call it thus
String query = "select OrclProc(?) from dual";
Object result = getResultFromStoredProcedure(query, 5);
DELIMITER //
CREATE PROCEDURE temp ( empId INT)
BEGIN
DECLARE var_etype VARCHAR(36);
SELECT
emptype = QOUTE(emptype)
FROM
dms_document
WHERE
id = empid;
SELECT
emptype,
CASE
WHEN emptype = 'P' THEN doctype
ELSE 'No Documents required'
END
FROM
dms_report
WHERE
pilot = 1;
End//
DELIMITER ;
I have created this procedure successfully but when I try to call it, I am getting error 1305 the function database.temp does not exist. I am trying to call using this statement:
SET #increment = '1';
select temp( #increment)
but I get Error, please tell me where I made mistake.
This is how you call it, use use the keyword call and then procedure's name
call procedureName(params);
in call of making an string
String sqlString = "procedureName("+?+")"; //in case of Integers
String sqlString = "procedureName('"+?+"')";//in case of Integers
bring the parameter in prepared statement.
MySQL's documentation on Using JDBC CallableStatements to Execute Stored Procedures explains the necessary steps quite well.
This is what your java code needs to look like:
CallableStatement cStmt = conn.prepareCall("{call temp(?)}");
cStmt.setInt(1, 42); //set your input parameter, empId, to 42.
If you want to work with the rows returned by your stored procedure's query in your Java code, you're also going to need to create an OUT parameter as noted in MySql's documentation page titled, CALL Syntax:
CALL can pass back values to its caller using parameters that are
declared as OUT or INOUT parameters
In order to call your stored procedure from MySQL workbench, use the CALL command. You can call stored procedure by directly setting values for each of the parameters:
SET #increment = 1;
CALL temp(#increment)
Then you simply use the SELECT statement to return the value of your output parameter
SELECT #outParameter
With help setting your output parameters, please read the article MySQL Stored Procedure - SELECT - Example.
Your stored procedure is syntactically wrong, and as mentioned in the comments, you're not using the stored procedure functionality for it's intended use. It's intended to be used for data manipulation not for querying. You should instead consider turning your procedure into a series of prepared statements.
Please let me know if you have any questions!
I am writing a simple java program that calls a oracle stored procedure, but it doesn't work with callable statement.
When I call that stored procedure on SQLDeveloper,
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'XXXXX', TABNAME=>'XXXXX',
PARTNAME=>'XXXXXYYYYMM', ESTIMATE_PERCENT=>5, METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE AUTO',
CASCADE=>TRUE, DEGREE => 4);
it works correctly.
I already wrote other calling stored procedure methods in my java codes successfully, I simply used callable statement to call this particular stored procedure. All other methods are created stored procedures by Database admin, not the oracle system stored procedures.
Statement stmt = null;
StringBuffer sb = new StringBuffer();
CallableStatement cstmt = null;
sb.append("CALL DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'XXXXX', TABNAME=>'XXXXX', PARTNAME=>'XXXXX");
sb.append(yyyymm);
sb.append("', ESTIMATE_PERCENT=>5, METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE AUTO', CASCADE=>TRUE, DEGREE => 4)");
cstmt = this.conn.prepareCall(sb.toString());
cstmt.execute();
This gives me an error like this.
java.sql.SQLException: ORA-06576 : not a valid function or procedure name.
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:218)
at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:969)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3476)
at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:4400)
at xxxxx.bo.batch.SYS010.SYS010.start(SYS010.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at framework.utility.classloader.DynamicClassLoader.execute(DynamicClassLoader.java:91)
at com.xxxxx.batch.module.Job.jobStart(Job.java:249)
at com.xxxxx.batch.module.Job.run(Job.java:300)
Could anyone give me any hint on what the real problem might be?
Does anyone have same error when calling DBMS_STATS from java source code?
Is this because of variables that I am passing within the function call?
I am using the same user account for oracle with java program and sqldeveloper.
Seems the "call" syntax for Oracle requires the statement to be wrapped in braces. See the examples provided with OracleCallableStatement. Note the {} surrounding the call statement (missing in the example above):
CallableStatement cs1 = conn.prepareCall( "{call proc (?,?)}" ) ;
The example also demonstrates bind variable usage.
Does it help if you replace your CALL with a PL/SQL block, i.e.
sb.append("BEGIN");
sb.append(" DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'XXXXX', TABNAME=>'XXXXX', PARTNAME=>'XXXXX");
sb.append(yyyymm);
sb.append("', ESTIMATE_PERCENT=>5, METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE AUTO', CASCADE=>TRUE, DEGREE => 4);");
sb.append("END;");
?
(Note the extra semicolon after the stored procedure call.)
you can call procedure from java code like this:
"select GATHER_TABLE_STATS('XXXX','XXXX','XXXX') from dual" to execute the it.
HTH.
I'm using SQLiteJDBC as the wrapper for an embedded database for my small Java app. Everytime I execute an INSERT statement, I get the following exception:
query does not return ResultSet
I am wondering if the JDBC Statement.executeStatement(String) method is looking for me to return a ResultSet, but that the SQLite driver knows that INSERT statements don't return anything; maybe SQLiteJDBC is throwing an error because it shouldn't be returning the ResultSet that Statement is asking for?!?
Here is the code that is producing the exception - I have made sure to setup and close all resources properly:
statement = con.createStatement();
String sql = "INSERT INTO widgets (widget_age) VALUES (27)";
statement.executeStatement(sql);
Any ideas?!?
When you are making a change and not asking for a result back, you need to call executeUpdate() instead of executeStatement().
EDIT
I can't even find a reference to executeStatement() anywhere. Were you using executeQuery()?
Sqlite always returns a message quen you execute a Query.
It's normal to have that warning/error, it's simply that no rows where returned so you can't use them in the callback if you defined one.
PD: I also think you meant executeQuery