【问题标题】:Oracle JDBC / PL SQL / TYPE / Package Level / Invalid Name PatternOracle JDBC / PL SQL / TYPE / 包级别 / 无效名称模式
【发布时间】:2014-12-19 06:46:23
【问题描述】:

我已经以这种方式声明了包级别类型(使用 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 不可见。如果我在架构级别创建类型,那么它就可以工作。”

是真的吗?

那么也许我应该在模式级别定义一个别名?

怎么样?我试过“创建同义词”:

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 中出现以下错误消息:Error(1,36): PLS-00905: object MYSCHEMA.RECPPART_ARRAY is invalid。

然后我尝试使用我的 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, "RECPPART_ARRAY");
cstmt.execute();
Array a = cstmt.getArray(1);

仍然存在异常,带有消息:无法构造描述符:无法解析类型:“MYSCHEMA.RECPPART_ARRAY”


添加

我刚刚找到的一些其他信息:

http://oracle.developer-works.com/article/5227493/%22invalid+name+pattern%22++when+trying+to+user+packaged+TYPE

有人写道:我有同样的问题。设法通过创建公共同义词并给予资助来解决它。

如你所见,我已经这样做了,但我没有运气。


添加

或者......也许在 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 登录...。发出授权时出现错误:

从第 1 行开始的错误命令 - 将 RM_TYPES.RECP_ARR 上的使用类型授予 myuser 错误报告 - SQL 错误:ORA-00990:权限缺失或无效 00990. 00000 - “权限缺失或无效” *原因:
*行动:

我现在想不通了。

【问题讨论】:

    标签: java oracle stored-procedures jdbc plsql


    【解决方案1】:

    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;
    

    【讨论】:

    • 谢谢...很高兴知道...所以我现在不必花更多时间在这上面,而是求助于定义记录类型(呃)。谢谢!
    • 关于 12c 的非常有趣的信息(关于时间!)您是否碰巧知道有关其内部工作原理的任何细节?
    • 非常感谢。看来我需要获取一个 12c 实例并使用它...
    【解决方案2】:

    您可以利用 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 轻松实现表类型。

    这是因为每个流水线函数都会隐式创建一个顶级 SQL 类型,该类型与您的 PL/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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      • 1970-01-01
      相关资源
      最近更新 更多