PL/SQL によるトークン(区切り文字による部分文字列)の取り出し
文字列を「ある区切り文字」 で切り出すファンクション
スペース区切りで単語を取り出したり、カンマ区切りのテキスト(CSV)などの部分文字列の切り出しに使用する。
ユーザー定義のストアド・ファンクション STRTOKEN の仕様
引数 | 内容 | デフォルト |
P_STRING | 対象文字列 | |
P_DELIMIT | トークンの区切り文字列 | |
P_POS | 切り出し開始 要素の番号(1〜) ≠ 文字位置 | 1 |
P_NTH | 切り出し要素数 | 1 |
P_EOD | 行末に到達時の戻り値 | NULL |
戻り値 | 切り出された文字列トークン | |
トークンの切り出しには 部分文字列の区切り位置を求めるための INSTR 関数 と 部分文字列を切り出すための SUBSTR 関数 を使用することで行なう。
注意点
このストアドファンクションは主に SQL から文字列切り出しを行なうためのもの。1つのトークンを切り出す毎に切り出す先頭位置と長さを求めている。応答時間を気にする PL/SQL バッチ処理のような繰り返し呼び出す用途には向いていないだろう。パフォーマンスが要求される場合には一度にすべてのトークンを配列形式で戻すようなストアドファンクションを作成した方が変換効率がよい。
また、文字列のデータの内部に区切り文字が存在する場合には項目の途中で切り出される。
カンマ区切りの文字列の分割例
SQL> set null '<NULL>'
SQL> select str,
2 strtoken(str, ',', 1) token1,
3 strtoken(str, ',', 2) token2,
4 strtoken(str, ',', 3) token3
5 from strtoken_sample;
STR TOKEN1 TOKEN2 TOKEN3
-------------------- -------------------- -------------------- --------------------
あああ,いいい,ううう あああ いいい ううう
あああ,いいい, あああ いいい <NULL>
あああ,いいい あああ いいい <NULL>
あああ, あああ <NULL> <NULL>
あああ あああ <NULL> <NULL>
,, <NULL> <NULL> <NULL>
行末に達したのかデータが空なのかを判別させる場合には 第5パラメータに終端をあらわす任意の文字列を指定する。
SQL> select str,
2 strtoken(str, ',', 1, 1, '<END_OF_DATA>') token1,
3 strtoken(str, ',', 2, 1, '<END_OF_DATA>') token2,
4 strtoken(str, ',', 3, 1, '<END_OF_DATA>') token3
5 from strtoken_sample;
STR TOKEN1 TOKEN2 TOKEN3
-------------------- -------------------- -------------------- --------------------
あああ,いいい,ううう あああ いいい ううう
あああ,いいい, あああ いいい <NULL>
あああ,いいい あああ いいい <END_OF_DATA>
あああ, あああ <NULL> <END_OF_DATA>
あああ あああ <END_OF_DATA> <END_OF_DATA>
,, <NULL> <NULL> <NULL>
関連事項
文字列切り出しファンクション STRTOKEN ソースコード
CREATE OR REPLACE FUNCTION RIVUS.STRTOKEN(
P_STRING VARCHAR2, P_DELIMIT VARCHAR2,
P_POS POSITIVEN := 1, P_NTH POSITIVEN := 1,
P_EOD VARCHAR2 := NULL)
RETURN VARCHAR2
IS
vStartPos PLS_INTEGER;
vEndPos PLS_INTEGER;
BEGIN
IF (P_POS = 1) THEN
vStartPos := 1;
ELSE
vStartPos := INSTR(P_STRING, P_DELIMIT, 1, P_POS - 1);
IF (vStartPos = 0) THEN
RETURN P_EOD;
END IF;
vStartPos := vStartPos + 1;
END IF;
vEndPos := INSTR(P_STRING, P_DELIMIT, vStartPos, P_NTH);
IF (vEndPos = 0) THEN
RETURN SUBSTR(P_STRING, vStartPos);
END IF;
RETURN SUBSTR(P_STRING, vStartPos, vEndPos - vStartPos);
END;
/
既存関数の上書きを防止するためにファンクション名の先頭に スキーマ名(RIVUS) が記述してあるので削除してください。
関連 SQL 関数