post icon

Separar texto en pl/sql

Buenas a todos, con este codigo podemos separar textos, si es que tenemos en una columna de una tabla por ejemplo el nombre completo de la persona, como tambien pùede ser una persona juridica, aqui va el script, query o como quieran llamarlo.
Primeramente declaro las variables primer_espacio y segundo_espacio para ver en que posicion se encuentran los espacios entre cada palabra
luego las variables para primer nombre, segundo nombre, primer apellido y segundo apellido, para el nombre de las empresas usaremos la variable de primer nombre, también utilizo 3 cursores para ir leyendo, uno para los nombres, otro para los apellidos y otro para las personas juridicas. Los nombres se encuentran en una columna separados por un espacio en blanco y los apellidos también en otra columna separados por un espacio en blanco, lo que hago es abrir y recorrer cada cursor, y en cada lectura del cursor busco los espacios en blanco de cada linea leída, entonces, cuando recorremos el cursor de nombres, busco la posición del espacio en blanco de la cadena, si la posición > 0 entonces quiere decir que al menos hay 2 nombres, entonces el primer nombre seria hasta la posición del primer espacio en blanco – 1 y el segundo nombre seria desde la posición del primer espacio en blanco + 1, de esa manera voy guardando los valores leidos en primer_nombre y segundo_nombre, luego de haber leido inserto los valores separados en una tabla , ya con columnas separadas, es decir, primer nombre, segundo nombre, primer apellido y segundo apellido
Lo mismo hago con el cursor de apellidos, pero en vez de insertar , actualizo las columnas de primer apellido y segundo apellido.
Lo mismo ocurre con el 3er cursor, solamente que aca no preguntamos por espacios en blanco por que nos interesa toda la cadena que corresponde a la razon social de la empresa.
Para buscar algun caracter en pl/sql usamos la funcion instr(‘cadena de texto’,’ ‘,1)
argumentos:
1- cualquier cadena de texto

