sql >> データベース >  >> RDS >> Oracle

Oracle9iでcsv文字列を最適に分割する方法

    ジョイス、

    次に3つの例を示します。

    1)dbms_utility.comma_to_tableを使用します。要素は有効な識別子である必要があるため、これは汎用ルーチンではありません。いくつかの汚いトリックで、それをより普遍的に機能させることができます:

    SQL> declare
      2    cn_non_occuring_prefix constant varchar2(4) := 'zzzz';
      3    mystring varchar2(2000):='a:sd:dfg:31456:dasd: :sdfsdf'; -- just an example
      4    l_tablen binary_integer;
      5    l_tab    dbms_utility.uncl_array;
      6  begin
      7    dbms_utility.comma_to_table
      8    ( list   => cn_non_occuring_prefix || replace(mystring,':',','||cn_non_occuring_prefix)
      9    , tablen => l_tablen
     10    , tab    => l_tab
     11    );
     12    for i in 1..l_tablen
     13    loop
     14      dbms_output.put_line(substr(l_tab(i),1+length(cn_non_occuring_prefix)));
     15    end loop;
     16  end;
     17  /
    a
    sd
    dfg
    31456
    dasd
    
    sdfsdf
    
    PL/SQL-procedure is geslaagd.
    

    2)レベルごとのSQLの接続を使用します。 10g以上を使用している場合は、次のような正規表現と組み合わせてレベルごとの接続アプローチを使用できます。

    SQL> declare
      2    mystring varchar2(2000):='a:sd:dfg:31456:dasd: :sdfsdf'; -- just an example
      3  begin
      4    for r in
      5    ( select regexp_substr(mystring,'[^:]+',1,level) element
      6        from dual
      7     connect by level <= length(regexp_replace(mystring,'[^:]+')) + 1
      8    )
      9    loop
     10      dbms_output.put_line(r.element);
     11    end loop;
     12  end;
     13  /
    a
    sd
    dfg
    31456
    dasd
    
    sdfsdf
    
    PL/SQL-procedure is geslaagd.
    

    3)SQLのレベル別接続を再度使用しますが、バージョン9を使用している場合は、古き良きSUBSTR/INSTRと組み合わせて使用​​します。

        SQL> declare
          2    mystring varchar2(2000):='a:sd:dfg:31456:dasd: :sdfsdf'; -- just an example
          3  begin
          4    for r in
          5    ( select substr
          6             ( str
          7             , instr(str,':',1,level) + 1
          8             , instr(str,':',1,level+1) - instr(str,':',1,level) - 1
          9             ) element
         10        from (select ':' || mystring || ':' str from dual)
         11     connect by level <= length(str) - length(replace(str,':')) - 1
         12    )
         13    loop
         14      dbms_output.put_line(r.element);
         15    end loop;
         16  end;
         17  /
        a
        sd
        dfg
        31456
        dasd
    
        sdfsdf
    
    PL/SQL-procedure is geslaagd.
    

    このようなテクニックについては、次のブログ投稿をご覧ください:http://rwijk.blogspot.com/2007/11/interval-based-row-generation.html

    これがお役に立てば幸いです。

    よろしく、ロブ。

    コメントに対処するには:

    分離された値を正規化されたテーブルに挿入する例。

    最初にテーブルを作成します:

    SQL> create table csv_table (col)
      2  as
      3  select 'a,sd,dfg,31456,dasd,,sdfsdf' from dual union all
      4  select 'a,bb,ccc,dddd' from dual union all
      5  select 'zz,yy,' from dual
      6  /
    
    Table created.
    
    SQL> create table normalized_table (value varchar2(10))
      2  /
    
    Table created.
    

    あなたはdbms_utility.comma_to_tableアプローチに興味を持っているように思われるので、ここで言及します。ただし、識別子の癖と行ごとの処理が遅いため、このバリアントはお勧めしません。

    SQL> declare
      2    cn_non_occuring_prefix constant varchar2(4) := 'zzzz';
      3    l_tablen binary_integer;
      4    l_tab    dbms_utility.uncl_array;
      5  begin
      6    for r in (select col from csv_table)
      7    loop
      8      dbms_utility.comma_to_table
      9      ( list   => cn_non_occuring_prefix || replace(r.col,',',','||cn_non_occuring_prefix)
     10      , tablen => l_tablen
     11      , tab    => l_tab
     12      );
     13      forall i in 1..l_tablen
     14        insert into normalized_table (value)
     15        values (substr(l_tab(i),length(cn_non_occuring_prefix)+1))
     16      ;
     17    end loop;
     18  end;
     19  /
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from normalized_table
      2  /
    
    VALUE
    ----------
    a
    sd
    dfg
    31456
    dasd
    
    sdfsdf
    a
    bb
    ccc
    dddd
    zz
    yy
    
    
    14 rows selected.
    

    この単一のSQLバリアントをお勧めします:

    SQL> truncate table normalized_table
      2  /
    
    Table truncated.
    
    SQL> insert into normalized_table (value)
      2   select substr
      3          ( col
      4          , instr(col,',',1,l) + 1
      5          , instr(col,',',1,l+1) - instr(col,',',1,l) - 1
      6          )
      7     from ( select ',' || col || ',' col from csv_table )
      8        , ( select level l from dual connect by level <= 100 )
      9    where l <= length(col) - length(replace(col,',')) - 1
     10  /
    
    14 rows created.
    
    SQL> select * from normalized_table
      2  /
    
    VALUE
    ----------
    a
    a
    zz
    sd
    bb
    yy
    dfg
    ccc
    
    31456
    dddd
    dasd
    
    sdfsdf
    
    14 rows selected.
    

    よろしく、ロブ。



    1. Postgresクエリウィンドウのパラメータを使用してアドホックSQLをテストする方法

    2. MySQLまたはMariaDBGaleraクラスターでレプリケーションパフォーマンスを向上させる方法

    3. MySQLの最新性からパーセンタイルを計算する

    4. 小数点以下8桁の緯度/経度には、どのMySQLデータ型を使用する必要がありますか?