Oracle PLSQL:从成员一调用静态方法

问题描述 投票:0回答:2

我的 Oracle 类型有两个方法,名称为 myType:

  create or replace type myType as object (

    dummy varchar2(1),

    constructor function myType(something varchar2) return self as result,

    member procedure mp(self in myType,force boolean := false),

    static procedure sp

  );

  create or replace type body myType is

    constructor function myType(something varchar2) return self as result
      is
    begin
      dummy := something;

      return;
    end;

    member procedure mp(self in myType,force boolean := false) is
    begin
      if self.dummy is null and force then
        myType.sp();
      end if;
    end;

    static procedure sp is
    begin
      null;
    end;

  end;

这会导致 Oracle 错误:myType 超出范围 (PLS-00225)。如果我删除“myType”。它认为我正在尝试将 sm() 作为成员方法调用,并且还给出了错误(PLS-00587)。

我已经找到了解决问题的方法:

create or replace synonym mySynonym for myType;

然后调用而不是 myType.sp(); -> mySynonym.sp();而且效果很好。

我仍然希望找到一些没有垃圾同义词的解决方案(如果存在的话)。

Oracle版本:11.2

重要:构造函数导致失败,在我的情况下无法消除

oracle-database plsql static-methods
2个回答
1
投票

抱歉,无法在 Oracle XE 11.2 上重现此问题:

SQL> create or replace type myType as object (
  2      z   char(1),
  3      member procedure mp,
  4      static procedure sp
  5  );
  6  /

Type created.

SQL> create or replace type body myType is
  2    member procedure mp is
  3    begin
  4      myType.sp();
  5    end;
  6
  7    static procedure sp is
  8    begin
  9      dbms_output.put_line('We''re here');
 10    end;
 11  end;
 12  /

Type body created.

SQL> set serveroutput on
SQL> declare
  2    x     myType;
  3  begin
  4    x := myType(z => 'X');
  5    x.mp();
  6  end;
  7  /
We're here

PL/SQL procedure successfully completed.

SQL>

您如何定义类型标头?

编辑:现在您已经添加了构造函数,我可以重现该错误。

解决该问题的一种方法是在调用静态过程时使用架构所有者来限定

myType

    member procedure mp(self in myType,force boolean := false) is
    begin
      if self.dummy is null and force then
        luke.myType.sp();
      end if;
    end;

此更改使我能够成功编译类型。

我在以用户

luke
连接到我的 11g XE 数据库时创建了您的过程。 该用户名很可能与您的系统不同。

当然,您的项目可能有不同的开发、测试和生产用户名,因此这可能不是您的理想方法。 如果是这样,创建同义词可能是最好的选择。


0
投票

也许有人会发现这很有用 - 还有另一种解决方案,不需要同义词或指定类型的模式所有者。使用动态 SQL(例如

execute immediate
)可以实现这一点。但要小心 -
execute immediate
强制 - 至少 - 软解析,如果频繁进行该调用,这将使您的代码变慢。

这是一个示例(基于 smnbbrv 代码):


 create or replace type myType as object (

    dummy varchar2(4000),

    constructor function myType(something varchar2) return self as result,

    member procedure mp(self in myType,force boolean := false),

    static procedure sp

  );
/
  create or replace type body myType is

    constructor function myType(something varchar2) return self as result
      is
    begin
      dummy := something;

      return;
    end;

    member procedure mp(self in myType,force boolean := false) is
    begin
      if self.dummy is null and force then
        execute immediate 'CALL myType.sp()';
      end if;
    end;

    static procedure sp is
    begin
      dbms_output.put_line('Call to myType.sp');
    end;

  end;
  /

测试:

set serveroutput on;

declare
  v_x myType := myType(something => null);
begin
  v_x.mp(force => True);
end;
/

-- Result printed to output:

Call to myType.sp


PL/SQL procedure successfully completed.


© www.soinside.com 2019 - 2024. All rights reserved.