2- en mi caso busco espacios en blanco, entonces pongo ‘ ‘, pero podrian querer buscar otro caracter, por ejemplo ‘-‘ , ‘_’,’*’,’a’,’B’,’1′, y un largo etc..
3- corresponde desde que posicion queremos buscar
retorna un numero que corresponde a la posicion del caracter buscado como 2do argumento, null en caso contrario
Si no queremos que retorne null debemos usar la funcion nvl
de esta forma –> nvl(instr(‘cadena de texto’,’ ‘,1),0), si la funcion instr no encontro ningun espacio, retornara 0, aun que en este caso retornara 7, por que en la posicion 7 encontro el espacio en blanco, de esta forma retornara 0 –> nvl(instr(‘cadena’,’ ‘,1),0.

Tambien utilizo un query dinamiquito, que borra la tabla antes de empezar el ciclo, eso se consigue con la siguiente sentencia

execute immediate sql
donde sql seria una variable de tipo varchar que contendra el query, por ejemplo

1
sql varchar:= 'truncate table nombre_tabla'

y eso es todo amigos, ojala le sirva a alguien, saludos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
DECLARE
primer_espacio   number(3);
segundo_espacio  number(3);
tercer_espacio  number(3);
primer_nombre    varchar2(30);
v_primer_apellido  varchar2(30);
v_razon_social  varchar2(80);
segundo_nombre   varchar2(30);
tercer_nombre   varchar2(30);
v_segundo_apellido varchar2(30);
sqldinamico varchar2(200) := 'truncate table dato_usuario_holapy '; 
 
cursor persona_nombre is
select p.rf_nombre,f.ta_nrtarj1
from personas_ref@prod1 p,
ftmaeta f
where p.rf_tipo_ident = 'CI'
and f.ta_cediden = p.rf_numero
and substr(f.ta_nrtarj1,1,8) = '10991041';
 
cursor persona_apellido is
select p.rf_apellido,f.ta_nrtarj1
from personas_ref@prod1 p,
ftmaeta f
where p.rf_tipo_ident = 'CI'
and f.ta_cediden = p.rf_numero
and substr(f.ta_nrtarj1,1,8) = '10991041';
 
cursor billto_holapy is
select f.ta_nrtarj1,f.ta_cediden,p.rf_nombre
from personas_ref@PROD1 p ,
ftmaeta f
where p.rf_tipo_ident ='RUC'
and f.ta_cediden = REPLACE(p.rf_numero,'-','')
and substr(f.ta_nrtarj1,1,8) = '10991041'
and p.rf_numero like '800%';
 
begin
execute immediate sqldinamico;
for x in persona_nombre loop
 
select nvl(instr(x.rf_nombre,' ',1),0)
into primer_espacio
from dual; --busca el primer espacio en la cadena
 
select nvl(instr(x.rf_nombre,' ',1,2),0)
into segundo_espacio
from dual; --busca el segundo espacio en la cadena
 
if primer_espacio > 0 then
select nvl(substr(x.rf_nombre,1,primer_espacio-1),'')
into primer_nombre
from dual ;
 
select nvl(substr(x.rf_nombre,primer_espacio+1),'')
into segundo_nombre
from dual ;
else
select nvl(substr(x.rf_nombre,1),'')
into primer_nombre
from dual ;
end if;
 
insert into dato_usuario_holapy(nro_tarjeta
,primer_nombre
,segundo_nombre
,tipo_persona)
values(x.ta_nrtarj1
,primer_nombre
,segundo_nombre
,'P') ;
end loop;
 
for x1 in persona_apellido loop
 
select nvl(instr(x1.rf_apellido,' ',1),0)
into primer_espacio
from dual; --busca el primer espacio en la cadena
 
select nvl(instr(x1.rf_apellido,' ',1,2),0)
into segundo_espacio
from dual; --busca el segundo espacio en la cadena
 
if primer_espacio > 0 then
select nvl(substr(x1.rf_apellido,1,primer_espacio-1),'')
into v_primer_apellido
from dual ;
 
select nvl(substr(x1.rf_apellido,primer_espacio+1),'')
into v_segundo_apellido
from dual ;
else
select nvl(substr(x1.rf_apellido,1),'')
into v_primer_apellido
from dual ;
end if;
 
update dato_usuario_holapy
set primer_apellido = v_primer_apellido,
segundo_apellido = v_segundo_apellido
where nro_tarjeta = x1.ta_nrtarj1;
 
end loop;
 
for x2 in billto_holapy loop
select x2.rf_nombre
into v_razon_social
from dual;
 
insert into dato_usuario_holapy(nro_tarjeta
,primer_nombre
,tipo_persona
)
values(x2.ta_nrtarj1
,v_razon_social
,'E') ;
 
end loop;
commit;
 
exception
when no_Data_found then
null;
 
END;

Comentarios desde Facebook:

  1. avatar
    MarCraft PARAGUAY Google Chrome Windows
    26 septiembre 2012 at 17:34 #

    Andaba paseando por la pagina y me encontré con este topic, y recordé un código de una función en PL/SQL que realice para un caso parecido.. para este caso se aplicaban solo casos 2 nombres y 2 apellidos que son devueltos en un cursor.

    ej: pi_nombre:= JUAN JULIAN PEREZ PEREIRA // DEVUELVE EN UN CURSOR SEPARADO NOMBRE1-NOMBRE2-APELLIDO1-APELLIDO2

    caso era una persona con un solo nombre o apellido se debe de mandar un espacio de mas en el lugar que corresponda.

    ej: pi_nombre:= JUAN PEREZ PEREIRA //DEVUELVE NULO EL SEGUNDO NOMBRE

    este es la función por si alguien le sirve…

    function f_separa_nombre(pi_nombre in varchar2)
    return sys_refcursor is
    v_1nombre varchar2(60);
    v_2nombre varchar2(60);
    v_1apellido varchar2(60);
    v_2apellido varchar2(60);
    v_cant float default 0;
    v_aux varchar2(15);
    v_cursor sys_refcursor;
    v_caso float default 0;
    v_posta float default 0;
    v_ciclo float default 0;
    v_nom varchar2(240) default pi_nombre||’ ‘;

    begin

    select length(v_nom) into v_cant from dual;

    while v_ciclov_cant loop

    v_aux := substr2(v_nom,v_ciclo,1);

    if v_aux = ‘ ‘ then

    case
    when v_caso=0 then
    v_1nombre := substr2(v_nom,1,v_ciclo-1);
    v_posta :=v_ciclo+1;

    when v_caso=1 then
    v_2nombre := substr2(v_nom,v_posta,v_ciclo-v_posta);
    v_posta :=v_ciclo+1;

    when v_caso=2 then
    v_1apellido:= substr2(v_nom,v_posta,v_ciclo-v_posta);
    v_posta :=v_ciclo+1;

    when v_caso=3 then
    v_2apellido:= substr2(v_nom,v_posta,v_ciclo-v_posta);
    v_posta :=v_ciclo+1;
    end case;

    v_caso:=v_caso+1;
    end if;

    v_ciclo:=v_ciclo+1;

    end loop;

    open v_cursor for
    select trim(v_1nombre) nombre1,
    trim(v_2nombre) nombre2,
    trim(v_1apellido) apellido1,
    trim(v_2apellido) apellido2
    from dual;

    return v_cursor;

    obviamente se puede optimizar la función para que me devuelva mas de 2 nombres y 2 apellidos.. como también se puede agregar un parámetro mas de entrada para usar como “carácter de separación” y no evaluar solo si es espacio.

    Saludos

    • avatar
      jesus MEXICO Mozilla Windows
      13 agosto 2014 at 16:43 #

      while v_ciclov_cant loop

      Aquí no entendí que onda???

      • avatar
        MarCraft PARAGUAY Google Chrome Windows
        13 agosto 2014 at 17:25 #

        while v_ciclo “distinto” v_cant loop.. no se pueden colocar los signos de mayor o menor dentro del comentario

    • avatar
      MarCraft PARAGUAY Google Chrome Windows
      13 agosto 2014 at 17:24 #

      No se copio el “distinto”.. tendría que ser v_ciclo v_cant

      • avatar
        jes MEXICO Mozilla Windows
        14 agosto 2014 at 11:50 #

        muchas gracias, ya me funciono el ejemplo ahora lo que quiero es dividir una columna en donde cada registro tiene varios espacios, y la subcadena entre cada espacio la quiero en la misma columna pero en diferente fila de otra tabla_aux para poder hacer las relaciones muchos a muchos.

        • avatar
          MarCraft PARAGUAY Google Chrome Windows
          14 agosto 2014 at 14:07 #

          entiendo a medias..
          podrías ejemplificar?

          tipo

          Fila columna1
          ————–
          1 juan perez
          2 carlos gonzales

          y el procedimiento recorra cada registro, separe las palabras e inserte como nuevas filas?

          Fila columna1
          ————–
          1 juan perez
          2 carlos gonzales
          3 juan
          4 perez
          5 carlos
          6 gonzales

        • avatar
          jes MEXICO Mozilla Windows
          14 agosto 2014 at 15:42 #

          TE EXPLICO:
          table_glosario

          palab fuente
          A XX YY
          B ZZ WW

          llave primaria palab.

          Lo que quiero es algo asi:

          table_glosario_aux

          palab fuente
          A XX
          A YY
          B ZZ
          B WW

          Porque de lo que he investigado con esta tabla auxiliar dejaría como llave primaria (palab y fuente)y asi podría hacer relación con otra tabla:

          table_fuentes

          cve_fuente fuente descripción
          1 XX (EXPLICA LA FUENTE)
          2 YY

          Me entiendes espero me puedas ayudar??

        • avatar
          MarCraft PARAGUAY Google Chrome Windows
          14 agosto 2014 at 16:30 #

          ME FUNCIONO PERFECTAMENTE.. SI NO SE COPIA BIEN EN EL COMENTARIO escribime en mi correo marcraft.12.04@gmail.com

          PROCEDURE SP_PRUEBA IS
          V_POS FLOAT DEFAULT 0;
          V_AUX FLOAT DEFAULT 0;
          V_FUENTE TABLE_GLOSARIO.FUENTE%TYPE;
          V_PALABRA TABLE_GLOSARIO.FUENTE%TYPE;

          BEGIN

          FOR M IN (SELECT * FROM table_glosario)LOOP
          V_FUENTE := TRIM(M.FUENTE);–SACO ESPACIOS
          V_AUX := 0;
          WHILE (V_AUX 1)LOOP
          V_POS := INSTR(V_FUENTE,’ ‘);–POSICION DE ESPACIO

          IF V_POS > 0 THEN
          V_PALABRA := TRIM(SUBSTR(V_FUENTE,0,V_POS));–GUARDO LA PALABRA HASTA EL ESPACIO
          V_FUENTE := TRIM(SUBSTR(V_FUENTE,V_POS,LENGTH(V_FUENTE)));–AJUSTO MI FUENTE SACO LA PALABRA GUARDADA
          ELSE
          V_PALABRA := V_FUENTE; –NO TIENE MAS ESPACIOS, GUARDO ULTIMA PALABRA
          V_AUX := 1; –ASIGNACION POR ULTIMA VUELTA
          END IF;
          –INSERTO LAS PALABRAS
          INSERT INTO TABLE_GLOSARIO_AUX(PALAB,FUENTE) VALUES (M.PALAB,V_PALABRA);

          END LOOP;
          END LOOP;

          END SP_PRUEBA;

  2. avatar
    jlvs PERU Google Chrome Windows
    10 junio 2010 at 16:24 #

    hola brother, esta bien tu algoritmo, perooo… que tiene de malo hacerlo con la funcion POSITION(espacio en blanco in 1ernombre 2donombre), esto me vota un entero y pues lo almaceno en variables, vota el numero donde se encuentra el espacio en blanco, ahora con la funcion RIGHT(nombres, variable q se alamaceno el valor de position) y asi con LEFT(). Bueno por cuestion d tiempo no te lo explico como es pero… mi pregunta es, tiene algo de malo hacerlo de la manera que la hago yo? quisiera saber si tiene defectos sino para hacer de la forma en que tu lo haces…

    • avatar
      pg_shadow PARAGUAY Google Chrome Windows
      11 junio 2010 at 05:47 #

      Hola amigo, que tal, esa funcion POSITION de oracle no la conocia, seguro hay muchas formas de solucionar eso, de todas formas seria bueno que tu escribas tu codigo, asi lo vemos todos y aprendemos

      Saludos

    • avatar
      carlos VENEZUELA Mozilla Firefox Linux
      8 noviembre 2011 at 17:51 #

      lo malo de la función POSITION es que devuelve la posición de la primera coincidencia encontrada, así, si existen varios espacios en blanco detectarás el primer espacio pero para los demas deberás hacer un bucle con la parte sobrante hasta que no encuentres espacios!!!

Responder