[PL/SQL] Quitar espacios en blanco entre cadenas


Actualmente me encuentro en un proyecto de migración de datos y el origen de este post va por una consulta que me hizo una compañera de trabajo. Y ya que la menciono, es una chica muy hábil técnicamente hablando, vaaya que últimamente me está tocando trabajar con gente muy hábil con las que estoy haciendo buenos trabajos, pues lo que más me sorprende de ella es que domina muy bien las consultas SQL y la programación PL/SQL, se sabe todas las sintaxis de Oracle, nunca la veo consultando ningún tipo de sintaxis por google, es muy segura =O

Eeeeen finnn.. su consulta era si conocía alguna función para quitar los espacios en blanco entre dos cadenas (me habrá puesto a prueba???). Lo cual no encontré googleando, así que me animé en preparar un programa.

La primera versión de mi programa fue:


SET SERVEROUTPUT ON
DECLARE
v_nombre VARCHAR2(100):= 'Juan    Perez';
v_nombre_sin_espacios VARCHAR2(100); 
v_cantidad_espacios_blanco int:= 1000; 

BEGIN
v_nombre_sin_espacios := REPLACE(v_nombre,' ', '');

    WHILE (v_cantidad_espacios_blanco > 1) LOOP

     v_cantidad_espacios_blanco := LENGTH(v_nombre) - LENGTH(v_nombre_sin_espacios);
     dbms_output.put_line(v_cantidad_espacios_blanco || ' -> ' || v_nombre);

       v_nombre :=  REPLACE(v_nombre, '  ', ' ');  
     
    END LOOP;
  dbms_output.put_line('R - > ' || v_nombre);

END;

La idea principal es encontrar la cantidad de espacios en blanco entre ambas palabras, este cálculo es una resta de la cantidad de caracteres de la frase original menos la cantidad de caracteres de la frase sin espacios en blanco. Luego a través de un loop ir reemplazando 1 espacio en blanco donde se encuentren 2 espacios en blanco, de esto trata la función REPLACE(v_nombre, ' ', ' ').

Al imprimir el resultado tengo lo siguiente:

bloque anónimo terminado
20 -> Juan                    Perez
10 -> Juan          Perez
5 -> Juan     Perez
3 -> Juan   Perez
2 -> Juan  Perez
1 -> Juan Perez
R - > Juan Perez

Seguí probando la función y me percaté que solo funcionaba con frases donde solo habían 2 palabras. Lo cual tuve que mejorar el algoritmo.

Esta es la segunda versión del programa:


SET SERVEROUTPUT ON
DECLARE
v_nombre VARCHAR2(100):= 'Christian            Gonzales                     Komiya';

v_nombre_sin_espacios VARCHAR2(100);
v_cantidad_espacios_blanco int:= 1000;
i int:=0;
j int:=0;
j1 int;
v_cantidad_bloques_esp_blanco int := 0;

BEGIN
v_nombre_sin_espacios := REPLACE(v_nombre,' ', '');

WHILE (TRUE) LOOP
   i:= i +1; 
   j := instr(v_nombre,' ',1, i );  
   j1 :=   instr(v_nombre,' ',1, i+1 ); 

 IF j = 0 THEN
    EXIT;
  END IF;
    
   IF j1 - j <> 1 THEN
     v_cantidad_bloques_esp_blanco := v_cantidad_bloques_esp_blanco +1;
   END IF;

  END LOOP;
   dbms_output.put_line('cantidad de bloques de espacio en blanco = ' || v_cantidad_bloques_esp_blanco);

    WHILE (v_cantidad_espacios_blanco > v_cantidad_bloques_esp_blanco) LOOP


     v_cantidad_espacios_blanco := LENGTH(v_nombre) - LENGTH(v_nombre_sin_espacios);
     dbms_output.put_line(v_cantidad_espacios_blanco || ' -> ' || v_nombre);

      v_nombre :=  REPLACE(v_nombre, '  ', ' '); 
    
    END LOOP;
  dbms_output.put_line('R - > ' || v_nombre);

END;


En esta versión lo que se quiere encontrar primero es cuántos bloques de espacios en blancos hay. Esto se puede obtener gracias a la función instr que nos ayuda a encontrar el índice donde se encuentra tal caracter, es algo como el indexOf. En un loop infinito empiezo buscar espacios en blanco, la variable "j" va a buscar el primer espacio en blanco y "j1" el siguiente espacio en blanco.
si la resta es 1, quiere decir que están pegados. Cuando la resta sea mayor que uno, quiere decir que hay una palabra en el medio, cuando esto sucede puedo aumentar en 1 a mi contador de bloques de espacios en blanco (v_cantidad_bloques_esp_blanco).

En el siguiente ejemplo se puede asumir que mi contador aumentará en uno cuando se realice la resta entre el índice 11 menos el índice 5:


Una vez obtenido la cantidad de bloques de espacios en blanco, se empieza a realizar los cortes respectivos como se muestra en la primera versión del programa. Estos cortes se realizarán hasta que el número de espacios en blanco (v_cantidad_espacios_blanco) no sobrepase la cantidad de bloques de espacios en blanco (v_cantidad_bloques_esp_blanco).

El resultado al ejecutar el programa es el siguiente:

bloque anónimo terminado
cantidad de bloques de espacio en blanco = 2
33 -> Christian            Gonzales                     Komiya
17 -> Christian      Gonzales           Komiya
9 -> Christian   Gonzales      Komiya
5 -> Christian  Gonzales   Komiya
3 -> Christian Gonzales  Komiya
2 -> Christian Gonzales Komiya
R - > Christian Gonzales Komiya

Me agrada las impresiones, se puede ver claramente como se están realizando los cortes y como disminuyen los espacios en blanco  =)

Si por ahi alguien logró hacerlo de otra manera, por favor compartir!!!  XD


Comentarios

Ana ha dicho que…
Buenas tardes, estaba revisando su blog y quisiera ofrecerle unos artículos para que sean publicados en él. Tendría algún correo electrónico o teléfono por medio del cual podamos comunicarnos.
Christian Komiya ha dicho que…
Claro Ana, mi mail es christian.komiya@gmail.com