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

10-178 LRU方式で追加更新その2

SQLパズル

LRUTable2
PID  PName
---  -----
データなし

LRU方式で管理しているLRUTable2に、
データを追加更新するストアドプロシージャLRUを作成する。
ただし、データがない場合を考慮する。
また、データの最大数は5とする。

exec LRU2('NotePad');
exec LRU2('EmEditor');
exec LRU2('Oracle');
exec LRU2('iexplore');
を実行後

      PID  PName
---------  -------
        1  NotePad
        2  EmEditor
        3  Oracle
        4  iexplore

exec LRU2('Java');
を実行後

      PID  PName
---------  -------
        1  NotePad
        2  EmEditor
        3  Oracle
        4  iexplore
        5  Java

exec LRU2('iexplore');
を実行後

      PID  PName
---------  -------
        1  NotePad
        2  EmEditor
        3  Oracle
        4  Java
        5  iexplore

exec LRU2('qprocess');
を実行後

      PID  PName
---------  -------
        1  EmEditor
        2  Oracle
        3  Java
        4  iexplore
        5  qprocess

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


データ作成スクリプト

create table LRUTable2(
PID   number(1)   primary key,
PName varchar2(8) unique);


SQL

create or replace procedure LRU2(p_val varchar2) as
    MaxProcess constant pls_Integer :=5;

    ExistMatch  pls_Integer;
    RecordCount pls_Integer;
begin
    select max(case when PName = p_val then 1 else 0 end),count(*)
      into ExistMatch,RecordCount
      from LRUTable2;

    if ExistMatch = 0 and RecordCount = MaxProcess then
        update LRUTable2
           set PID    = decode(PID-1,0,MaxProcess,PID-1),
               PName  = decode(PID,1,p_val,PName);
    elsif RecordCount=0 or ExistMatch = 0 and RecordCount < MaxProcess then
        insert into LRUTable2(PID,PName) values(RecordCount+1,p_val);
    else --ExistMatch = 1
        update LRUTable2 a
        set PID = (select b.NewPID
                     from (select bb.RowID as Row_ID,
                           Row_Number() over(order by decode(bb.PName,p_val,1,0),bb.PID) as NewPID
                           from LRUTable2 bb) b
                   where a.RowID = b.Row_ID);
    end if;
end;
/

sho err

truncate table LRUTable2;

exec LRU2('NotePad');
exec LRU2('EmEditor');
exec LRU2('Oracle');
exec LRU2('iexplore');
select PID,PName from LRUTable2 order by PID;

exec LRU2('Java');
select PID,PName from LRUTable2 order by PID;

exec LRU2('iexplore');
select PID,PName from LRUTable2 order by PID;

exec LRU2('qprocess');
select PID,PName from LRUTable2 order by PID;


解説

最初のスカラー問い合わせで、
件数と、p_valと等しいデータが存在するか
を調べてます。