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-)