様々な基本になるサンプルを記録しています。

不定期更新です。

記事のサイドに使用している商品の紹介も掲載しているので、良ければご覧ください。

【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文字で区切るかを指定できるようにした。
文字の分割はいろいろなパターンがあって、その文字が実際にデータとして使われる文字になってしまうと色々と面倒なことになる。
その為に今回の第三引数を使って対応を広くできるようにした。

f:id:karinto441:20181026232548p:plain

分けるのであれば、第三引数はいらないのだけど
カンマでわけるときにダブルクォーテーションで囲んだ中にカンマがあったら、
そこで分かれてしまう可能性がある。
ダブルクォーテーションを除去するまでには行けなかったけど、
あとはreplace関数でそれぞれの要素に対して、消してあげればいい。