Oracle數據庫中RETURNING子句

RETURNING子句允許您檢索插入、刪除或更新所修改的列(以及基于列的表達式)的值。如果不使用RETURNING,則必須在DML語句完成后運行SELECT語句,才能獲得更改列的值。因此,RETURNING有助于避免再次往返數據庫,即PL/SQL塊中的另一個上下文切換。

RETURNING子句可以返回多行數據,在這種情況下,您將使用RETURNING BULK COLLECT INTO窗體。

您還可以在RETURNING子句中調用聚合函數,以獲取DML語句更改的多行中的列的總和、計數等。

最后,還可以將RETURNING與EXECUTE IMMEDIATE一起使用(用于動態構建和執行的SQL語句)。

1、基本用法

1.1、單行操作:

當對單行數據進行DML操作時,可以使用RETURNING子句將受影響行的列值返回給變量。

DECLARE  v_empno employees.EMPLOYEE_ID%TYPE;  v_ename employees.FIRST_NAME%TYPE;  
BEGIN  UPDATE employees SET FIRST_NAME = 'superdb' WHERE EMPLOYEE_ID = 206 RETURNING EMPLOYEE_ID, FIRST_NAME INTO v_empno, v_ename;  DBMS_OUTPUT.PUT_LINE('Updated EMPLOYEE_ID: ' || v_empno || ', FIRST_NAME: ' || v_ename);  
END;
/Updated EMPLOYEE_ID: 206, FIRST_NAME: superdbPL/SQL procedure successfully completed.

1.2、多行操作:

當對多行數據進行DML操作時,需要使用PL/SQL的集合類型(如TABLE OF類型或嵌套表)來接收返回的多行數據。

示例(使用BULK COLLECT INTO):


HR@orcl> select EMPLOYEE_ID, FIRST_NAME,SALARY FROM employees WHERE DEPARTMENT_ID = 110 ;EMPLOYEE_ID FIRST_NAME               SALARY
----------- -------------------- ----------205 Shelley                   12008206 William                    8300DECLARE  TYPE emp_tab IS TABLE OF employees.EMPLOYEE_ID%TYPE INDEX BY PLS_INTEGER;  v_empnos emp_tab;  TYPE name_tab IS TABLE OF employees.FIRST_NAME%TYPE INDEX BY PLS_INTEGER;  v_enames name_tab;  
BEGIN  -- 正確的多列多行處理示例:  UPDATE employees SET FIRST_NAME = 'John Doe' WHERE DEPARTMENT_ID = 110   RETURNING EMPLOYEE_ID, FIRST_NAME BULK COLLECT INTO v_empnos, v_enames; -- 遍歷并輸出  FOR i IN 1 .. v_empnos.COUNT LOOP  DBMS_OUTPUT.PUT_LINE('Empno: ' || v_empnos(i) || ', Ename: ' || v_enames(i));  END LOOP;  
END;
/
Empno: 205, Ename: John Doe
Empno: 206, Ename: John DoePL/SQL procedure successfully completed.

2、使用RECORD類型

對于需要同時處理多列數據的情況,可以使用PL/SQL的RECORD類型來定義一個能夠包含多列數據的復合類型,然后結合BULK COLLECT INTO來使用。

DECLARE  TYPE emp_rec IS RECORD (  empno employees.EMPLOYEE_ID%TYPE,  ename employees.FIRST_NAME%TYPE  );  TYPE emp_tab IS TABLE OF emp_rec INDEX BY PLS_INTEGER;  v_emps emp_tab;  
BEGIN  -- 多列多行處理示例UPDATE employees SET FIRST_NAME = 'superdb' WHERE DEPARTMENT_ID = 110  RETURNING EMPLOYEE_ID, FIRST_NAME BULK COLLECT INTO v_emps;  -- 遍歷并輸出    FOR i IN 1 .. v_emps.COUNT LOOP  DBMS_OUTPUT.PUT_LINE('Empno: ' || v_emps(i).empno || ', Ename: ' || v_emps(i).ename);  END LOOP;  
END;
/
Empno: 205, Ename: superdb
Empno: 206, Ename: superdbPL/SQL procedure successfully completed.

3、RETURNING子句中調用聚合函數

You can also call aggregate functions in the RETURNING clause to obtain sums, counts and so on of columns in multiple rows changed by the DML statement.
還可以在RETURNING子句中調用聚合函數,以獲取DML語句更改的多行中的列的總和、計數等。


