首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

打造可重用 PL/SQL 訊息輸出套件:從簡單 DBMS_OUTPUT 到企業級日誌庫

     編輯:Oracle 資料庫基礎

動機:重複造輪子的代價

遷移 Oracle Forms 6i→9i 時,內建 `alert_message` 參數傳遞失效,數千警告訊息需逐一修改。同理,PL/SQL 開發中反覆寫 `DBMS_OUTPUT.PUT_LINE` 既囉嗦又難維護。封裝成可重用套件,單點維護、全域受益。

演進階梯

第 1 階:最簡單包裝

CREATE OR REPLACE PROCEDURE am (p_cnt NUMBER) AS
BEGIN
  DBMS_OUTPUT.PUT_LINE('Records updated: ' || p_cnt);
END;
/

呼叫:`am(46);`

第 2 階:支援字串與除錯定位

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');

第 3 階:語意化訊息庫(業務導向)

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...

問題:程序數量膨脹、管理混亂。

第 4 階:多參數彈性化

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');

第 5 階:健壯化——長訊息自動換行

利用 `SET SERVEROUTPUT ON FORMAT WORD_WRAPPED` 讓 SQL*Plus 自動處理,避免自寫遞歸切割。

第 6 階:封裝成 Package(終極形態)

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;
/

未來擴充方向

  • 寫入資料表 `APP_LOG`(非同步批次寫入),支援生產環境永久保存。
  • 整合 `UTL_FILE` 輸出至檔案,支援排程作業無人值守。
  • 加入日誌等級(DEBUG/INFO/WARN/ERROR)、模組標籤、堆疊追蹤。
  • 若 Oracle 變更 `DBMS_OUTPUT` 介面,僅需修改 Package Body,業務代碼零影響。

核心啟示

「將易變的外部依賴封裝在自有抽象層,是應對技術演進的最佳防禦。」
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved