遷移 Oracle Forms 6i→9i 時,內建 `alert_message` 參數傳遞失效,數千警告訊息需逐一修改。同理,PL/SQL 開發中反覆寫 `DBMS_OUTPUT.PUT_LINE` 既囉嗦又難維護。封裝成可重用套件,單點維護、全域受益。
CREATE OR REPLACE PROCEDURE am (p_cnt NUMBER) AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Records updated: ' || p_cnt);
END;
/
呼叫:`am(46);`
CREATE OR REPLACE PROCEDURE ams (p_msg VARCHAR2) AS
BEGIN
DBMS_OUTPUT.PUT_LINE(p_msg);
END;
-- 除錯用法
ams('ENTER: calc_bonus');
ams(' v_emp_id=' || v_emp_id);
ams('EXIT: calc_bonus');
CREATE OR REPLACE PROCEDURE dup_cnt (p_cnt NUMBER) AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Duplicates counted: ' || p_cnt);
END;
CREATE OR REPLACE PROCEDURE ins_msg (p_cnt NUMBER) AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Rows inserted: ' || p_cnt);
END;
-- 同理 upd_msg, del_msg...
問題:程序數量膨脹、管理混亂。
CREATE OR REPLACE PROCEDURE am (p_prefix VARCHAR2, p_suffix VARCHAR2 DEFAULT NULL) AS
BEGIN
DBMS_OUTPUT.PUT_LINE(p_prefix || p_suffix);
END;
-- 呼叫
am('Duplicates counted: ', 46);
am('Current step: ', 'VALIDATE');
利用 `SET SERVEROUTPUT ON FORMAT WORD_WRAPPED` 讓 SQL*Plus 自動處理,避免自寫遞歸切割。
CREATE OR REPLACE PACKAGE prt AS
PROCEDURE ln (p_msg VARCHAR2);
PROCEDURE ln (p_msg NUMBER);
PROCEDURE ln (p_msg DATE);
PROCEDURE ln (p_msg BOOLEAN);
PROCEDURE dup (p_cnt NUMBER);
PROCEDURE ins (p_cnt NUMBER);
PROCEDURE upd (p_cnt NUMBER);
PROCEDURE del (p_cnt NUMBER);
END prt;
/
CREATE OR REPLACE PACKAGE BODY prt AS
PROCEDURE ln (p_msg VARCHAR2) IS BEGIN DBMS_OUTPUT.PUT_LINE(p_msg); END;
PROCEDURE ln (p_msg NUMBER) IS BEGIN DBMS_OUTPUT.PUT_LINE(TO_CHAR(p_msg)); END;
PROCEDURE ln (p_msg DATE) IS BEGIN DBMS_OUTPUT.PUT_LINE(TO_CHAR(p_msg,'YYYY-MM-DD HH24:MI:SS')); END;
PROCEDURE ln (p_msg BOOLEAN) IS BEGIN DBMS_OUTPUT.PUT_LINE(CASE p_msg WHEN TRUE THEN 'TRUE' WHEN FALSE THEN 'FALSE' ELSE 'NULL' END); END;
PROCEDURE dup (p_cnt NUMBER) IS BEGIN DBMS_OUTPUT.PUT_LINE('Duplicates counted: ' || p_cnt); END;
PROCEDURE ins (p_cnt NUMBER) IS BEGIN DBMS_OUTPUT.PUT_LINE('Rows inserted: ' || p_cnt); END;
PROCEDURE upd (p_cnt NUMBER) IS BEGIN DBMS_OUTPUT.PUT_LINE('Rows updated: ' || p_cnt); END;
PROCEDURE del (p_cnt NUMBER) IS BEGIN DBMS_OUTPUT.PUT_LINE('Rows deleted: ' || p_cnt); END;
END prt;
/
-- 使用
BEGIN
prt.ln('Start batch');
prt.ins(123);
prt.ln(SYSDATE);
END;
/
「將易變的外部依賴封裝在自有抽象層,是應對技術演進的最佳防禦。」