Search code examples
oracleplsqluser-defined-types

Setter methods in UDT in Oracle database


I'm still new to this and trying to get my head around it. UDT are able to define methods which you can call on the object stored, I seem to create a method that returns a value fine but was wondering if it's possible create a setter methods. This scenario isn't really useful but it's simple just for clarification

For example, I have this type:

create TYPE TestType2 AS OBJECT(
Numb NUMBER(4),
Str VARCHAR2(10),
MEMBER FUNCTION setNum(numba NUMBER) RETURN NUMBER
);

Which compiles fine so my assumption setter methods are allow I've tried create the body type below:

CREATE TYPE BODY TestType2 as
member function setNum(numba NUMBER) return NUMBER is
    begin
        SELF.Numb := numba;
        return SELF.Numb;
    END;
END;

However this won't work giving me the errors below:

Error(3,9): PL/SQL: Statement ignored
Error(3,14): PLS-00363: expression 'SELF.NUMB' cannot be used as an assignment target

Is there a way to create a set method or is this only allowed in store procedures?


Solution

  • This is an obscure error. The problem is member functions take an implicit parameter of SELF. So if you want to change something you need to make the parameter explicit:

    create or replace TYPE TestType2 AS OBJECT(   
        Numb NUMBER(4,0),
        Str VARCHAR2(10),
        MEMBER procedure setNum(self in out TestType2, numba NUMBER )
     );
    /
    CREATE or replace TYPE BODY TestType2 as
        member function setNum(self in out TestType2 , numba NUMBER) return NUMBER 
        is
        begin
            self.Numb := numba;
            return SELF.Numb;
        END;
    END;
    /
    

    Note that the SELF parameter remains implicit when calling the function:

    declare
       t TestType2 := TestType2(4, 'TEST');
       n pls_integer;
    begin
        dbms_output.put_line('1' || t.numb);
        n := t.setNum(8);
        dbms_output.put_line('2' || t.numb);
    end;
    /
    

    Incidentally, setter methods don't need to be functions; we can have member procedures too.

    create or replace TYPE TestType2 AS OBJECT(
        Numb NUMBER(4,0),
        Str VARCHAR2(10),
        MEMBER procedure setNum(self in out TestType2, numba NUMBER ),
        MEMBER FUNCTION getNum RETURN NUMBER
    );
    /
    CREATE or replace TYPE BODY TestType2 as
        member procedure setNum(self in out TestType2, numba NUMBER )
    is
        begin
            self.Numb := numba;
        END;
    
        MEMBER FUNCTION getNum RETURN NUMBER
        is
        begin
            return self.numb;
        end;
    END;
    /