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