トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

10-243 場合分けを使う正規表現

SQLパズル

strTable
Val
-----------------
a,b,c<x,y,z>
a,b,c
,,,,a
a,,b,,c,,d
<a,b,c,d>eee<f,g>

<と>で囲まれてないカンマを削除する。

出力結果
Val                NewVal
-----------------  -----------------
a,b,c<x,y,z>       abc<x,y,z>
a,b,c              abc
,,,,a              a
a,,b,,c,,d         abcd
<a,b,c,d>eee<f,g>  <a,b,c,d>eee<f,g>

こちらを参考にさせていただきました(英語)


データ作成スクリプト

create table strTable(val) as
select 'a,b,c<x,y,z>' from dual union all
select 'a,b,c' from dual union all
select ',,,,a' from dual union all
select 'a,,b,,c,,d' from dual union all
select '<a,b,c,d>eee<f,g>' from dual;


SQL

col    Val for a20
col NewVal for a20

--■■■正規表現を使う方法(10g以降)■■■
select Val,
RegExp_Replace(Val,'(<[^>]*>)|,','\1') as NewVal
  from strTable;

--■■■PL/SQLを使う方法■■■
declare
    KakkoFlag boolean := false;
    willOut varchar2(4000);
begin
    for rec in (select Val from strTable) Loop
        for i in 1..length(rec.Val) Loop
            if substr(rec.Val,i,1) = '<' then
                KakkoFlag := true;
                willOut := willOut || substr(rec.Val,i,1);
            elsif substr(rec.Val,i,1) = '>' then
                KakkoFlag := false;
                willOut := willOut || substr(rec.Val,i,1);
            elsif substr(rec.Val,i,1) = ',' and KakkoFlag then
                null;
            else
                willOut := willOut || substr(rec.Val,i,1);
            end if;
        end Loop;
        DBMS_Output.Put_Line(RPad(rec.Val,20) || '■' || willOut);
        willOut := null;
    end Loop;
end;
/


解説

正規表現の評価の仕組みを理解した上で
<と,の2通りで、場合分けをしてます。

先読みが使えない、Oracleの正規表現でもなんとかなる時もあるのです。