Por motivos de trabajo he tenido que volver a trabajar con mi amigo PL/SQL, con quien pasé buenos momentos en la uni… y algunos no tan buenos.

En muchos lenguajes de programación es habitual encontrar una función SPLIT (o similar) que sirve para obtener en un array o una tabla cada uno de los elementos de una cadena de texto separados por un caracter delimitador.

Sin embargo, lograr esto en SQL no es nada fácil, por mucho que sea PL. El caso es que me he visto en la obligación de realizar esta operación con un campo de una base de datos ORACLE y la búsqueda de información ha sido algo durilla, así que he pensado en explicar aquí la manera de hacerlo por si a alguien le es de utilidad.

Después de encontrar varias soluciones chapucerillas, la mayoría de las cuales hacían uso de una u otra manera de la función Substr (incluida en PLQSL), en varios foros se habla de una función “user-made” que es muy sencilla de entender y de personalizar. Es esta:

CREATE OR REPLACE FUNCTION split
(
p_list varchar2,
p_del varchar2 := ','
) RETURN split_tbl pipelined
IS
l_idx pls_integer,
l_list varchar2(32767) := p_list,
AA
l_value  varchar2(32767),
BEGIN
loop                
l_idx := instr(l_list,p_del),               
IF l_idx > 0 THEN                   
pipe ROW(substr(l_list,1,l_idx-1)),                      
l_list := substr(l_list,l_idx+LENGTH(p_del)),              
ELSE
pipe ROW(l_list),
exit,
END IF,
END loop,
RETURN,
END split,

La función SPLIT recibe dos parámetros: p_list con la cadena de texto y p_del con el carácter delimitador que servirá para separar un elemento de otro. Mediante el uso de la función Substr y tuberías consigue separar cada elemento en una fila o registro de una tabla.

Por ello, el tipo de dato que devuelve la función se llama split_tbl y hay que definirlo antes como una tabla de varchars de la máxima longitud posible:

CREATE OR REPLACE TYPE split_tbl AS TABLE OF varchar2(32767),

Una vez hecho esto, el código funcionará perfectamente. La tabla resultante de la función dispondrá de un único campo llamado COLUMN_VALUE (por si hace falta usarlo en alguna otra parte) con los valores buscados en la cadena.

Con la función Split creada, podemos hacer consultas como esta:

SELECT * FROM TABLE(split(´one,two,three´)),

cuyo resultado será una tabla de un sólo campo con tres registros:

one
two
three

Por supuesto se puede moficar para adaptarse a las necesidades de cada uno. En mi caso, la convertí en un procedimiento que en vez de devolver la tabla, inserta los valores uno a uno en una tabla temporal, para así disponer de ella ‘físicamente’. Las posibilidades son infinitas.


Fatal error: Cannot use object of type stdClass as array in /homepages/35/d378790237/htdocs/davidsite.com/wp-content/plugins/social-counters/counters/facebook.php on line 56