PL / SQL для функции внедрения в пользовательских типах - PullRequest
6 голосов
/ 03 августа 2011

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

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

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 ]

7 голосов
/ 03 августа 2011

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

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;
4 голосов
/ 04 августа 2011

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

Во-первых, нам нужен корневой объект.Этот ТИП не является экземпляром, что означает, что мы не можем фактически объявить его экземпляр.Обратите внимание, что функция-член TO_STRING () также объявлена ​​как NOT INSTANTIABLE.Это означает, что любой TYPE, который наследуется от 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.Ключевое слово 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-)

...