Hi I have problem with calling store procedure.
when i am trying to call my procedure from my following java code
connection = ConnectionManager.getInstance().getConnection(dataBaseURL, serverName, portNumber, sid, username, password);
callable = connection.prepareCall("{call SCHEMA_RESTORE.restore()}");
callable.executeUpdate();
..................................
I am getting this Exception
Exception in thread "main" java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00201: identifier 'SCHEMA_RESTORE.RESTORE' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
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:1891)
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 oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:656)
My Prodedure is
CREATE OR REPLACE PACKAGE BODY SCHEMA_RESTORE IS
PROCEDURE backup (pbRecreateBackupTable IN BOOLEAN DEFAULT FALSE)
IS
TableAlreadyExists EXCEPTION;
PRAGMA EXCEPTION_INIT (TableAlreadyExists, -955);
nCount NUMBER;
CURSOR cTables IS SELECT tbls.table_name tbl, SUBSTR(tbls.table_name,4) name FROM user_tables tbls, FT_T_TBDF tbdf
WHERE tbls.table_name NOT LIKE gsPrefix || '%' AND tbls.table_name NOT LIKE 'FT_CFG%' AND tbls.table_name NOT IN ('FT_WF_APEV','FT_WF_WFTJ','FT_WF_WFTN','FT_WF_WFNP','FT_WF_WFNV','FT_WF_WFIO','FT_WF_WFGV','FT_WF_WFND','FT_WF_WFDF','EXCEPTIONS','TESTDSFP') and tbls.table_name NOT LIKE 'FT_LOG%'
AND tbdf.tbl_id(+) = SUBSTR(tbls.table_name,-4) AND tbdf.tbl_desc NOT LIKE '%Note: This table is obsolete%';
BEGIN
RAISE;
END;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END backup;
The error message says that SCHEMA_RESTORE.RESTORE cannot be found. There are several possible causes:
The package (and procedure) are in a different schema, e.g. you compiled it as user A but are trying to call them as user B.
You don't have the access right to execute procedures from the package. Thus it becomes invisible.
You have defined the procedure in the package body, but haven't declared it in the package header.
A further problem I can see are the parentheses. If you call a procedure without arguments, the prentheses shoul be omitted:
{ call SCHEMA_RESTORE.restore }
It comes when you make a procedure in one user and connect the db in another.
To solve this issue try this
GRANT EXECUTE ON procedureName TO username
Otherwise connect with correct username which you using
Did the procedure compile successfully ? Also check if you can see it via some editor (PL/SQL dev ?) under the schema
or you may use this to see if it is there -
SELECT * FROM DBA_OBJECTS WHERE object_name = '%your proc name%';
Related
I have created a java stored procedure in Oracle, using query:
CREATE OR REPLACE PROCEDURE GETSHEETROWS(I_file_id number, I_sheetNode clob,template_key varchar2 ,wksht_key varchar2 ,wksht_name varchar2 )
AS LANGUAGE JAVA
NAME 'SheetRowsJson.getSheetRows(int, java.sql.Clob, java.lang.String, java.lang.String, java.lang.String)';
/
Following is my java code. (Input I_sheetnode is of json type. Since there is no Jsontype datatype in plsql, I used clob there and so, I used the same here)
public static void getSheetRows( int I_file_id, Clob I_sheetNode, String
template_key, String wksht_key,String wksht_name ) {
try{
String url = "jdbc:oracle:thin:#xxxxx:port/yyyyy";
Connection conn = DriverManager.getConnection(url,"username","password");
System.out.println("-------------------Connection Successful--------------------------------");
String sheetRows = "select X.Node,X.rn from json_table (("+ I_sheetNode.toString() +"),'$.table_row[*]' COLUMNS(rn for ordinality,Node varchar2(4000) FORMAT JSON PATH '$')) X";
PreparedStatement ps=conn.prepareStatement(sheetRows);
ResultSet rs = ps.executeQuery();
/* Remaining code goes here */
When I am trying to run the procedure like this,
set serveroutput on;
call dbms_java.set_output(50);
execute GETSHEETROWS(14,'{"name":"sheet","table_row":[{"value":"1","item":"11111","id":"2","value":"1","action":"NEW"},{"value":"2","item":"22222","id":"3","value":"4","action":"NEW"}]}','TEMPLATE','SHEET','Sheet1');
/
I am getting the following output:
Call completed.
-------------------Connection Successful--------------------------------
java.sql.SQLSyntaxErrorException: ORA-01729: database link name expected
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:774)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java)
at SheetRowsJson.getSheetRows(SheetRowsJson.java:25)
PL/SQL procedure successfully completed.
I am unable to figure out the reason for this. Since "Connection successful" is being printed, is the connection really successful? or not? If not, why?
Note: I have already loaded java class using loadjava utility.
If you add a basic debugging print of your generated statement, e.g.:
System.out.println(sheetRows);
you'll see something like:
select X.Node,X.rn from json_table ((oracle.sql.CLOB#77556fd),'$.table_row[*]' COLUMNS(rn for ordinality,Node varchar2(4000) FORMAT JSON PATH '$')) X
The toString() method shows you the object ID, not the string contents. And the # in that ID is causing the error you see (as 77556fd or whatever value you see isn't a valid object identifier).
You could embed the actual passed-in string value, but you'd have to enclose it in single quotes, and you'd be restricted by the size of a string literal in your DB (either 4k or 32k depending on version and settings) which makes using a CLOB in the first place pointless; and you should be using bind variables anyway, something like:
sheetRows = "select X.Node,X.rn from json_table (?,'$.table_row[*]' COLUMNS(rn for ordinality,Node varchar2(4000) FORMAT JSON PATH '$')) X";
PreparedStatement ps=conn.prepareStatement(sheetRows);
ps.setClob(1, I_sheetNode);
ResultSet rs= ps.executeQuery();
I am getting a "java.sql.SQLException: ORA-22922: nonexistent LOB value".
I was originally testing outside the DB, but did see this replicating your setup more fully. The only way I've avoided it so far is to avoid an implicit temporary CLOB:
create table t (c) as (
select to_clob('{"name":"sheet","table_row":[{"value":"1","item":"11111","id":"2","value":"1","action":"NEW"},{"value":"2","item":"22222","id":"3","value":"4","action":"NEW"}]}') from dual
);
declare
l_clob clob;
begin
select c into l_clob from t;
getsheetrows(14, l_clob, 'TEMPLATE', 'SHEET', 'Sheet1');
end;
/
The connection is not successful.
The "connection successful" message will be printed in all cases. Even if getConnection returns null or error, System.out.print will still print "connection successful".
You might want to add an if statement or an try catch statement to check for the existence of connection instead of adding an System.out.print statement which dosen't check for the existence of the connection and will just print "connection successful"
PS:Check your url and/or the jars you are using.
I stuck with Oracle store procedure calling. The code looks simple, but I seriously don't know how to make it work.
This is my code for creating the procedure
DELIMITER ##
CREATE OR REPLACE PROCEDURE updateAward(_total_amount in Number, _no_of_sales in Number, _agent in NUMBER, _id in NUMBER) AS
BEGIN
update Award set total_amount = _total_amount, no_of_sales = _no_of_sales, agent_id = _agent where ID = _id ##
commit ##
So, when I execute it through NetBean (it is the only tool I have at this moment), the code run well.
I also tried to run the compile statement
alter PROCEDURE updateAward compile;
and then, use
select *
from user_errors
where name = 'ORG_SPGETTYPE'
The select return empty, proving that the compile process is ok. However, when I trigger the procedure
call updateAward(1,1,1,1);
It returns the error
Package or function UPDATEAWARD is in an invalid state
and the command
SELECT object_name FROM user_objects WHERE status='INVALID';
return the name of the procedure. How can I solve this problem ?
Update 1:
if I use
BEGIN
updateAward(1,1,1,1);
End;
I got error
Error code 6550, SQL state 65000: ORA-06550: line 2, column 20:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
:= . ( % ;
Update 2:
The reason I put the deliminator is because i got error with ";" when working through some vpn to the other network (still not sure why). So, i updated the code like your answer, but then, with the End; in the end of the procedure and then, get the Invalid SQL statement1. If i remove it and execute (through Netbean), the procedure is created successfully. However, after compiling and check the user_errors, it got the
"PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ; "
First things first, your procedure syntax looks wrong. Don't use DELIMITER as that syntax is specific to MySQL. Instead, try something like the following.
CREATE OR REPLACE PROCEDURE updateAward(_total_amount in Number, _no_of_sales in Number, _agent in NUMBER, _id in NUMBER) AS
BEGIN
update Award set total_amount = _total_amount, no_of_sales = _no_of_sales, agent_id = _agent where ID = _id;
commit;
END;
Firstly, there are a couple of things wrong with your procedure:
You're not using delimiters correctly. Delimiters should be used to terminate the whole procedure, not each line.
The NetBeans SQL window doesn't know SQL very well so it cannot tell when the procedure ends and something else begins. Normally, it uses semicolons (;) to tell when one statement ends and another begins, but stored procedures can contain semicolons within them so that wouldn't work. Instead, we change the delimiter to something else so that the NetBeans SQL window sends the entire stored procedure to the database in one go.
Variable names are not allowed to begin with an underscore (_). In particular, rule 5 in the list of Schema Object Naming Rules at this Oracle documentation page states that
Nonquoted identifiers must begin with an alphabetic character from your database character set.
Underscores are not alphabetic characters.
I've taken your procedure, fixed the use of delimiters and added an extra p onto the front of each parameter name (p for 'parameter'), and I got the following, which ran successfully in NetBeans and created a procedure without errors:
delimiter $$
CREATE OR REPLACE PROCEDURE updateAward(p_total_amount in Number, p_no_of_sales in Number, p_agent in NUMBER, p_id in NUMBER) AS
BEGIN
update Award set total_amount = p_total_amount, no_of_sales = p_no_of_sales, agent_id = p_agent where ID = p_id;
commit;
END;
$$
delimiter ;
Secondly, you write
[...] and then, use
select *
from user_errors
where name = 'ORG_SPGETTYPE'
The select return empty, proving that the compile process is ok.
Um, no. This proves that there are no errors in the procedure ORG_SPGETTYPE (or no procedure with that name exists). Your procedure is named updateAward, which Oracle will capitalise to UPDATEAWARD. Try
select *
from user_errors
where name = 'UPDATEAWARD';
instead.
I have declared package level type this way (using Oracle XE 11):
create or replace PACKAGE RM_TYPES
AS
TYPE RECPPART_ARR IS TABLE OF RM_RECEPCIONPARTIDAS%ROWTYPE;
END RM_TYPES;
I have SP like this:
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RM_TYPES.RECPPART_ARR) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
I have java code like this:
CallableStatement cstmt = conn.prepareCall("{call RM_TRY_B(?)}");
cstmt.registerOutParameter(1, OracleTypes.ARRAY, "RM_TYPES.RECPPART_ARR");
cstmt.execute();
Array a = cstmt.getArray(1);
It gives me an excepcion:
Exception in thread "main" java.sql.SQLException: invalid name pattern: RM_TYPES.RECPPART_ARR
I have already granted access to package to my user by issuing this command to oracle:
GRANT EXECUTE ON RM_TYPES TO myuser;
I used this as reference: https://docs.oracle.com/database/121/JJDBC/apxref.htm#JJDBC28913 (section named: Creating Java level objects for each row using %ROWTYPE Attribute
Where did I do wrong?
I've also try passing in this name in my java code: "RECPPART_ARR" or "MYSCHEMA.RM_TYPES.RECPPART_ARR" none of them works.
Then I read someone said this on stackoverflow: java - passing array in oracle stored procedure : "actually the problem is that any type created within a package is not visible by java. If I create the type at schema level then it works. "
Is it true?
Then maybe I should define an alias at schema level?
How? I tried "CREATE SYNONYM":
CREATE PUBLIC SYNONYM RECPPART_ARRAY FOR RM_TYPES.RECPPART_ARR;
And then (tried to modify my SP):
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RECPPART_ARRAY) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
But this time this SP wouldn't compile, with this error message in my SQLDeveloper: Error(1,36): PLS-00905: object MYSCHEMA.RECPPART_ARRAY is invalid.
Then I tried using the previous definition of my sp:
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RM_TYPES.RECPPART_ARR) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
And modified my Java code to use the synomim instead:
CallableStatement cstmt = conn.prepareCall("{call RM_TRY_B(?)}");
cstmt.registerOutParameter(1, OracleTypes.ARRAY, "RECPPART_ARRAY");
cstmt.execute();
Array a = cstmt.getArray(1);
Still, exception, with message: Fail to construct descriptor: Unable to resolve type: "MYSCHEMA.RECPPART_ARRAY"
ADDITION
Some other info I just found:
http://oracle.developer-works.com/article/5227493/%22invalid+name+pattern%22++when+trying+to+user+packaged+TYPE
Someone wrote: I had the same issue. Managed to solve it by creating public synonym and giving grants.
As you see, I did that already, but no luck for me.
ADDITION
Or ... maybe something like this in oracle (after reading this: http://docs.oracle.com/javadb/10.10.1.2/ref/rrefsqljgrant.html ):
create or replace PACKAGE RM_TYPES
AS
TYPE RECPPART_ARR IS TABLE OF RM_RECEPCIONPARTIDAS%ROWTYPE;
END RM_TYPES;
sqlplus (logged in as sys as SYSDBA)> GRANT USAGE ON TYPE RM_TYPES.RECPPART_ARR TO myuser;
CREATE PUBLIC SYNONYM RECPPART_ARRAY FOR RM_TYPES.RECPPART_ARR;
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RM_TYPES.RECPPART_ARR) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
....
I tried it..., even logged in using user "sys" as SYSDBA .... I got an error when issuing grant:
Error starting at line : 1 in command -
GRANT USAGE TYPE ON RM_TYPES.RECP_ARR TO myuser
Error report -
SQL Error: ORA-00990: missing or invalid privilege
00990. 00000 - "missing or invalid privilege"
*Cause:
*Action:
I'm running out of idea now.
JDBC Support for PL/SQL Data Types as Parameters is a new feature of Oracle 12c.
PL/SQL types look and act like regular types; they can be used in SQL and other contexts, they have a TYPE_OID and TYPECODE, and they have a data dictionary view (DBA_PLSQL_TYPES). One odd difference is that PL/SQL types do not show up in DBA_OBJECTS.
In older versions you must create a TYPE as a stand-alone object in order to use it outside of PL/SQL. Code like this can create the objects:
CREATE OR REPLACE TYPE RECPPART_REC IS OBJECT
(
--list RM_RECEPCIONPARTIDAS columns here. %ROWTYPE is not available in SQL.
);
CREATE OR REPLACE RECPPART_ARR IS TABLE OF RECPPART_REC;
You could make use of a little-known feature in PL/SQL: PIPELINED functions. An example:
create table tab (
id number(7)
);
/
insert into tab values (1);
insert into tab values (2);
create or replace package pkg
as
type typ is table of tab%rowtype;
end pkg;
/
create or replace procedure proc (param out pkg.typ) as
begin
select * bulk collect into param from tab;
end;
/
create or replace function func return pkg.typ pipelined as
begin
for rec in (select * from tab) loop
pipe row(rec);
end loop;
end;
/
select * from table(func);
The above will yield:
ID
--
1
2
So you can materialise the table type also easily from JDBC.
The reason for this is the fact that every pipelined function implicitly creates a top-level SQL type that is of the same type as your PL/SQL table type. In the above case something like:
create or replace type SYS_PLSQL_29848_13_1 as object (ID NUMBER(7));
create or replace type SYS_PLSQL_29753_9_1 as table of SYS_PLSQL_29848_13_1;
This is more of a side-note. In general, you should probably prefer the approach suggested by Jon Heller
I have a stored procedure and I can execute it on plsql. Now I want to call it from my eclipse. don't worry about the connection, it is correct.
In the plsql I see two variables for this stored procedure. the top one is the result which is string , the below one is my variable which is string too.
I have tried:
callablestatement = {call mystroedprocedure (?,?)}
callablestatement.registeroutparameter(1, OracleTypes.varchar);
callablestatement.setString(2, "5555");
But I got this exception:
java.sql.sqlexception: ora-06550: line 1, column 7:
pls_00306: wrong number of types of arguments in call to 'mystroedprocedure'
ORA-06550: line 1, colmuns 7:
PL/SQL: statemnent ignored.
I can't see the body of the stored procedure because I don't have privilege.
I am using ojdbc6.jar
I want to execute a Oracle Stored procedure using named parameter from Java CollableStatement. Syntactically all is good by when we execute the application we get SQL Error-
Java Code -
int method1(){
CallableStatement stmt stmt = connection.prepareCall("{call "+strSQL.toString()+"}");
sp_copy_my_tree(?,?,?)
stmt.setInt("src_cd_ekey", 2057);
stmt.setInt("trg_ef_ekey", 8222);
stmt.setInt("trg_display_order", 1]);
returnValue = stmt.executeUpdate(strSQL.toString());
return returnValue ;
}
Oracle Stored Procedure -
create or replace PROCEDURE sp_copy_my_tree (src_ab_ekey IN NUMBER DEFAULT NULL,
src_cd_ekey IN NUMBER DEFAULT NULL, trg_ef_ekey IN NUMBER DEFAULT NULL,
trg_gh_ekey IN NUMBER DEFAULT NULL, trg_display_order IN NUMBER)
IS
begin
--- Some PL/SQL code ---
END ;
When I execute the above java statement I am getting Exception -
*java.sql.SQLException: Attempt to set a parameter name that does not occur in the SQL: src_cd_ekey*
Note- I have also tried to pass all the parameters in the same order of procedure, where for other 2 parameters I have passed null. But still getting the same Exception.
Please somebody help us to resolve this issue.
This issue came because of two reasons.
1) The Number of parameters declared in Procedure is different than the number of parameter passed from Java procedure call.
This is the reason why the aptly given Answer 1, to this thread cannot be used as is. We need to pass all 5 parameters from the procedure call in the proper sequence.
2) Named Parameter in Java is different then Oracle Named Parameter.
In Oracle we can execute procedure by passing only selected parameters, as the parameters passed may not be following the proper sequence so the values can be paired with the parameter name(as key). example -
EXEC sp_copy_my_tree (src_cd_ekey=>2057, trg_ef_ekey=>8222, trg_display_order=>1);
In Java we cannot emulate this and java named parameter has different meaning. In java statement we can specify the parameter name starting with colon instead of using ? as placeholder. Later while setting the placeholder we can use these parameter names rather then index. Example -
CallableStatement stmt stmt = connection.prepareCall( "{call sp_copy_my_tree(:src_cd_ekey,:trg_ef_ekey, :trg_display_order)}");
stmt.setInt("src_cd_ekey", 2057);
stmt.setInt("trg_ef_ekey", 8222);
stmt.setInt("trg_display_order", 1]);
But this call by Oracle will be considered as execution request to procedure with first 3 parameters.
Note: I was getting SqlException with stmt.executeUpdate(), so I used stmt.execute(). It might be a problem in my implementation but the latter worked in my case.
Try this method:
CallableStatement stmt = connection.prepareCall("{call sp_copy_my_tree (?,?,?}");
stmt.setInt(1, 2057);
stmt.setInt(2, 8222);
stmt.setInt(3, 1);
returnValue = stmt.executeUpdate();
return returnValue ;
}
See documentation for details: http://docs.oracle.com/cd/E11882_01/java.112/e16548/getsta.htm#i1008346