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

Oracle RETURNING INTO 子句深度解析:DML 執行前後值的精準捕獲與應用模式

     編輯:Oracle 教學

核心語義:誰在什麼時候返回什麼?

DML 類型RETURNING 返回內容典型場景
INSERT插入**後**的列值(含默認值、觸發器賦值、序列填充)獲取自增主鍵、審計新增記錄
UPDATE更新**後**的列值確認修改結果、捕獲觸發器衍生值
DELETE刪除**前**的列值歸檔刪除數據、異步同步舊值

語法規範與限制

-- 單行 DML
INSERT INTO t_test VALUES (1, 'zhangsan', 27) RETURNING age INTO v_age;
UPDATE t_test SET age = 28 RETURNING age INTO v_age;
DELETE FROM t_test WHERE id = 1 RETURNING age INTO v_age;

-- 多行 DML(僅 PL/SQL 支持,返回集合)
DECLARE
  TYPE age_arr IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  v_ages age_arr;
BEGIN
  UPDATE t_test SET age = age + 1 RETURNING age BULK COLLECT INTO v_ages;
  FOR i IN 1..v_ages.COUNT LOOP DBMS_OUTPUT.PUT_LINE(v_ages(i)); END LOOP;
END;

支持矩陣

語句形式支持 RETURNING備註
INSERT ... VALUES✅單行
INSERT ... SELECT❌多行不可預測
UPDATE✅單行/多行(PL/SQL BULK COLLECT)
DELETE✅單行/多行(PL/SQL BULK COLLECT)
MERGE❌12c+ 部分支持,建議拆分 INSERT/UPDATE

實戰應用模式

模式 1:主鍵回填(替代序列 CURRVAL)

DECLARE
  v_id t_test.id%TYPE;
BEGIN
  INSERT INTO t_test (name, age) VALUES ('lisi', 30) RETURNING id INTO v_id;
  -- v_id 即為新生成的主鍵,無需 SELECT seq.CURRVAL,避免會話級併發風險
  INSERT INTO t_test_log (ref_id, action) VALUES (v_id, 'INSERT');
END;

模式 2:審計觸發器替代方案(應用層捕獲舊/新值)

-- 更新前捕獲舊值
UPDATE t_test SET age = 31 WHERE id = v_id RETURNING age INTO v_old_age;
-- v_old_age 為更新前值(注意:UPDATE RETURNING 返回新值,若需舊值需先查詢或用觸發器)

修正:UPDATE RETURNING 返回**新值**;若需同時獲取舊值與新值,需在觸發器中使用 :OLD/:NEW 或應用層先查後改。

模式 3:批量處理性能優化

FORALL i IN 1..v_cnt
  UPDATE t_test SET age = v_new_ages(i) WHERE id = v_ids(i)
  RETURNING age BULK COLLECT INTO v_updated_ages;
-- 單次上下文切換完成批量更新與結果回收,性能提升數量級

與觸發器的協作邊界

  • 觸發器:數據庫內強制業務規則、跨表同步、安全審計,**不可繞過**。
  • RETURNING INTO:應用層即時獲取 DML 結果,**可選**、輕量、無額外上下文切換。
  • **最佳組合**:觸發器維護衍生列(如 updated_at、version),應用層 RETURNING 獲取觸發器生成的值。

版本演進亮點

  • 10g:基礎單行支持。
  • 11g:BULK COLLECT 支持多行 RETURNING。
  • 12c:RETURNING 可用於 MERGE 的 WHEN MATCHED THEN UPDATE 分支(受限)。
  • 21c:RETURNING * 簡寫返回所有列(實驗性)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved