oracle plsql oracle11g oracle11gr2 subtype

oracle - ¿Cómo eliminar la dependencia del subtipo?



plsql oracle11g (3)

En el siguiente ejemplo, he escrito una función to_str() y un procedimiento set() para cada subtipo pls_integer . Las funciones y procedimientos son casi idénticos excepto el tipo.

¿Cómo puedo eliminar la necesidad de escribir otro to_str() y set() para un nuevo subtipo sin renunciar a la restricción proporcionada por el subtipo?

Cayendo de nuevo a varchar2 como

procedure set(list in varchar2, prefix in varchar2)

y luego llamándolo como

set(to_str(list), ''foos:'')

no suena muy buena idea y todavía tengo que proporcionar to_str() para cada subtipo.

Estoy abierto a todo tipo de propuestas diferentes, ya que soy un novato en Oracle y las nuevas funciones de Oracle me sorprenden casi a diario.

Estoy corriendo 11.2.0.1.0.

create table so1table ( id number, data varchar(20) ); create or replace package so1 as subtype foo_t is pls_integer range 0 .. 4 not null; type foolist is table of foo_t; procedure set(id_ in number, list in foolist default foolist(1)); subtype bar_t is pls_integer range 5 .. 10 not null; type barlist is table of bar_t; procedure set(id_ in number, list in barlist default barlist(5)); end; / show errors create or replace package body so1 as /* Do I have always to implement these very similar functions/procedures for every single type ? */ function to_str(list in foolist) return varchar2 as str varchar2(32767); begin for i in list.first .. list.last loop str := str || '' '' || list(i); end loop; return str; end; function to_str(list in barlist) return varchar2 as str varchar2(32767); begin for i in list.first .. list.last loop str := str || '' '' || list(i); end loop; return str; end; procedure set(id_ in number, list in foolist default foolist(1)) as values_ constant varchar2(32767) := ''foos:'' || to_str(list); begin insert into so1table (id, data) values (id_, values_); end; procedure set(id_ in number, list in barlist default barlist(5)) as values_ constant varchar2(32767) := ''bars:'' || to_str(list); begin insert into so1table (id, data) values (id_, values_); end; end; / show errors begin so1.set(1, so1.foolist(0, 3)); so1.set(2, so1.barlist(5, 7, 10)); end; / SQLPLUS> select * from so1table; ID DATA ---------- -------------------- 1 foos: 0 3 2 bars: 5 7 10


Es posible que esto no responda a su pregunta, pero ¿por qué no colocar los datos en una tabla regular, luego concatenarlos, como muestra, usando la función de agregación wm_concat ?

es decir,

> select * from myTable; ID Category Value --- --------- ------ 1 foo 0 2 foo 3 3 bar 5 4 bar 7 5 bar 10 > select Category||''s: ''||replace(wm_concat(Value),'','','' '') Data from myTable group by Category; Data ------------- bars: 5 7 10 foos: 0 3

wm_concat es de tipo independiente, por lo que no es necesario que sobrecargue sus funciones. Además, hay otros methods que se pueden utilizar; El método de función analítica se ve bien, ¡pero no tengo 11g para probar!

( Editar de lo contrario, creo que puede lograr lo que está buscando con el modelo de objetos de Oracle; específicamente el polimorfismo. Sin embargo, esto está más allá de mí ... así que tal vez alguien más pueda hacerlo).


La siguiente respuesta es en realidad a cómo lo harías en postgresql (y plpgsql), y tampoco sé acerca de los subtipos de Oracle, pero asumo que son lo suficientemente similares como para que al menos te conduzcan a tu respuesta.

create function add (anynonarray,anynonarray) returning anynonarray as ''begin return $1 + $2; end'';

Sé que arruiné la sintaxis, pero debería mostrar lo que quiero mostrar con ella, de todos modos.

La idea es que sustituirá "anynonarray" o cualquiera de las alternativas con el tipo de parámetro de la llamada. Una restricción es que todos los "anynonarray" en el ejemplo anterior serán del mismo tipo.

La documentación referida a esto como polimorfismo.


create table so1table ( id number, data varchar(20) ); create or replace type parent_type as object ( v_number number, --Prefix probably belongs with a list, not an individual value. --For simplicity, I''m not adding another level to the objects. v_prefix varchar2(10) ) not instantiable not final; / create or replace type parentlist as table of parent_type; / create or replace type foo_type under parent_type ( constructor function foo_type(v_number number) return self as result ); / --The data must be stored as a NUMBER, since ADTs don''t support --PL/SQL specific data types. The type safety is enforced by the --conversion in the constructor. create or replace type body foo_type is constructor function foo_type(v_number number) return self as result as subtype foo_subtype is pls_integer range 0 .. 4 not null; new_number foo_subtype := v_number; begin self.v_number := new_number; self.v_prefix := ''foos:''; return; end; end; / create or replace type foolist as table of foo_type; / create or replace type bar_type under parent_type ( constructor function bar_type(v_number number) return self as result ); / create or replace type body bar_type is constructor function bar_type(v_number number) return self as result as subtype bar_subtype is pls_integer range 5 .. 10 not null; new_number bar_subtype := v_number; begin self.v_number := new_number; self.v_prefix := ''bars:''; return; end; end; / create or replace type barlist as table of bar_type; / create or replace package so1 as procedure set(id_ in number, list in parentlist); end; / create or replace package body so1 as function to_str(list in parentlist) return varchar2 as v_value VARCHAR2(32767); begin for i in list.first .. list.last loop if i = 1 then v_value := list(i).v_prefix; end if; v_value := v_value || '' '' || list(i).v_number; end loop; return v_value; end to_str; procedure set(id_ in number, list in parentlist) as values_ constant varchar2(32767) := to_str(list); begin insert into so1table (id, data) values (id_, values_); end set; end so1; / begin --You probably don''t want to mix foos and bars, but it is allowed. so1.set(1, parentlist(foo_type(0), foo_type(3))); so1.set(2, parentlist(bar_type(5), bar_type(7), bar_type(10))); --These would generate "ORA-06502: PL/SQL: numeric or value error" --so1.set(1, parentlist(foo_type(5))); --so1.set(1, parentlist(bar_type(4))); end; / select * from so1table;