存儲過程是 Oracle PL/SQL 核心編程單元,將業務邏輯封裝在資料庫層可提升性能、安全性與可維護性。本文通過兩個漸進式實例,詳細講解創建、調用、參數傳遞、異常處理全流程。
CREATE [OR REPLACE] PROCEDURE procedure_name
[ (parameter [, parameter]...) ]
IS | AS
-- 聲明區:變量、游標、異常、嵌套子程序
BEGIN
-- 執行區:SQL/PLSQL 語句
[EXCEPTION
-- 異常處理區
]
END [procedure_name];
CREATE OR REPLACE PROCEDURE output_date
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
END output_date;
/
SHOW ERRORS
CREATE OR REPLACE:存在則覆蓋,便於開發迭代IS ... BEGIN ... END:PL/SQL 塊標準結構DBMS_OUTPUT.PUT_LINE:標準輸出包,需客戶端啟用 `SET SERVEROUTPUT ON`TO_CHAR(SYSDATE, ...):格式化日期輸出,避免隱式轉換-- SQL*Plus 中編譯
SQL> @output_date.sql
Procedure created.
-- 啟用輸出並執行
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE output_date;
2024-01-15 14:30:25
PL/SQL procedure successfully completed.
-- 或在匿名塊中調用
SQL> BEGIN
2 output_date;
3 END;
4 /
CREATE TABLE tab_user (
id NUMBER(10) PRIMARY KEY,
username VARCHAR2(50) NOT NULL
);
INSERT INTO tab_user VALUES (1, 'zhangsan');
INSERT INTO tab_user VALUES (2, 'lisi');
COMMIT;
CREATE OR REPLACE PROCEDURE get_username (
v_id IN NUMBER,
v_username OUT VARCHAR2
)
AS
BEGIN
SELECT username
INTO v_username
FROM tab_user
WHERE id = v_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20001, 'ID 不存在: ' || v_id);
WHEN TOO_MANY_ROWS THEN
RAISE_APPLICATION_ERROR(-20002, 'ID 返回多行數據: ' || v_id);
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20000, '查詢異常: ' || SQLERRM);
END get_username;
/
SHOW ERRORS
| 模式 | 方向 | 可讀 | 可寫 | 默認值支持 | 典型用途 |
|---|---|---|---|---|---|
| IN | 調用者 → 過程 | ✅ | ❌ | ✅ | 輸入條件、過濾值 |
| OUT | 過程 → 調用者 | ❌ | ✅ | ❌ | 返回結果、狀態碼 |
| IN OUT | 雙向 | ✅ | ✅ | ❌ | 輸入並修改返回 |
-- 正常調用
SQL> VARIABLE v_name VARCHAR2(50)
SQL> EXECUTE get_username(1, :v_name);
PL/SQL procedure successfully completed.
SQL> PRINT v_name
V_NAME
--------------------------------------------------
zhangsan
-- 異常調用:ID 不存在
SQL> EXECUTE get_username(99, :v_name);
BEGIN get_username(99, :v_name); END;
*
ERROR at line 1:
ORA-20001: ID 不存在: 99
ORA-06512: at "SCOTT.GET_USERNAME", line 10
ORA-06512: at line 1
SHOW ERRORS PROCEDURE get_username;
-- 或查詢視圖
SELECT * FROM USER_ERRORS WHERE NAME = 'GET_USERNAME' ORDER BY SEQUENCE;
-- 會話級開啟 SQL 追蹤
ALTER SESSION SET SQL_TRACE = TRUE;
-- 或使用 DBMS_MONITOR
EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE(waits => TRUE, binds => TRUE);
-- 關鍵節點打印調試信息
DBMS_OUTPUT.PUT_LINE('DEBUG: v_id=' || v_id || ', v_username=' || v_username);
存儲過程是將業務邏輯下沉資料庫層的關鍵手段。從無參數的簡單過程開始,逐步掌握參數傳遞、異常處理、事務控制,再進階至包設計與動態 SQL,構建健壯、高性能、可維護的資料庫程序體系。