views:

45

answers:

2

Hello, I have a column with pipe separated values such as:

'23|12.1| 450|30|9|78|82.5|92.1|120|185|52|11'

I want to parse this column to fill a table with 12 corresponding columns: month1, month2, month3...month12.

So month1 will have the value 23, month2 the value 12.1 etc...

Is there a way to parse it by a loop or delimeter instead of having to separate one value at a time using substr?

Thanks.

A: 

I don't think there's something already defined.

There are few implementations at orafaq and I found this also.

Unreason
+3  A: 

You can use 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

With a loop in 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

Update

You only have 12 columns, I would write the query direcly without a loop, it will be more performant and easier to maintain than dynamic SQL (not to mention infinitely easier to write):

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;
Vincent Malgrat
Thanks Vincent, your post is helpful, but that does not address the whole problem. It is not parsing the string that is the problem as much as it is inserting them into the columns respectively.As in what could be added into the loop to insert the values one column at a time? or insert them all into a record in a separate table?I think that the fact that all columns end with something like an index (month1, month2, month3...) there should be a way to access and update them independently in the loop.Thanks
DMS
@DMS: I would not use dynamic SQL in such a case. A single statement is the way to go, both for performance reason and code maintainability.
Vincent Malgrat
OK. noted thanks.
DMS