HR@orcl> select EMPLOYEE_ID, FIRST_NAME,SALARY FROM employees WHERE DEPARTMENT_ID = 110 ;EMPLOYEE_ID FIRST_NAME               SALARY
----------- -------------------- ----------205 Shelley                   12008206 William                    8300-- 您可以使用組函數執行另一個SQL語句來檢索這些信息。DECLARE l_total INTEGER; 
BEGIN UPDATE employees SET salary = salary * 2 WHERE DEPARTMENT_ID = 110;-- 要做SUM運算,需要寫很多代碼。SELECT SUM (salary) INTO l_total FROM employees WHERE DEPARTMENT_ID = 110;DBMS_OUTPUT.put_line (l_total); 
END;-- 可以在PL/SQL中執行計算。使用RETURNING可以收回所有修改后的工資。然后對它們進行迭代,一條語句完成總和。DECLARE l_salaries   DBMS_SQL.number_table; l_total      INTEGER := 0; 
BEGIN UPDATE employees SET salary = salary * 2 WHERE DEPARTMENT_ID = 110RETURNING salary BULK COLLECT INTO l_salaries; FOR indx IN 1 .. l_salaries.COUNT LOOP l_total := l_total + l_salaries (indx); END LOOP; DBMS_OUTPUT.put_line (l_total); 
END;
/

在這里插入圖片描述

您可以在RETURNING子句中直接調用SUM、COUNT等,從而在將數據返回到PL/SQL塊之前執行分析。非常酷

Yes! You can call SUM, COUNT, etc. directly in the RETURNING clause and thereby perform analytics before you return the data back to your PL/SQL block. Very cool.

HR@orcl> select EMPLOYEE_ID, FIRST_NAME,SALARY FROM employees WHERE DEPARTMENT_ID = 110 ;EMPLOYEE_ID FIRST_NAME               SALARY
----------- -------------------- ----------205 Shelley                   12008206 William                    8300DECLARE l_total INTEGER; 
BEGIN UPDATE employees SET salary = salary * 2 WHERE DEPARTMENT_ID = 110RETURNING SUM (salary) INTO l_total; DBMS_OUTPUT.put_line (l_total); 
END;
/

在這里插入圖片描述

4、RETURNING與EXECUTE IMMEDIATE一起使用

you can also use RETURNING with EXECUTE IMMEDIATE (for dynamically constructed and executed SQL statements).
還可以將RETURNING與EXECUTE IMMEDIATE一起使用(用于動態構建和執行的SQL語句)

4.1、在執行動態SQL語句時,利用RETURNING子句返回單行

DECLARE  l_EMPLOYEE_ID   employees.EMPLOYEE_ID%TYPE;  
BEGIN  EXECUTE IMMEDIATE q'[UPDATE employees  SET FIRST_NAME = FIRST_NAME || '-1' WHERE EMPLOYEE_ID=206RETURNING EMPLOYEE_ID INTO :one_para_id]'       RETURNING INTO l_EMPLOYEE_ID;  DBMS_OUTPUT.put_line (l_EMPLOYEE_ID);   
END;
/

在這里插入圖片描述

4.2、在執行動態SQL語句時,利用RETURNING子句返回多行

DECLARE  l_EMPLOYEE_ID   DBMS_SQL.number_table;  
BEGIN  EXECUTE IMMEDIATE q'[UPDATE employees  SET FIRST_NAME = FIRST_NAME || 'list' WHERE DEPARTMENT_ID = 110RETURNING EMPLOYEE_ID INTO :para_list]'       RETURNING BULK COLLECT INTO l_EMPLOYEE_ID;  FOR indx IN 1 .. l_EMPLOYEE_ID.COUNT  LOOP  DBMS_OUTPUT.put_line (l_EMPLOYEE_ID (indx));  END LOOP;  
END;
/

在這里插入圖片描述

5、限制和注意事項

  • RETURNING子句不能與并行DML操作或遠程對象一起使用。

  • 在通過視圖向基表中插入數據時,RETURNING子句只能與單基表視圖一起使用。

  • 對于UPDATE和DELETE語句,RETURNING子句可以返回舊值(在Oracle 23ai/c及更高版本中增強)和新值,但對于INSERT語句,它只返回新值(因為插入前沒有舊值)。

  • 在使用RETURNING子句時,必須確保返回的列與INTO子句中指定的變量類型兼容。

  • 在動態SQL中使用RETURNING子句時,需要注意綁定變量的使用,并且RETURNING BULK COLLECT INTO通常需要在

6、Oracle 23ai/c及更高版本中

在Oracle 23c及更高版本中,你可以使用FLASHBACK QUERY或AS OF VERSIONS BETWEEN子句(在適當的情況下)與RETURNING子句結合來訪問舊值,但這通常不是直接返回舊值和新值的方式。實際上,更常見的是利用Oracle的閃回技術(如Flashback Data Archive)或觸發器(Triggers)來捕獲舊值。

