separado separada salida procedimientos procedimiento por partes parametros funciones extraer entrada ejecutar dividir developer con comas caracter campo cadena buscar almacenado oracle plsql tokenize

oracle - salida - División de cadena separada por comas en un proceso almacenado PL/SQL



procedimiento almacenado oracle select (8)

Aquí hay una buena solución:

FUNCTION comma_to_table(iv_raw IN VARCHAR2) RETURN dbms_utility.lname_array IS ltab_lname dbms_utility.lname_array; ln_len BINARY_INTEGER; BEGIN dbms_utility.comma_to_table(list => iv_raw ,tablen => ln_len ,tab => ltab_lname); FOR i IN 1 .. ln_len LOOP dbms_output.put_line(''element '' || i || '' is '' || ltab_lname(i)); END LOOP; RETURN ltab_lname; END;

Fuente: CSV - valores separados por comas - y PL / SQL (el enlace ya no es válido)

Tengo una cadena CSV 100.01,200.02,300.03 que necesito pasar a un procedimiento almacenado PL / SQL en Oracle. Dentro del proceso, necesito insertar estos valores en una columna de Número en la tabla.

Para esto, tengo un enfoque de trabajo desde aquí:

Cómo dividir mejor las cadenas de CSV en Oracle 9i

[2] Usando SQL conecta por nivel.].

Ahora, tengo otro requisito. Necesito pasar 2 cadenas CSV [igual de longitud] como entrada al proceso almacenado PL / SQL. Y necesito romper esta cadena e insertar cada valor de dos cadenas CSV en dos columnas diferentes en la tabla. ¿Podrían por favor dejarme ¿Sabes cómo hacerlo?

Ejemplo de entradas CSV: mystring varchar2 (2000): = ''0.75, 0.64, 0.56, 0.45'';

myAmount varchar2 (2000): = ''0.25, 0.5, 0.65, 0.8'';

Los valores de myString entrarían en los valores de Columna A y myAmount en la Columna B de la tabla.

¿Podrías decirme cómo lograr esto?

Gracias.


En cuanto al caso de connect by uso, este enfoque debería funcionar para usted:

select regexp_substr(''SMITH,ALLEN,WARD,JONES'',''[^,]+'', 1, level) from dual connect by regexp_substr(''SMITH,ALLEN,WARD,JONES'', ''[^,]+'', 1, level) is not null;


Esto debería hacer lo que estás buscando. Supone que tu lista siempre será solo números. Si ese no es el caso, simplemente cambie las referencias a DBMS_SQL.NUMBER_TABLE por un tipo de tabla que funcione para todos sus datos:

