3-2. 実装方針の検討~データの加工・編集~

データ加工

前のページでは単なるデータ移送という最もシンプルなロジックをサンプルにしましたが、実際に業務でプログラムを記述する際はそんなことは滅多になく、何らかの編集処理を行うことになります。
その場合、どのように記述すべきでしょうか。

それでは明示カーソルでFOR-LOOPによるサンプルを基に、empnoが9000以上(役員)の場合のみ、commに1000を設定する場合を考えましょう。

------------------------------------------------------------
DECLARE
  CURSOR c1 IS
  SELECT empno, ename, hiredate, deptno
  FROM   emp
  WHERE  empno > 5000;
  r1 c1%ROWTYPE;
BEGIN
  FOR r1 IN c1
  LOOP
    -- emono9000以上はcommに1000を設定
    IF empno>=9000 THEN
      INSERT INTO emptmp(empno, ename, hiredate, deptno, comm)
      VALUES(r1.empno, r1.ename, r1.hiredate, r1.deptno, 1000);
    ELSE
    -- それ以外は今まで通り
      INSERT INTO emptmp(empno, ename, hiredate, deptno)
      VALUES(r1.empno, r1.ename, r1.hiredate, r1.deptno);
    END IF;
  END LOOP;
EXCEPTION
  WHEN OTHERS THEN
    RAISE;
END;
------------------------------------------------------------

ちょっとこれは冗長すぎますね。
仕様が変わったらINSERT文を2ヵ所修正しなければなりません。
保守性を高めるためには、このようなコードの記述は避けるべきです。

もう少し整理してみましょう。

------------------------------------------------------------
DECLARE
CURSOR c1 IS
SELECT empno, ename, hiredate, deptno
FROM emp
WHERE empno > 5000;
r1 c1%ROWTYPE;
ln_comm NUMBER;
BEGIN
FOR r1 IN c1
LOOP
-- emono9000以上はcommに1000を設定
IF empno>=9000 THEN
ln_comm := 1000;
ELSE
ln_comm := NULL;
END IF;
INSERT INTO emptmp(empno, ename, hiredate, deptno, comm)
VALUES(r1.empno, r1.ename, r1.hiredate, r1.deptno, ln_comm);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
------------------------------------------------------------

PL/SQLの言語でロジックを記述するのではこれでも間違っていませんが、よりSQLとPL/SQLを統合させると違った記述ができます。
また、一時的に値を変数に代入するというのも、美しくありません。

次のように記述することができます。

------------------------------------------------------------
DECLARE
  CURSOR c1 IS
  SELECT empno, ename, hiredate, deptno,
         CASE WHEN empno>=9000 THEN 1000 ELSE NULL END comm
  FROM   emp
  WHERE  empno > 5000;
  r1 c1%ROWTYPE;
  ln_comm NUMBER;
BEGIN
  FOR r1 IN c1
  LOOP
    INSERT INTO emptmp(empno, ename, hiredate, deptno, comm)
    VALUES(r1.empno, r1.ename, r1.hiredate, r1.deptno, ln_comm);
  END LOOP;
EXCEPTION
  WHEN OTHERS THEN
    RAISE;
END;
------------------------------------------------------------

commへの設定ロジックがカーソル定義SQLの中で完結しています。
同時に、PL/SQLのロジックには手が入っていません。
こうすることで、PL/SQLのロジックはシンプルなままにしておくことができ、ロジックが1ヵ所のSQLに集中するため、プログラムの保守性が向上します。

SQLが複雑になることを嫌い、このような編集ロジックをPL/SQLで記述する人がいますが、ロジックが分散するだけでたいていの場合は慣れの問題であることが多いです。
テストのフェイズに入り久しぶりに見るソースコードを追う、他人の作成したソースコードを追う、という場面になれば、ロジックは1ヵ所に固まってあった方が早く理解することができますし、勘違いや誤解もしづらくなります。

Posted by tfurukaw