2

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.

2 Answers 2

2

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;
3
  • Thanks... nice to know.... so I wouldn't have to spend more time on it for now, and resort to defining record type (ugh). Thanks! Commented Dec 19, 2014 at 8:15
  • Very interesting info about 12c (about time!) Do you happen to know any details about how this works, internally?
    – Lukas Eder
    Commented Dec 19, 2014 at 8:46
  • Thank you very much. Looks like I need to get a hold of a 12c instance and play with it...
    – Lukas Eder
    Commented Dec 20, 2014 at 8:50
1

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.