@RobVanWijk hace un comentario pertinente:
se podría argumentar que esos documentos deben estar almacena como cuatro columnas numéricas en vez de 1 cadena.
Este es un caso clásico en el que sería genial si pudiéramos definir dominios de datos en nuestros esquemas. Oracle no es compatible con esto, pero es justo ni ninguno de los otros proveedores de DBMS. Aún así, podemos emplear tipos definidos por el usuario para construir tipos de datos complejos con comportamiento adjunto. Es una lástima que la sintaxis UDT sea tan torpe.
De todos modos, el comentario de Rob me ha recordado que me arrebaté una Prueba de concepto usando este mismo dominio hace un tiempo. He colgado, no como una solución seria, sino como un indicador de cómo podrían ser las cosas interesantes ....
La especificación del tipo ...
create or replace type ip_address_t as object
(octet1 number(3,0)
, octet2 number(3,0)
, octet3 number(3,0)
, octet4 number(3,0)
, constructor function ip_address_t
(octet1 number, octet2 number, octet3 number, octet4 number)
return self as result
, member function to_string
return varchar2
, member function to_padded_string
return varchar2
, map member function sort_order return number)
/
... y el cuerpo ...
create or replace type body ip_address_t as
constructor function ip_address_t
(octet1 number, octet2 number, octet3 number, octet4 number)
return self as result
is
begin
if (octet1 is null or octet2 is null or octet3 is null or octet4 is null)
then
raise INVALID_NUMBER;
else
self.octet1 := octet1;
self.octet2 := octet2;
self.octet3 := octet3;
self.octet4 := octet4;
end if;
return;
end ip_address_t;
member function to_string return varchar2
is
begin
return trim(to_char(self.octet1))||'.'||
trim(to_char(self.octet2))||'.'||
trim(to_char(self.octet3))||'.'||
trim(to_char(self.octet4));
end to_string;
member function to_padded_string return varchar2
is
begin
return lpad(trim(to_char(self.octet1)),3,'0')||'.'||
lpad(trim(to_char(self.octet2)),3,'0')||'.'||
lpad(trim(to_char(self.octet3)),3,'0')||'.'||
lpad(trim(to_char(self.octet4)),3,'0');
end to_padded_string;
map member function sort_order return number
is
begin
return to_number(
lpad(trim(to_char(self.octet1)),3,'0')||
lpad(trim(to_char(self.octet2)),3,'0')||
lpad(trim(to_char(self.octet3)),3,'0')||
lpad(trim(to_char(self.octet4)),3,'0')
);
end sort_order;
end;
/
Utilizaré este tipo para definir una columna en una tabla de prueba que completaré con algunos datos de prueba.
SQL> create table t23 (id number, domnain_name varchar2(128), ip_address ip_address_t)
2/
Table created.
SQL> insert into t23 values (1000, 'http://www.example.com', ip_address_t(8,1,3,0))
2/
1 row created.
SQL> insert into t23 values (800, 'http://www.example1.com', ip_address_t(9,1,2,0))
2/
1 row created.
SQL> insert into t23 values (1100, 'http://www.example2.com', ip_address_t(10,1,2,0))
2/
1 row created.
SQL> insert into t23 values (1103, 'http://www.example3.com', ip_address_t(10,1,25,0))
2/
1 row created.
SQL> insert into t23 values (1102, 'http://www.example4.com', ip_address_t(1,11,25,0))
2/
1 row created.
SQL> insert into t23 values (1101, 'http://www.example5.com', ip_address_t(11,1,25,0))
2/
1 row created.
SQL>
Recuerde siempre: al hacer referencia a los atributos o métodos de una columna UDT tenemos que utilizar un alias de mesa:
SQL> select t.id
2 , t.ip_address.to_string() as ip_address
3 from t23 t
4 order by t.ip_address.sort_order()
5/
ID IP_ADDRESS
---------- ---------------
1102 1.11.25.0
1000 8.1.3.0
800 9.1.2.0
1100 10.1.2.0
1103 10.1.25.0
1101 11.1.25.0
SQL>
Independientemente de respuesta que se obtiene aquí: Nota mental para el futuro, no almacene los números como cadenas (y son números si necesita procesarlos como números). –
gracias, pero no fue mi decisión :-) – opHASnoNAME
@LasseVKarlsen - esos no son números, tienen demasiados períodos en ellos . Claramente, son cadenas que simplemente están compuestas por caracteres numéricos, al igual que las direcciones IP (que es, tal vez, la fuente de estos datos). – APC