CREATE OR REPLACE PROCEDURE insert_from_lists( list1_in IN VARCHAR2, list2_in IN VARCHAR2, delimiter_in IN VARCHAR2 := '','' ) IS v_tbl1 DBMS_SQL.NUMBER_TABLE; v_tbl2 DBMS_SQL.NUMBER_TABLE; FUNCTION list_to_tbl ( list_in IN VARCHAR2 ) RETURN DBMS_SQL.NUMBER_TABLE IS v_retval DBMS_SQL.NUMBER_TABLE; BEGIN IF list_in is not null THEN /* || Use lengths loop through the list the correct amount of times, || and substr to get only the correct item for that row */ FOR i in 1 .. length(list_in)-length(replace(list_in,delimiter_in,''''))+1 LOOP /* || Set the row = next item in the list */ v_retval(i) := substr ( delimiter_in||list_in||delimiter_in, instr(delimiter_in||list_in||delimiter_in, delimiter_in, 1, i ) + 1, instr (delimiter_in||list_in||delimiter_in, delimiter_in, 1, i+1) - instr (delimiter_in||list_in||delimiter_in, delimiter_in, 1, i) -1 ); END LOOP; END IF; RETURN v_retval; END list_to_tbl; BEGIN -- Put lists into collections v_tbl1 := list_to_tbl(list1_in); v_tbl2 := list_to_tbl(list2_in); IF v_tbl1.COUNT <> v_tbl2.COUNT THEN raise_application_error(num => -20001, msg => ''Length of lists do not match''); END IF; -- Bulk insert from collections FORALL i IN INDICES OF v_tbl1 insert into tmp (a, b) values (v_tbl1(i), v_tbl2(i)); END insert_from_lists;


No estoy seguro de si esto se ajusta a su versión de Oracle. En mi 10g puedo usar funciones de tabla canalizadas:

set serveroutput on create type number_list as table of number; -- since you want this solution create or replace function split_csv (i_csv varchar2) return number_list pipelined is mystring varchar2(2000):= i_csv; begin for r in ( select regexp_substr(mystring,''[^,]+'',1,level) element from dual connect by level <= length(regexp_replace(mystring,''[^,]+'')) + 1 ) loop --dbms_output.put_line(r.element); pipe row(to_number(r.element, ''999999.99'')); end loop; end; / insert into foo select column_a,column_b from (select column_value column_a, rownum rn from table(split_csv(''0.75, 0.64, 0.56, 0.45''))) a ,(select column_value column_b, rownum rn from table(split_csv(''0.25, 0.5, 0.65, 0.8''))) b where a.rn = b.rn ;


Ya se han proporcionado muchas buenas soluciones. Sin embargo, si el texto se proporciona en un formato delimitado por comas simple o similar, y la velocidad es importante, entonces tengo para usted una solución con una función TABLE (en PL / SQL). También proporcioné un resumen de algunas otras soluciones.

Por favor, consulte más en Blog Entry on Parsing CSV en varias columnas .


Yo uso apex_util.string_to_table para analizar cadenas, pero puedes usar un analizador diferente si lo deseas. Luego puede insertar los datos como en este ejemplo:

declare myString varchar2(2000) :=''0.75, 0.64, 0.56, 0.45''; myAmount varchar2(2000) :=''0.25, 0.5, 0.65, 0.8''; v_array1 apex_application_global.vc_arr2; v_array2 apex_application_global.vc_arr2; begin v_array1 := apex_util.string_to_table(myString, '', ''); v_array2 := apex_util.string_to_table(myAmount, '', ''); forall i in 1..v_array1.count insert into mytable (a, b) values (v_array1(i), v_array2(i)); end;

Apex_util está disponible desde Oracle 10G en adelante. Antes de esto, se llamaba htmldb_util y no se instalaba de manera predeterminada. Si no puede usar eso, podría usar el analizador de cadenas que escribí hace muchos años y lo publiqué here .


crear o reemplazar el procedure pro_ss(v_str varchar2) como

v_str1 varchar2(100); v_comma_pos number := 0; v_start_pos number := 1; begin loop v_comma_pos := instr(v_str,'','',v_start_pos); if v_comma_pos = 0 then v_str1 := substr(v_str,v_start_pos); dbms_output.put_line(v_str1); exit; end if; v_str1 := substr(v_str,v_start_pos,(v_comma_pos - v_start_pos)); dbms_output.put_line(v_str1); v_start_pos := v_comma_pos + 1; end loop; end; / call pro_ss(''aa,bb,cc,dd,ee,ff,gg,hh,ii,jj'');

outout: aa bb cc dd ee ff gg hh ii jj


CREATE OR REPLACE PROCEDURE insert_into ( p_errcode OUT NUMBER, p_errmesg OUT VARCHAR2, p_rowsaffected OUT INTEGER ) AS v_param0 VARCHAR2 (30) := ''0.25,2.25,33.689, abc, 99''; v_param1 VARCHAR2 (30) := ''2.65,66.32, abc-def, 21.5''; BEGIN FOR i IN (SELECT COLUMN_VALUE FROM TABLE (SPLIT (v_param0, '',''))) LOOP INSERT INTO tempo (col1 ) VALUES (i.COLUMN_VALUE ); END LOOP; FOR i IN (SELECT COLUMN_VALUE FROM TABLE (SPLIT (v_param1, '',''))) LOOP INSERT INTO tempo (col2 ) VALUES (i.COLUMN_VALUE ); END LOOP; END;