用于自定义类型的内爆函数的PL / SQL

时间:2011-08-03 15:27:03

标签: oracle object plsql concatenation sql-types

有没有办法在PL / SQL中创建一个implode例程,它将任何自定义数据类型作为参数并连接其成员,由某些指定的字符串分隔?

例如,假设我有以下类型:

CREATE TYPE myPerson AS OBJECT(
  forename VARCHAR2(50),
  surname  VARCHAR2(50),
  age      NUMBER
);

然后,假设一个函数返回一个myPerson类型的对象,但是我希望这些列连接在一起:

SELECT implode(getPerson(1234),'$$') from dual;

返回(假设设置了这个设计示例中的数据):

John$$Doe$$55

可以将分隔符指定为可选参数,但第一个参数的类型可以是任何内容(不一定是myPerson)。

2 个答案:

答案 0 :(得分:7)

您的自定义数据类型可以支持方法,方法可以有参数。

CREATE TYPE myPerson AS OBJECT(   
  forename VARCHAR2(50),   
  surname  VARCHAR2(50),   
  age      NUMBER,

  MEMBER FUNCTION
  get_record(pGlue IN varchar2)   RETURN VARCHAR2 );

CREATE TYPE BODY myPerson 
AS 
   MEMBER FUNCTION get_record(pGlue varchar2) RETURN VARCHAR2

 IS
BEGIN
 RETURN forename || pGlue  || surname  || pGlue || age ;
END get_record;

END;

答案 1 :(得分:4)

通过使用继承和多态,可以构建处理这些字符串的通用方法。如果我们要使用对象,我们应该利用对象编程的功能。

首先我们需要一个根对象。此TYPE不可实例化,这意味着我们实际上无法声明它的实例。请注意,TO_STRING()成员函数也声明为NOT INSTANTIABLE。这意味着任何继承自STRINGABLE_TYPE的TYPE必须拥有自己的方法实现。

SQL> create or replace type stringable_type as object
  2        ( id number(7,0)
  3          , NOT INSTANTIABLE member function to_string
  4                          return varchar2
  5      )
  6  not final not instantiable
  7  /

Type created.

SQL>

这是一种继承自STRINGABLE_TYPE的类型。 OVERRIDING关键字是必需的,即使父类型的声明迫使我们实现它。

SQL> create or replace type emp_type under stringable_type
  2   ( empno number(7,0)
  3     , ename varchar2(20)
  4     , sal number(7,2)
  5     , OVERRIDING member function to_string
  6                          return varchar2
  7      );
  8  /

Type created.

SQL> create or replace type body emp_type
  2  is
  3      OVERRIDING member function to_string
  4                          return varchar2
  5      is
  6      begin
  7          return 'EMP>>'||self.id||'='||self.empno||'::'||self.ename||'::'||self.sal;
  8      end;
  9  end;
 10  /

Type body created.

SQL>

这是另一种类型......

SQL> create or replace type dept_type under stringable_type
  2   ( deptno number(2,0)
  3     , dname varchar2(30)
  4     , OVERRIDING member function to_string
  5                          return varchar2
  6      );
  7  /

Type created.

SQL> create or replace type body dept_type
  2  is
  3      OVERRIDING member function to_string
  4                          return varchar2
  5      is
  6      begin
  7          return 'DEPT>>'||self.id||'='||self.deptno||'::'||self.dname;
  8      end;
  9  end;
 10  /

Type body created.

SQL>

现在,我们可以创建一个采用泛型类型并调用泛型方法的函数:

SQL> create or replace function type_to_string
  2      (p_obj in stringable_type)
  3      return varchar2
  4  is
  5  begin
  6      return p_obj.to_string();
  7  end;
  8  /

Function created.

SQL>

通过多态的奇迹,我们可以将两个不同的对象传递给函数,它实际上将执行覆盖方法:

SQL> set serveroutput on
SQL> declare
  2     obj1 emp_type;
  3     obj2 dept_type;
  4  begin
  5      obj1 := emp_type(1, 8000, 'VAN WIJK', 3500);
  6      obj2 := dept_type(2, 20, 'COMMUNICATIONS');
  7      dbms_output.put_line(type_to_string(obj1));
  8      dbms_output.put_line(type_to_string(obj2));
  9  end;
 10  /
EMP>>1=8000::VAN WIJK::3500
DEPT>>2=20::COMMUNICATIONS

PL/SQL procedure successfully completed.

SQL>

达到这一点需要做很多工作。如果Oracle的TYPE至少有一个抽象的TO_STRING()加入它,我们可以覆盖它,这将是很好的。但这只是其对象实现中的许多松散目标之一8-)