ORACLE 正規表現 CSVデータの分割

先日、DBに格納されているCSV形式のデータの一部を置換するSQLをつくった際に
正規表現を使うことになったので、整理しておきたいと思う。

今回やりたいこと:
 CSV形式で格納されたデータを、1項目ごとに分割する

◆INPUTデータ
下記のようにCSVのデータがあったとする。
今回は、大手銀行、時価総額、本店所在地がCSV形式で格納されている。

CSV_DATA
-----------------------------------------------------------------------------------------------------------
"三菱東京UFJ銀行","10,204,409","〒100-8388","東京都千代田区丸の内2-7-1"
"みずほ銀行","5,326,047","〒100-8176","東京都千代田区大手町1-5-5"
"三井住友銀行","6,306,688","〒100-0005","東京都千代田区丸の内一丁目1番2号"

◆SQL
 カンマ区切りのデータを1項目ごとに分割する。
 ”時価総額”など、金額の項目にはカンマ区切りで入っているので考慮する必要がある。
 

 


SQL> select REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,1) from ADDRESS;

REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,1)
----------------------------------------------------------------------------------------
"三菱東京UFJ銀行",
"みずほ銀行",
"三井住友銀行",

SQL> select REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,2) from ADDRESS;

REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,2)
----------------------------------------------------------------------------------------
"10,204,409",
"5,326,047",
"6,306,688",

SQL> select REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,3) from ADDRESS;

REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,3)
----------------------------------------------------------------------------------------
"〒100-8388",
"〒100-8176",
"〒100-0005",

SQL> select REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,4) from ADDRESS;

REGEXP_SUBSTR(CSV_DATA,'("[^"]*",{0,1})|(,{0,1}[^,]*,)',1,4)
----------------------------------------------------------------------------------------
"東京都千代田区丸の内2-7-1"
"東京都千代田区大手町1-5-5"
"東京都千代田区丸の内一丁目1番2号"

◆説明
 ・REGEXP_SUBSTR
  正規表現が扱えるOracle関数は下記のような関数ある。今回はREGEXP_SUBSTRを利用した。
   REGEXP_LIKE
   REGEXP_COUNT
   REGEXP_INSTR
   REGEXP_REPLACE
   REGEXP_SUBSTR

 ・正規表現
  ①or②の場合に抽出されるようにする。

  ① ("[^"]*",{0,1})
   () ・・・括弧の中を組合せとするための括弧
   " ・・・1文字目に"が入っている場合
   [^"]* ・・・"ではない文字が*(複数回)続く場合
   " ・・・項目の最後の"の場合
   ,{0,1} ・・・カンマが0回か1回の場合

  ② (,{0,1}[^,]*,)
   () ・・・括弧の中を組合せとするための括弧
   ,{0,1} ・・・カンマが0回か1回の場合
   [^,]* ・・・カンマじゃない文字が*(複数回)続く場合
   , ・・・最後がカンマ

これじゃうまくいかないケースがあるからもうちょっと改良する。