PL / SQL для функции implode на пользовательских типах

есть ли способ создать процедуру implode в PL / SQL, которая принимает любой пользовательский тип данных в качестве параметра и объединяет его члены, разделенные некоторой указанной строкой?

например, скажем у меня есть следующие типа:

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

затем, скажем, функция возвращает объект типа myPerson, но я хочу, чтобы столбцы были объединены вместе:

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

вернуться (если данные в этом примере устанавливается up):

John$$Doe$

где разделитель может быть указан как необязательный параметр, но тип первого параметра может быть любым (не обязательно myPerson).

2 ответов


пользовательский тип данных может поддерживать методы и методы могут иметь параметры.

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;

можно построить универсальный способ обработки этих строк, используя наследование и полиморфизм. Если мы собираемся использовать объекты, мы должны использовать возможности объектно-ориентированного программирования.

во-первых нам нужен корневой объект. Этот тип не является экземпляром, что означает, что мы не можем фактически объявить его экземпляр. Обратите внимание, что функция-член TO_STRING() также объявлена как не ИНСТАНЦИРУЕМАЯ. Это означает, что любой тип, наследуемый от STRINGABLE_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. Главнейшей сайта является обязательным, даже если declartion родительского типа заставляет ее реализовать.

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 хотя бы был запечен абстрактный TO_STRING (), который мы могли бы просто переопределить. Но это только один из многих свободных концов в их реализации объекта 8-)