如何覆盖ORDER方法PL / SQL?

时间:2014-04-25 18:51:53

标签: sql oracle inheritance plsql oracle11g

我必须定义一个具有一些属性的对象类型Employee,然后我必须定义一个将继承Employee类型的对象类型Manager,并且将有一个名为nrEmp的aditional属性,它将包含每个manager的员工数量在他的指挥下。此外,我必须为类型管理器实现方法ORDER,因此我可以按照他们拥有的员工数量来命令管理员。首先我定义了这种类型:

CREATE OR REPLACE TYPE Departament AS OBJECT ( 
    deptno NUMBER(2),
    dname CHAR(14)
   );

接下来我定义了Employee类型:

CREATE OR REPLACE TYPE Employee AS OBJECT ( 
    empno  NUMBER(4),
    ename CHAR(10),
    dept REF Departament,
    sal NUMBER(7,2)
   ) NOT FINAL;

到目前为止,一切都运转正常。接下来我尝试定义类型管理器:

CREATE OR REPLACE TYPE Manager UNDER Employee (
  nrEmp INTEGER,
  ORDER MEMBER FUNCTION compare(m Manager) RETURN INTEGER
  );

当我这样做时,我收到以下错误:

Error(1,1): PLS-00646: MAP or ORDER method must be defined in the root of the subtype hierarchy

据我所知,我必须在Employee类型中声明该方法。但我不确定如何以正确的方式做到这一点。无法找到任何显示如何在继承时实现ORDER方法的示例。任何帮助,将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:4)

我找到了一种方法来做到这一点。我不能说这是最好的解决方案或最优雅的解决方案,但它可以满足我的需求。这是代码。 员工类型:

CREATE OR REPLACE TYPE Employee AS OBJECT ( 
    empno  NUMBER(4),
    ename CHAR(10),
    dept REF Departament,
    sal NUMBER(7,2),
    ORDER MEMBER FUNCTION match (other IN Employee) RETURN INTEGER
   ) NOT FINAL;

经理类型:

CREATE OR REPLACE TYPE Manager UNDER Employee (
  nrEmp INTEGER
  );

员工类型的正文:

CREATE OR REPLACE TYPE BODY Employee AS 
   ORDER MEMBER FUNCTION match(other IN Employee) Return INTEGER IS
    v_mng_self Manager;
    v_mng_other Manager;
   BEGIN 
      v_mng_self := TREAT(self AS Manager);
      v_mng_other := TREAT(other AS Manager);
      IF v_mng_self.nrEmp < v_mng_other.nrEmp THEN
         RETURN -1;  
      ELSIF v_mng_self.nrEmp > v_mng_other.nrEmp THEN 
         RETURN 1;   
      ELSE 
         RETURN 0;
      END IF;
   END;
END;

如果您想比较2个Manager对象,那就是您需要做的全部工作。 ORDER方法将执行从Employee到Manager类型的类型转换。例如:

DECLARE 
   manager1 Manager;
   manager2 Manager;
BEGIN
   manager1 := Manager(7823,'John',null,2000,10);
   manager2 := Manager(7782,'Bob',null,3000,15);
   IF manager1 < manager2 THEN
     SYS.DBMS_OUTPUT.PUT_LINE('manager1 has less employees than manager2');
   END IF;
END;

不要忘记在上面的代码块之前设置输出,这样就可以看到显示的结果。

SET SERVEROUTPUT ON;

答案 1 :(得分:1)

我只需要解决同样的问题并提出以下解决方案:

create or replace type employee as object(
   empno number( 4 ),
   member function compare_internal( e employee ) return integer,
   order member function compare( e employee ) return integer 
) not final;
/

create or replace type body employee is
   member function compare_internal( e employee ) return integer is
      begin
         return
            case
            when self.empno = e.empno then 0
            when self.empno > e.empno then 1
            when self.empno < e.empno then -1
            end;
      end;

   order member function compare( e employee ) return integer is
      begin
         return compare_internal( e );
      end;
end;
/

create or replace type manager under employee( 
   nr_emp integer,
   overriding member function compare_internal( e employee )
   return integer );
/

create or replace type body manager is
   overriding member function compare_internal( e employee ) return integer is
      m manager;
      r integer;
      begin
         if e is of ( manager ) then
            m := treat( e as manager );
            r :=
               case
                  when self.nr_emp = m.nr_emp then 0
                  when self.nr_emp > m.nr_emp then 1
                  when self.nr_emp < m.nr_emp then -1
               end;
         end if;
         return r;
      end;
end;
/

这允许通过覆盖被调用函数来覆盖order / map函数。

declare
  x employee;
  y employee;
begin
  x := employee(empno => 1);
  y := employee(empno => 1);
  dbms_output.put_line( x.compare(y) );
  -- gives 0, as both have same empno

  x := manager(empno => 1, nr_emp => 2);
  y := manager(empno => 1, nr_emp => 3);
  dbms_output.put_line( x.compare(y) );
  -- gives -1 as both have different nr_emp

  x := employee(empno => 1);
  y := manager(empno => 1, nr_emp => 3);
  dbms_output.put_line( x.compare(y) );
  -- gives 0, as both have same empno -- is that what we want?

  x := manager(empno => 1, nr_emp => 3);
  y := employee(empno => 1);

  dbms_output.put_line( x.compare(y) );
  -- gives null, y is not a manager

end;