首页 > 数据库 >Oracle数据库中RETURNING子句

Oracle数据库中RETURNING子句

时间:2024-07-05 10:57:14浏览次数:30  
标签:RETURNING 子句 EMPLOYEE SQL Oracle ID FIRST

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: superdb

PL/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                   12008
        206 William                    8300

DECLARE  
  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 Doe

PL/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: superdb

PL/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                   12008
        206 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 = 110
   RETURNING 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                   12008
        206 William                    8300

DECLARE l_total INTEGER; 
BEGIN 
  UPDATE employees 
     SET salary = salary * 2 
   WHERE DEPARTMENT_ID = 110
  RETURNING 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=206
      RETURNING 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 = 110
      RETURNING 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特性或策略。

标签:RETURNING,子句,EMPLOYEE,SQL,Oracle,ID,FIRST
From: https://blog.csdn.net/zxrhhm/article/details/140151250

相关文章

  • Create Operations and the Oracle Restart Configuration
    CreateOperationCreatedComponentAutomaticallyAddedtoOracleRestartConfiguration?CreateadatabasewithOUIorDBCAYesCreateadatabasewiththe CREATE DATABASE SQLstatementNoCreateanOracleASMinstancewithOUI,DBCA,orASM......
  • oraclelinux9.2内网升级OpenSSH9.8p1
    oraclelinux9.2内网升级OpenSSH9.8p1#备份SSHmkdir-p/etc/sshbakcp-rf/etc/ssh/*/etc/sshbakcp-rf/usr/bin/openssl/usr/bin/openssl.bakcp-rf/etc/pam.d/etc/pam.d.bakcp-rf/usr/lib/systemd/system/system.bakdnfinstall-ygccgcc-c++#上传3个压缩包,下载地......
  • 服务器Oracle数据库损坏修复
    当Oracle数据库在服务器上损坏时,修复过程需要谨慎且系统地进行,以确保数据的完整性和系统的稳定性。一、初步诊断与评估检查错误日志:首先,检查Oracle数据库的错误日志(如alertlog和tracefiles),这些日志通常包含有关数据库损坏的详细信息,如错误代码、失败的操作等。确定损坏范围:......
  • Oracle 临时表 OracleDataAdapter 批量更新
    ///<summary>///注意,字段名必需大小写保持一致///</summary>protectedstaticstringupdateSql=@"MergeintoTable_NameTUsingTempTableSON(T.USER_ID=S.USERID)WHENMATCHEDTHENUPDATESETT.NICK_NAME=S......
  • Oracle PL / SQL变量
    变量是PL/SQL程序中特定数据类型的内存中的命名位置。我们必须在PL/SQL块的声明部分声明它们。变量命名PL/SQL变量必须遵循标识符命名规则:变量名称的长度必须小于31个字符。变量名称必须以大写或小写ASCII字母开头:AZ或az。PL/SQL不区分大小写。变量名称可以由1......
  • Oracle PL / SQL文字
    文字是一个显式的数字,字符,字符串或BOOLEAN值。例如,数字14和BOOLEAN FALSE是两个文字。数字字面量我们可以在算术表达式中使用两种类型的数字文字:整数和实数。整数字面值是一个可选的有符号整数,不带小数点。例如:36-141123+32767实数字面值是带小数点的......
  • Oracle PL / SQL数据类型
    PL/SQL是SQL的过程语言扩展,它支持与SQL对数据库相同的数据类型。PL/SQL可以处理任何数据库数据类型,并且还有自己的数据类型。VARCHAR2:我们将使用数据类型VARCHAR2处理PL/SQL中的字符串。PL/SQLVARCHAR2最多可容纳32,767个字符。NUMBER:我们将使用数据类型NUMBER处......
  • Oracle数据库统计信息收集
    Oracle数据库统计信息收集重新收集表统计信息--重新收集表统计信息BEGINDBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'ORCL',TABNAME=>'XXX',ESTIMATE_PERCENT=>100,DEGREE=>4);END;重新收集列统计信息......
  • Oracle临时表on commit preserve rows和on commit delete rows区别
    Oracle临时表:在Oracle中创建一张表,这个表不用于其他的什么功能,主要用于自己的软件系统一些特有功能才用的,而当你用完之后表中的数据就没用了。Oracle的临时表创建之后基本不占用表空间,如果你没有指定临时表(包括临时表的索引)存放的表空的时候,你插入到临时表的数据是存放......
  • ubuntu上安装oracle11g的错误解决
    环境:OS:16.04DB:11.2.0.4单机 发现在ubuntu上安装oracle,按照文档都已经安装了想要的包,但是检查还是无法通过,忽略后可以进行安装,但是需要修改很多地方1.安装的依赖包aptupdateapt-getinstallbinutilsapt-getinstalllibcap-devapt-getinstalllibstdc++5apt-get......