但是,對于UPDATE和DELETE操作,如果你想要在同一個操作中同時獲取舊值和新值,你可能需要采取以下策略之一:

  1. 使用觸發器:在UPDATE或DELETE操作之前,使用觸發器來捕獲舊值,并將它們存儲在另一個表或PL/SQL變量中。然后,你可以通過RETURNING子句獲取新值。
  2. 使用PL/SQL變量:如果你正在執行單行操作,你可以在PL/SQL中先查詢要更新的行以獲取舊值,然后執行UPDATE或DELETE操作,并使用RETURNING子句獲取新值。
  3. 利用Oracle的內置功能(如果可用):在某些Oracle版本中,可能有特定的內置函數或特性允許你同時訪問舊值和新值,但這通常不是通過RETURNING子句直接實現的。
  4. 使用版本化表(如Oracle Total Recall或Flashback Data Archive):這些特性允許你查詢表的歷史版本,從而可以間接地獲取舊值。
  5. 在SQL*Plus或SQLcl中使用SET SERVEROUTPUT ON和DBMS_OUTPUT.PUT_LINE:雖然這不會直接返回舊值和新值到客戶端,但你可以在PL/SQL塊中使用這些工具來打印出你在執行DML操作時捕獲的舊值和新值。

請記住,RETURNING子句本身在Oracle 23c及更高版本中并沒有直接提供返回舊值和新值的功能。相反,它主要用于在DML操作后返回新值給PL/SQL程序或觸發器中的變量。如果你需要舊值,你可能需要結合使用其他Oracle特性或策略。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/39089.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/39089.shtml
英文地址,請注明出處:http://en.pswp.cn/web/39089.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Plotly:原理、使用與數據可視化的未來

文章目錄 引言Plotly的原理Plotly的基本使用安裝Plotly創建基本圖表定制圖表樣式 Plotly的高級特性交互式圖表圖表動畫圖表集成 結論 引言 在當今的數據驅動世界中,數據可視化已經成為了一個至關重要的工具。它允許我們直觀地理解數據,發現數據中的模式…

CXL-GPU: 全球首款實現百ns以內的低延遲CXL解決方案

數據中心在追求更高性能和更低總擁有成本(TCO)的過程中面臨三大主要內存挑戰。首先,當前服務器內存層次結構存在局限性。直接連接的DRAM與固態硬盤(SSD)存儲之間存在三個數量級的延遲差異。當處理器直接連接的內存容量…

VideoPrism——探索視頻分析領域模型的算法與應用

概述 論文地址:https://arxiv.org/pdf/2402.13217.pdf 視頻是我們觀察世界的生動窗口,記錄了從日常瞬間到科學探索的各種體驗。在這個數字時代,視頻基礎模型(ViFM)有可能分析如此海量的信息并提取新的見解。迄今為止,…

【vuejs】vue-router 路由跳轉參數傳遞詳解和應用場景及技巧

1. Vue2 Router 路由基礎 1.1 路由定義 路由定義是Vue Router中實現頁面路由跳轉的基礎。在Vue2中,路由的定義通常在應用的入口文件或路由配置文件中進行。路由定義涉及到路徑模式(path)、視圖組件(component)以及一…

【數據分析思維--史上最全最牛逼】

前言: 💞💞大家好,我是書生?,主要和大家分享一下數據分析的思維!怎么提好我們對于業務的判斷是非常重要的!!!希望對大家有所幫助。 💞💞代碼是你…

采煤機作業3D虛擬仿真教學線上展示增強應急培訓效果

在化工行業的生產現場,安全永遠是首要之務。為了加強從業人員的應急響應能力和危機管理能力,紛紛引入化工行業工藝VR模擬培訓,讓應急演練更加生動、高效。 化工行業工藝VR模擬培訓軟件基于真實的廠區環境,精確還原了各類事件場景和…

醫療器械FDA | 醫療器械軟件如何做源代碼審計?

醫療器械網絡安全測試https://link.zhihu.com/?targethttps%3A//www.wanyun.cn/Support%3Fshare%3D24315_ea8a0e47-b38d-4cd6-8ed1-9e7711a8ad5e 醫療器械源代碼審計是一個確保醫療器械軟件安全性和可靠性的重要過程。以下是醫療器械源代碼審計的主要步驟和要點,以…

Vue3 sortablejs 表格拖拽后,表格無法更新的問題處理

