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:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.