I need to use following via Java EXEC DBMS_STREAMS_ADM.SET_TAG(tag => HEXTORAW('17')); using a simple Database client. along with other usual select/delete queries but its complaining for invalid SQL statement.
I tried removing the exec as its for PL/SQL and calling it with {} but still I am getting the same error.
EXEC is SQL*Plus (Oracle's native SQL client) syntax and you can't use it here. The JDBC syntax for calling stored procedures is through the CALL directive. You can omit the parameter name in the call (tag => HEXTORAW('17')). For example:
try (CallableStatement cs
= myConnection.prepareCall("{ call DBMS_STREAMS_ADM.SET_TAG(HEXTORAW(?)) }")) {
cs.setString(1, "17");
cs.execute();
}
It is unclear which DBClient you are currently using (please tell us), but the following might work as well:
DBClient.execute("{ call DBMS_STREAMS_ADM.set_tag(HEXTORAW('17')) }");
or then
DBClient.execute("begin DBMS_STREAMS_ADM.SET_TAG(HEXTORAW('17')); end;");
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 code I'm trying to fix and a function is used within a CallableStatement but it seems that said function is called in a particular instance where a Schema of the Database becomes the entire 'see-able' database for the function.
Let me explain :
My database (in PostgreSQL) has multiple projects (schemas) such as i2b2test_project or i2b2test_project2. Each of these projects has an architecture of multiple tables, such as visit_dimension, patient_dimension, etc..
Now, if I want to reference the visit_dimension table from a i2b2test_project, I need to use i2b2test_project.visit_dimension, as any logical SQL syntax would suggest.
The problem is that, in the code (which I'll include below), a CallableStatement is used to execute a function (plain old load-table-from-temp-table function). This function references the architecture mentioned above as if only one project exists, as the database. In other words, instead of referencing i2b2test_project.visit_dimension, it only references visit_dimension.
I haven't found a way to execute a function in some sort of 'separated instance' of the database and as a result, the function can not be used in a plain SQL statement inside a DB terminal, errors such as visit_dimension table does not exist etc..
So I ask : Does the call statement (which indeed seems to reference the schema) allow for such a 'separated instance' of the database ? And is there a way to do so with a plain SQL statement ?
Code :
CallableStatement callStmt = conn.prepareCall("{call "
+ this.getDbSchemaName()
+ "INSERT_ENCOUNTERVISIT_FROMTEMP(?,?,?)}");
callStmt.setString(1, tempTableName);
callStmt.setInt(2, uploadId);
callStmt.registerOutParameter(3, java.sql.Types.VARCHAR);
callStmt.execute();
I have trouble executing the following using a JDBC prepared statement:
CREATE OR REPLACE TRIGGER Time_trg BEFORE INSERT ON Time FOR EACH ROW
BEGIN
SELECT Time_seq.NEXTVAL INTO :new.id FROM dual;
END;
The code:
try {
PreparedStatement statement = connection.prepareStatement( sql );
preparedStatement.executeUpdate();
} finally {
statement.close();
}
I'm getting this error:
java.sql.SQLException: Missing IN or OUT parameter at index:: 1
I'm working on a database agnostic solution so I need something that is portable. So what is oracle's problem?
There is no need to write our own stored procedure to do this. Oracle provides a built-in stored procedure we can use: DBMS_UTILITY.EXEC_DDL_STATEMENT:
DBMS_UTILITY.EXEC_DDL_STATEMENT('create table t1 (id number)');
In fact this is safer than the workaround procedure suggested in the accepted answer as it doesn't allow the execution of DML and so is protected against SQL injection
Use oracle.jdbc.OraclePreparedStatement
OraclePreparedStatement statement = (OraclePreparedStatement)connection.prepareStatement( sql );
As this is much specific to Oracle, regular PrepareStatement doesn't help. Oracle provides a wrapper for the same, with additional functionalities as well.
Similarly, Oracle provides OracleCallableStatement similar to CallableStatement
WorkAround: (When PreparedStatement has to be used - Risk of being misused
CREATE PROCEDURE EXECUTE_MY_DDL(INSTRING VARCHAR2)
AS
BEGIN
EXECUTE IMMEDIATE INSTRING;
END;
Reference JavaDoc
Since you cannot have any bind variables in Oracle DDL anyway, why use a PreparedStatement? You can use a static statement instead and shouldn't run into this problem:
try (Statement s = connection.createStatement()) {
s.executeUpdate(sql);
}
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.
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.