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,
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ヵ所に固まってあった方が早く理解することができますし、勘違いや誤解もしづらくなります。
最近のコメント