【问题标题】:Some mistake in calling one procedure from another从另一个调用一个过程的一些错误
【发布时间】:2012-07-04 16:16:35
【问题描述】:

由于要求,我必须从另一个存储过程调用一个存储过程。

问题似乎出在我正在使用的输出参数out_result_size 附近。当我测试main_func 时它工作正常,但是当我测试synonym_proc 时它说

synonym_proc 无效

我最终必须使用 JPA 的 @NamedNativeQuery 从 Java 调用 synonym_proc

CREATE OR REPLACE PROCEDURE synonym_proc (
    result_cursor      OUT SYS_REFCURSOR,
    in_cp_id           IN NUMBER,
    in_cp_name         IN VARCHAR2 := NULL,
    in_country_name    IN VARCHAR2 := NULL,
    in_industry_name   IN VARCHAR2 := NULL,
    in_max_result_size IN NUMBER
) AS
    out_result_size NUMBER;
BEGIN
   result_cursor := someSchema.somePackage.main_func(in_cp_id,
              in_cp_name,
              in_country_name,
              in_industry_name,
              in_max_result_size,
              out_result_size);
END;

更新:很抱歉没有提及我之前没有注意到的问题的变化。 main_func 是一个函数(不是过程),它返回一个游标并驻留在某个模式中的某个包内。编译时出现以下编译错误:

错误:PLS-00201:标识符“SOMESCHEMA.SOMEPACKAGE”必须是 声明..语句被忽略。

更新 2

一些架构定义

CREATE OR REPLACE PACKAGE someSchema."SomePackage"
is
...
function mainFunc
(
    in_cp_id                in gem.tcp_real_profile_main_approved.cp%type
    , in_cp_name            in gem.tcp_real_profile_main_approved.name%type
    , in_country_name       in gem.tcp_real_profile_main_approved.country_name%type
    , in_industry_name      in gem.tcp_real_profile_main_approved.industry_name%type
    , in_max_result_size    in number
    , out_result_size       out number
)
return search_result_type_cursor;

添加

type search_result_type_cursor
 is ref cursor
 return search_type;

是的,数据类型是正确的,因为我描述了函数 (main_func) 并交叉验证了数据类型。

【问题讨论】:

  • 是的,无效。当你真正尝试编译这个过程时,你会得到什么?
  • 我在问题中提到过。 “错误:PLS-00201:必须声明标识符 'SOMESCHEMA.SOMEPACKAGE'.. 语句被忽略。”
  • 而someSchema.somePackage.main_func的定义是什么?
  • @tbone,请参阅更新 2
  • 您将sys_refcursor 与可能是强类型的search_result_type_cursor 混合在一起。这是故意的还是必要的?

标签: oracle stored-procedures plsql


【解决方案1】:

基于 cmets,特别是您可以在其他模式中描述和测试过程,看起来这可能是权限问题。如果您对其他模式中的对象的权限是通过角色授予的,那么您将能够直接执行包过程,但角色 aren't recognised inside named blocks。如果这是问题所在,那么您必须获得对 someSchema.somePackage 的执行权限,直接授予创建存储过程的用户。

为了演示这个问题,我可以在我的 SCOTT 架构中创建一个包,并将其上的执行权限授予一个角色,并将该角色授予一个用户——这两个都是我为测试创建的。作为SYS

create role scott_tmp_role;
grant connect to someuser identified by <password>;
grant scott_tmp_role to someuser;
grant create procedure to someuser;

作为SCOTT:

create package p42 as
    procedure proc;
end p42;
/

Package created.

create package body p42 as
    procedure proc is
    begin
        null;
    end proc;
end p42;
/

Package body created.

grant execute on p42 to scott_tmp_role;

Grant succeeded.

作为我的新SOMEUSER,验证我的角色:

select * from session_roles;

ROLE
------------------------------
CONNECT
SCOTT_TMP_ROLE

我可以在匿名块中执行该过程:

begin
    scott.p42.proc;
end;
/

PL/SQL procedure successfully completed.

...但不在命名块中:

create or replace procedure sp42 as
begin
    scott.p42.proc;
end;
/

Warning: Procedure created with compilation errors.

show errors

Errors for PROCEDURE SP42:

LINE/COL ERROR
-------- -----------------------------------------------------------------
3/2      PL/SQL: Statement ignored
3/2      PLS-00201: identifier 'SCOTT.P42' must be declared

如果SCOTT 直接将权限授予我的新用户:

grant execute on p42 to someuser;

...那么命名块现在可以工作了:

create or replace procedure sp42 as
begin
    scott.p42.proc;
end;
/

Procedure created.

如果您想查看您可能从哪里获得执行权限,您可以运行这样的查询,尽管可能有一个角色层次结构可供选择:

select grantee, privilege from all_tab_privs
where table_schema = 'SomeSchema'
and table_name = 'SomePackage';

【讨论】:

  • SO 中最好的解释答案之一。您的理由是绝对正确的(尽管我们需要访问的软件包非常重要,我们正在寻找方法来做到这一点是另一回事)。 +1 很好的解释。谢谢亚历克斯!
【解决方案2】:

您不能指定过程或函数的参数大小。尝试删除尺寸,并按照 Vincent 的建议移动 commit

CREATE OR REPLACE PROCEDURE synonym_proc(result_cursor      OUT SYS_REFCURSOR,
                                         in_cp_id           IN NUMBER,
                                         in_cp_name         IN VARCHAR2,
                                         in_country_name    IN VARCHAR2,
                                         in_industry_name   IN VARCHAR2,
                                         in_max_result_size IN NUMBER) AS
  out_result_size NUMBER;
BEGIN
  main_proc(result_cursor,
            in_cp_id,
            in_cp_name,
            in_country_name,
            in_industry_name,
            in_max_result_size,
            out_result_size);
  COMMIT;
END;

您应该收到类似PLS-00103: Encountered the symbol "(" when expecting one of the following: ... 的错误

【讨论】:

  • 感谢亚历克斯的回答。但这不是主要原因。我更新了问题。我的错。请查看更新后的问题。
【解决方案3】:

Oracle SP 的语法是

CREATE OR REPLACE PROCEDURE procedure_name(--parameter list) AS
--Local Variables
BEGIN
--Body
END;

现在您犯了一个错误,即没有将 COMMIT 放在 END 之前,而是将其放在 END 之后。应该是这样的

COMMIT;
END;

【讨论】:

  • 感谢泽山的回答。但这不是主要原因。我更新了问题。我的错。请查看更新后的问题。
猜你喜欢
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多