實用sortablejs在vue項目中實現表格行拖拽排序 你可能會發現,表格排序是可以實現,但是我們基于數據驅動的vue中關聯的數據并沒有發生變化, 如果你的表格帶有列固定(固定列實際上在dom中有兩個表格,其中固定的列在一個表格中&…

【Python】優雅的快速選擇 - 快速排序 - 隨機快速排序

快速選擇(遞歸實現版) 這里給出以 “leetcode215. 數組中的第K個最大元素”為例的代碼。 class Solution:def findKthLargest(self, nums, k):self.nums numsn len(nums)return self.quickSelect(0,n-1,n-k)def quickSelect(self,l,r,k): # 手擼快速…

Vue3實戰筆記(64)—Vue 3自定義指令的藝術:實戰中的最佳實踐

文章目錄 前言一、一些簡單的Vue3自定義指令超實用案例總結 前言 書接上文,在Vue3中,自定義指令是一種強大的工具,允許我們擴展HTML元素的功能。通過自定義指令,我們可以創建可重用的行為,并將它們綁定到任何元素上。…

訂單折扣金額分攤算法|代金券分攤|收銀系統|積分分攤|分攤|精度問題|按比例分配|錢分攤|錢分配

一個金額分攤的算法,將折扣分攤按比例(細單實收在總體的占比)到各個細單中。 此算法需要達到以下要求: 折扣金額接近細單總額,甚至折扣金額等于細單金額,某些時候甚至超過細單總額,要保證實收不…

游泳哪個牌子好?6大游泳耳機選購技巧總結分享

游泳耳機作為水上運動愛好者和游泳專業人士的必備裝備,不僅要能夠抵御水的侵入,還要提供清晰的音質和舒適的佩戴體驗。在市面上,不同品牌的游泳耳機琳瑯滿目,選擇起來可能會令人頭疼。本文旨在為您提供一份詳盡的游泳耳機選購指南…

每日一練 - Routing Policy節點邏輯

01 真題題目 一個 routing-policy 下可以有多個節點,不同節點號用 node 標識,每個節點下可以有多個if-match 和 apply 子句,下面哪些描述是錯誤的? A. 不同節點之間是“或"的關系 B. 當路由與該節點的任意一個 if-match 條件匹配失敗后,系統自動轉入下一節點…

Gemma輕量級開放模型在個人PC上釋放強大性能,讓每個桌面秒變AI工作站

Google DeepMind團隊最近推出了Gemma,這是一個基于其先前Gemini模型研究和技術的開放模型家族。這些模型專為語言理解、推理和安全性而設計,具有輕量級和高性能的特點。 Gemma 7B模型在不同能力領域的語言理解和生成性能,與同樣規模的開放模型…

名企專訪|對抗價格內卷,格行隨身WiFi如何持續三年爆火引領潮流

近期要是問網紅達人最喜歡帶貨的單品是什么?那一定有格行隨身WiFi的一席之地。能聚集了如此多的明星達人,僅僅是一句帶貨收益高顯然無法說服大家。顯然這里面還有著不為人知的秘密,先鋒財經特意專訪了格行隨身WiFi的創始人劉永先先生&#xf…

8.x86游戲實戰-OD詳解

免責聲明:內容僅供學習參考,請合法利用知識,禁止進行違法犯罪活動! 本次游戲沒法給 內容參考于:微塵網絡安全 上一個內容:7.x86游戲實戰-C實現跨進程讀寫-跨進程寫內存 工具下載:下載 OllyI…

嵌入式Linux之Uboot簡介和移植

uboot簡介 uboot 的全稱是 Universal Boot Loader,uboot 是一個遵循 GPL 協議的開源軟件,uboot是一個裸機代碼,可以看作是一個裸機綜合例程。現在的 uboot 已經支持液晶屏、網絡、USB 等高級功能。 也就是說,可以在沒有系統的情況…

[我靠升級逆襲成為大師]韓漫日漫無刪減完整版,免費在線觀看漫畫

[我靠升級逆襲成為大師]韓漫日漫無刪減完整版,免費在線觀看漫畫 不能多說,怕審-核不過,自己看圖吧。 目前統計【統計日期:2024-07-03】: 完結的有:420部。 連載的有:308部,持續更…

生單鏈路流程復雜,涉及到上下游商品、庫存、營銷、風控、拆單、校驗、落庫等等十多個節點操作,需要保證數據的完整性和正確性

處理復雜的生單鏈路流程,確保數據的完整性和正確性,需要一個綜合的策略,包括但不限于以下幾個方面: 1. **流程設計**: - 明確每個節點的職責和輸入輸出,確保流程的邏輯清晰。 2. **數據校驗**&#xf…

python庫(1):Nuitka庫

1 Nuitka介紹 Nuitka是一個 Python 解釋器的替代品,支持CPython提供的代碼,可編譯 Python 代碼到 C 程序,并使用 libpython 來執行這些代碼,就像 CPython 一樣。 這讓你可以在沒有安裝 Python 的環境中運行 Python 程序&#xf…