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

时间:2015-02-24 20:56:34

标签: oracle plsql oracle10g

我正在使用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:必须声明组件'MY_FUNC2'

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

我最初没有创建这个函数和同义词。是否有可能我在S2中缺少某些权限,因此MY_FUNC可以正常工作?

2 个答案:

答案 0 :(得分:14)

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

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';

答案 1 :(得分:6)

我来到这里是因为我有同样的问题。
对我来说问题是程序是在包体中定义的,而不是在包头中定义的。
我正在使用丢失的BEGIN END语句执行我的函数。