如何解决错误“PLS-00363:表达式不能用作Oracle中的赋值目标”“,

j8yoct9x  于 2023-02-18  发布在  Oracle
关注(0)|答案(2)|浏览(541)

我有以下plsql对象:

CREATE OR REPLACE TYPE TestType AS OBJECT
    (
      firstname VARCHAR2(30),
      lastname VARCHAR2(30),
      MEMBER PROCEDURE dosomething,
      MEMBER function downgrade return number,
      CONSTRUCTOR FUNCTION TestType(fname VARCHAR2, lname VARCHAR2) RETURN SELF AS RESULT
    )
    /

    CREATE OR REPLACE TYPE BODY TestType AS
      CONSTRUCTOR FUNCTION TestType(fname VARCHAR2, lname VARCHAR2)
        RETURN SELF AS RESULT
      IS
      BEGIN
        SELF.firstname := fname;
        SELF.lastname := lname;
        RETURN;
      END;  
      
      MEMBER function downgrade return number IS
      BEGIN
        self.dosomething; /* Compilation Error Here */

        return 1;
      END;
      MEMBER PROCEDURE dosomething IS
      BEGIN
        null;
      END;
    END;
    /

这是一个复杂对象的例子,基本上从一个成员函数开始,我需要调用一个成员过程,当这样做的时候,我得到了编译错误:PLS-00363:表达式不能用作赋值目标
我不明白为什么会引发此错误。
有人知道我哪里做错了吗?
多谢。干杯,

sq1bmfud

sq1bmfud1#

尽管文件上说:
成员方法有一个名为SELF的内置参数,表示当前调用该方法的对象示例。
SELF可以显式声明,但这不是必须的。...
它后来还说:
SELF始终是传递给方法的第一个参数。

  • 在成员函数中,如果未声明SELF,则其参数模式默认为IN。
  • 在成员过程中,如果未声明SELF,则其参数模式默认为IN OUT。默认行为不包括NOCOPY编译器提示。

你得到这个错误是因为你的过程调用

self.dosomething;

隐式地将self作为IN OUT传递给过程,但是它被隐式地作为IN传递给函数,这意味着它没有处于正确的模式来调用过程--模式意味着过程可以修改self,而函数说它不会。
您可以通过更改函数中的模式来避免此错误,方法是在以下两种类型中显式声明self参数:

MEMBER function downgrade (self in out TestType) return number,

和类型体:

MEMBER function downgrade (self in out TestType) return number IS

fiddle
如果您的真实的过程不会修改self(可能不太可能),那么您可以声明它是self IN
人们常说函数应该只返回值,而不应该有副作用,所以可以说这是更正确的--调用你的成员函数的人可能不期望它改变任何东西。
所以如果dosomething * 正在改变数据,那么downgrade也应该是一个过程,用一个OUT参数代替返回值,这样你就不需要声明self,因为默认情况下两者都是IN OUT

7vux5j2d

7vux5j2d2#

以下代码编译成功:

MEMBER FUNCTION DOWNGRADE RETURN NUMBER IS
    me TestType := SELF;
  BEGIN
    me.dosomething;
    RETURN 1;
  END;

但是你应该仔细测试一下,它是否像预期的那样工作。
否则,您可以将过程更改为函数并忽略返回值:

CREATE OR REPLACE TYPE TestType AS OBJECT
(
  firstname VARCHAR2(30),
  lastname VARCHAR2(30),
  MEMBER FUNCTION dosomething RETURN NUMBER,
  MEMBER FUNCTION DOWNGRADE RETURN NUMBER,
  CONSTRUCTOR FUNCTION TestType(fname VARCHAR2, lname VARCHAR2) RETURN SELF AS RESULT
)
/

CREATE OR REPLACE TYPE BODY TestType AS
  CONSTRUCTOR FUNCTION TestType(fname VARCHAR2, lname VARCHAR2)
    RETURN SELF AS RESULT
  IS
  BEGIN
    SELF.firstname := fname;
    SELF.lastname := lname;
    RETURN;
  END;  
  
  MEMBER FUNCTION DOWNGRADE RETURN NUMBER IS
    ret NUMBER;
  BEGIN
     ret := self.dosomething;
    RETURN 1;
  END;
  MEMBER FUNCTION dosomething RETURN NUMBER IS
  BEGIN
    NULL;
    RETURN NULL;
  END;
END;
/

另一种方法是创建STATIC PROCEDURE过程而不是MEMBER PROCEDURE

相关问题