【Oracle】よくあるSPLIT関数を実装する。
さすがにそのままの仕様を実現することはできなかったが、
かろうじてそれに近いものを公開しようと思う。
今回使用しているTYPEは以下を参照
fubukin.hatenablog.com
create or replace FUNCTION SPLIT_REC ( /* 引数: STR :区切り文字の入った文字列 STR_SPLIT :判定対象文字列 PUSH_NUM :STR_SPLITの文字列の何番目で分割するか設定(デフォルトは最初の文字) 戻り値: VALIE01:要素番号 VALUE02:値 VALUE03:値の文字数 VALUE04:値のバイト数 */ STR VARCHAR2, STR_SPLIT VARCHAR2, PUSH_NUM NUMBER DEFAULT 0 ) RETURN STD_VALUE4_TABLE PIPELINED IS W_RET_REC STD_VALUE4; W_STR VARCHAR2(32760) := STR; T_STR VARCHAR2(32760) := ''; I NUMBER(38); VSTARTPOS NUMBER(38); VENDPOS NUMBER(38); BEGIN I := 1; IF STR IS NULL THEN RETURN; END IF; LOOP W_RET_REC := STD_VALUE4(' ',' ',' ',' '); VSTARTPOS := 1; VENDPOS := INSTR(W_STR,STR_SPLIT,VSTARTPOS,1); IF ( VENDPOS = 0 ) THEN W_RET_REC.VALUE01 := I; W_RET_REC.VALUE02 := SUBSTR(W_STR,VSTARTPOS); W_RET_REC.VALUE03 := TO_CHAR(NVL(LENGTH(W_RET_REC.VALUE02),0) ); W_RET_REC.VALUE04 := TO_CHAR(NVL(LENGTHB(W_RET_REC.VALUE02),0) ); PIPE ROW ( W_RET_REC ); RETURN; ELSE VENDPOS := VENDPOS + PUSH_NUM; END IF; W_RET_REC.VALUE01 := TO_CHAR(I); W_RET_REC.VALUE02 := SUBSTR(W_STR,VSTARTPOS,VENDPOS - VSTARTPOS); W_RET_REC.VALUE03 := TO_CHAR(NVL(LENGTH(W_RET_REC.VALUE02),0) ); W_RET_REC.VALUE04 := TO_CHAR(NVL(LENGTHB(W_RET_REC.VALUE02),0) ); PIPE ROW ( W_RET_REC ); T_STR := SUBSTR(W_STR,VENDPOS); W_STR := SUBSTR(W_STR,VENDPOS + 1); IF T_STR IS NULL THEN EXIT; END IF; I := I + 1; END LOOP; RETURN; EXCEPTION WHEN OTHERS THEN W_RET_REC.VALUE01 := 0; W_RET_REC.VALUE04 := SQLERRM; PIPE ROW ( W_RET_REC ); RETURN; END;
デルミタ文字を1文字指定でしかできなかったので、
第三引数にデルミタ文字が2文字以上だったら、デルミタ文字のどの1文字で区切るかを指定できるようにした。
文字の分割はいろいろなパターンがあって、その文字が実際にデータとして使われる文字になってしまうと色々と面倒なことになる。
その為に今回の第三引数を使って対応を広くできるようにした。
分けるのであれば、第三引数はいらないのだけど
カンマでわけるときにダブルクォーテーションで囲んだ中にカンマがあったら、
そこで分かれてしまう可能性がある。
ダブルクォーテーションを除去するまでには行けなかったけど、
あとはreplace関数でそれぞれの要素に対して、消してあげればいい。