在PL/SQL存储过程中拆分逗号分隔的字符串

Jim*_*mmy 22 oracle plsql tokenize

我有CSV字符串100.01,200.02,300.03,我需要传递给Oracle中的PL/SQL存储过程.在proc中,我需要在表格的Number列中插入这些值.

为此,我从这里得到了一个工作方法:

如何在oracle 9i中最好地分割csv字符串

[2]按级别使用SQL连接.

现在,我有另一个要求.我需要传递2个CSV字符串[长度相等]作为PL/SQL存储过程的输入.我需要打破这个字符串并将两个CSV字符串中的每个值插入表格中的两个不同列.请你让我知道怎么去吗?

CSV输入示例:mystring varchar2(2000):='0.75,0.64,0.56,0.45';

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

myString值将进入A列,myAmount值进入表中的B列.

你能告诉我如何实现这个目标吗?

谢谢.

Mic*_*eyn 8

这是一个很好的解决方案:

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;
Run Code Online (Sandbox Code Playgroud)

来源:CSV - 逗号分隔值 - 和PL/SQL(链接不再有效)


Cra*_*aig 8

这应该做你想要的..它假设你的列表将永远只是数字.如果不是这种情况,只需将对DBMS_SQL.NUMBER_TABLE的引用更改为适用于所有数据的表类型:

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; 
Run Code Online (Sandbox Code Playgroud)


Ton*_*ews 6

我使用apex_util.string_to_table来解析字符串,但如果您愿意,可以使用不同的解析器.然后您可以插入数据,如下例所示:

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;
Run Code Online (Sandbox Code Playgroud)

Apex_util可从Oracle 10G开始提供.在此之前,它被称为htmldb_util,默认情况下未安装.如果你不能使用它,你可以使用我多年前写的字符串解析器并发布在这里.