oracle tokenize string
Analizando cadena delimitada por tuberÃa en columnas? (3)
Tengo una columna con valores separados por tubería, como:
''23 | 12.1 | 450 | 30 | 9 | 78 | 82.5 | 92.1 | 120 | 185 | 52 | 11 ''
Quiero analizar esta columna para completar una tabla con 12 columnas correspondientes: mes1, mes2, mes3 ... mes12.
Entonces month1 tendrá el valor 23, month2, el valor 12.1, etc.
¿Hay alguna manera de analizarlo mediante un bucle o un delímetro en lugar de tener que separar un valor a la vez con substr?
Gracias.
Tenía 99 problemas. Utilicé expresiones regulares. Ahora tengo 100 problemas. Ja, ja, ja, ja, solo concatenar el delim en el principio y el final de la cadena.
solución pura de sql:
set define on
undefine string
undefine delim
undefine nth
accept string prompt ''Enter the string: ''
accept delim prompt ''Enter the delimiter: ''
accept nth prompt ''Enter nth: ''
select ''&&string'' as string,
''&&delim'' as delimiter,
&&nth||decode(&&nth,1,''st'',2,''nd'',3,''rd'',''th'') as nth,
substr(''&&delim''||''&&string''||''&delim'',
instr(''&&delim''||''&&string''||''&&delim'', ''&&delim'', 1, &&nth ) + length(''&&delim''),
instr(''&&delim''||''&&string''||''&&delim'', ''&&delim'', 1, &&nth + 1 ) - instr(''&&delim''||''&&string''||''&&delim'', ''&&delim'', 1, &&nth ) - length(''&&delim'')
) as val from dual
/
Puede usar regexp_substr
(10g +):
SQL> SELECT regexp_substr(''23|12.1| 450|30|9|'', ''[^|]+'', 1, 1) c1,
2 regexp_substr(''23|12.1| 450|30|9|'', ''[^|]+'', 1, 2) c2,
3 regexp_substr(''23|12.1| 450|30|9|'', ''[^|]+'', 1, 3) c3
4 FROM dual;
C1 C2 C3
-- ---- ----
23 12.1 450
Con un bucle en PL / SQL:
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 p_tsv VARCHAR2(1000) := ''23|12.1| 450|30|9|78|82.5|92.1|120|185|52|11'';
3 l_item VARCHAR2(100);
4 BEGIN
5 FOR i IN 1 .. length(p_tsv) - length(REPLACE(p_tsv, ''|'', '''')) + 1 LOOP
6 l_item := regexp_substr(p_tsv, ''[^|]+'', 1, i);
7 dbms_output.put_line(l_item);
8 END LOOP;
9 END;
10 /
23
12.1
450
30
9
78
82.5
92.1
120
185
52
11
PL/SQL procedure successfully completed
Actualizar
Solo tiene 12 columnas, escribiría la consulta directamente sin un bucle, será más eficiente y más fácil de mantener que el SQL dinámico (sin mencionar que es infinitamente más fácil de escribir):
INSERT INTO your_table
(ID, month1, month2, month3...)
SELECT :p_id,
regexp_substr(:p_tsv, ''[^|]+'', 1, 1) c1,
regexp_substr(:p_tsv, ''[^|]+'', 1, 2) c2,
regexp_substr(:p_tsv, ''[^|]+'', 1, 3) c3
...
FROM dual;