CREATE OR REPLACE PROCEDURE procedure_name (
param1 IN NUMBER,
param2 IN NUMBER
) IS
var1 INTEGER := 0;
var2 DATE;
BEGIN
-- 程式邏輯
NULL;
END procedure_name;
/
將查詢結果存入變數,**必須回傳恰好一筆**,否則拋出 NO_DATA_FOUND 或 TOO_MANY_ROWS。
BEGIN
SELECT col1, col2 INTO var1, var2 FROM typestruct WHERE ...;
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- 處理無資料
NULL;
END;
IF v_test = 1 THEN
BEGIN
-- do something
END;
END IF;
WHILE v_test = 1 LOOP
BEGIN
-- 迴圈主體
END;
END LOOP;
v_test := 123;
IS
CURSOR cur IS SELECT * FROM xxx;
BEGIN
FOR cur_rec IN cur LOOP
v_sum := cur_rec.col1 + cur_rec.col2;
END LOOP;
END;
CURSOR c_user(c_id NUMBER) IS SELECT name FROM user WHERE typeid = c_id;
OPEN c_user(v_id);
LOOP
FETCH c_user INTO v_name;
EXIT WHEN c_user%NOTFOUND;
-- 處理
END LOOP;
CLOSE c_user;
BEGIN proc_name(1); END;)。-- 正確
SELECT a.appname FROM appinfo a;
-- 錯誤
SELECT a.appname FROM appinfo AS a;
Oracle 不支援 AS 關鍵字定義表別名,直接空白隔開即可。
-- 正確
SELECT af.keynode INTO kn FROM appfoundation af WHERE ...;
-- 錯誤:缺少 INTO
SELECT af.keynode FROM appfoundation af WHERE ...;
-- 編譯錯誤:PLS-00428: an INTO clause is expected in this SELECT statement
避免 NO_DATA_FOUND 例外,可先 SELECT COUNT(*) 檢查。
-- 正確
SELECT keynode INTO kn FROM appfoundation WHERE appid = aid AND foundationid = fid;
-- 危險:別名 af 與欄位名衝突,編譯通過但執行期拋 ORA-01422: exact fetch returns more than requested number of rows
SELECT af.keynode INTO kn FROM appfoundation af WHERE af.appid = appid AND af.foundationid = foundationid;
當 WHERE 條件中的 appid、foundationid 解析為表欄位而非參數,導致條件永真,回傳多筆。
SELECT SUM(vcount) INTO fcount FROM a WHERE bid = 'xxxxxx';
IF fcount IS NULL THEN
fcount := 0; -- 即使宣告 fcount NUMBER(8) := 0,查無資料時仍會變 NULL
END IF;
結論:聚合函數查無資料回傳 NULL,需顯式判斷轉 0。
getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
CallableStatement cs = session.connection().prepareCall("{call modifyapppnumber_remain(?)}");
cs.setString(1, foundationid);
cs.execute();
return null;
}
});
| 特性 | PROCEDURE | FUNCTION |
|---|---|---|
| 回傳值 | 可無,或透過 OUT/IN OUT 參數 | 必須回傳單一值(RETURN) |
| SQL 中呼叫 | 不可直接在 SELECT 中呼叫 | 可在 SELECT/WHERE 中呼叫 |
| DML 內使用 | 可執行 DML | 若在 SQL 中呼叫,限制較多(需 DETERMINISTIC/PARALLEL_ENABLE) |