我已经用这种方式声明了包级别类型(使用Oracle XE 11):
create or replace PACKAGE RM_TYPES
AS
TYPE RECPPART_ARR IS TABLE OF RM_RECEPCIONPARTIDAS%ROWTYPE;
END RM_TYPES;
我有这样的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;
我有这样的java代码:
CallableStatement cstmt = conn.prepareCall("{call RM_TRY_B(?)}");
cstmt.registerOutParameter(1, OracleTypes.ARRAY, "RM_TYPES.RECPPART_ARR");
cstmt.execute();
Array a = cstmt.getArray(1);
它给了我一个例外:
Exception in thread "main" java.sql.SQLException: invalid name pattern: RM_TYPES.RECPPART_ARR
我已经通过向oracle发出此命令来授予对我的用户的访问权限:
GRANT EXECUTE ON RM_TYPES TO myuser;
我使用它作为参考:https://docs.oracle.com/database/121/JJDBC/apxref.htm#JJDBC28913(命名为:使用%ROWTYPE属性为每行创建Java级别对象
我哪里做错了?
我也尝试在我的java代码中传递此名称:" RECPPART_ARR"或" MYSCHEMA.RM_TYPES.RECPPART_ARR"它们都不起作用。
然后我读到有人在stackoverflow上说这个:java - passing array in oracle stored procedure:"实际上问题是java中看不到包中创建的任何类型。如果我在模式级别创建类型,那么它的工作原理。 "
是真的吗?
那么也许我应该在架构级别定义一个别名?
如何?我尝试了#34;创建SYNONYM":
CREATE PUBLIC SYNONYM RECPPART_ARRAY FOR RM_TYPES.RECPPART_ARR;
然后(试图修改我的SP):
create or replace PROCEDURE "RM_TRY_B" (partidas OUT RECPPART_ARRAY) as
begin
SELECT * BULK COLLECT INTO partidas FROM rm_recepcionpartidas;
end;
但这次这个SP无法编译,我的SQLDeveloper中出现此错误消息:错误(1,36):PLS-00905:对象MYSCHEMA.RECPPART_ARRAY无效。
然后我尝试使用我之前的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;
修改我的Java代码以改为使用synomim:
CallableStatement cstmt = conn.prepareCall("{call RM_TRY_B(?)}");
cstmt.registerOutParameter(1, OracleTypes.ARRAY, "RECPPART_ARRAY");
cstmt.execute();
Array a = cstmt.getArray(1);
仍然是异常,带有消息:无法构造描述符:无法解析类型:" MYSCHEMA.RECPPART_ARRAY"
ADDITION
我刚发现的其他一些信息:
有人写道:我有同样的问题。管理通过创建公共同义词和赠款来解决它。
如你所见,我已经这样做了,但对我来说没有运气。
ADDITION
或者......在oracle中可能是这样的(在阅读之后: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;
...
我试过了......,甚至使用用户" sys"作为SYSDBA ....我在发出grant时遇到错误:
从命令行中的第1行开始出错 -
在RM_TYPES.RECP_ARR上向myuser授予使用类型
错误报告 -
SQL错误:ORA-00990:缺少或无效的权限
00990. 00000 - "缺少或无效的特权"
*原因:
*操作:
我现在已经没想完了。
答案 0 :(得分:2)
JDBC Support for PL/SQL Data Types as Parameters是Oracle 12c的新功能。
PL / SQL类型看起来像常规类型;它们可以在SQL和其他上下文中使用,它们具有TYPE_OID和TYPECODE,并且它们具有数据字典视图(DBA_PLSQL_TYPES)。一个奇怪的区别是PL / SQL类型没有出现在DBA_OBJECTS中。
在旧版本中,您必须创建一个TYPE作为独立对象,以便在PL / SQL之外使用它。像这样的代码可以创建对象:
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;
答案 1 :(得分:1)
您可以在PL / SQL中使用一个鲜为人知的功能:PIPELINED
函数。一个例子:
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);
以上将产生:
ID
--
1
2
因此,您也可以轻松地从JDBC中实现表类型。
原因是每个流水线函数都隐式创建一个与PL / SQL表类型相同类型的顶级SQL类型。在上面的例子中:
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;
这更像是一个侧面说明。一般来说,您可能更喜欢the approach suggested by Jon Heller