为什么我得到 PLS-00302:组件存在时必须声明?

Why do I get PLS-00302: component must be declared when it exists?

我正在使用 Oracle 10.2。

我正在使用一些脚本将一些 ORACLE 对象从一个 SCHEMA (S1) 移动到另一个 (S2)。 我正在创建具有 DBA 角色的功能。 移动时,我的功能之一变得无效,但我不明白为什么。 它的代码遵循以下几行:

MY_FUNC

CREATE OR REPLACE FUNCTION S2."MY_FUNC" RETURN VARCHAR2 IS
   something VARCHAR2;
   othervar VARCHAR2 (50):= 'TEST';   
BEGIN
   something := S2.MY_FUNC2();
    /*some code*/
    return othervar;
END;
/

如果我在没有架构的情况下使用 MY_FUNC2,它会起作用:
something := MY_FUNC2(); 而不是 something := S2.MY_FUNC2();

My_FUNC2

CREATE OR REPLACE FUNCTION S2."MY_FUNC2" RETURN VARCHAR2 IS
       something BOOLEAN;
       othervar VARCHAR2 (50) := 'TEST2';           
    BEGIN
       /*some code*/
        return othervar;
    END;
    /

MY_FUNC2 有这样一个同义词:

 CREATE OR REPLACE PUBLIC SYNONYM "MY_FUNC2" FOR "S2"."MY_FUNC2"

MY_FUNC 编译错误:

PLS-00302: component 'MY_FUNC2' must be declared

我不明白为什么会出现此错误,当我的函数在另一个模式 (S1) 中时,它们具有完全相同的结构并且创建的同义词完全相同(但指向 S1)并且 MY_FUNC编译好的。

我最初并没有创建这个函数和同义词。有没有可能是我在S2中少了一些权限,所以MY_FUNC可以正常工作?

如果您有一个与架构同名的对象,您可能会遇到该错误。例如:

create sequence s2;

begin
  s2.a;
end;
/

ORA-06550: line 2, column 6:
PLS-00302: component 'A' must be declared
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored

当您引用 S2.MY_FUNC2 时,正在解析对象名称,因此它不会尝试将 S2 评估为架构名称。当您将其称为 MY_FUNC2 时,不会造成混淆,因此可以正常工作。

文档explains name resolution。限定对象名称的第一部分 - 此处为 S2 - 在被评估为不同的模式之前被评估为当前模式上的对象。

这可能不是一个序列;其他对象可能会导致相同的错误。您可以通过查询数据字典来检查是否存在同名对象。

select owner, object_type, object_name
from all_objects
where object_name = 'S2';

我来这里是因为我遇到了同样的问题。
对我来说问题是程序是在包体中定义的,而不是在包头中。
我在执行我的函数时使用了一个 lose BEGIN END 语句。