简体   繁体   English

ORACLE 更新并返回 OLD 和 NEW 值

[英]ORACLE update with returning OLD and NEW values

Is there equivalent to this T-SQL query in PL/SQL (Oracle 12c)? PL/SQL (Oracle 12c) 中是否有与此 T-SQL 查询等效的功能?

UPDATE A SET A.columnA = 10 WHERE A.columnB < 30 OUTPUT INSERTED.*, DELETED.*

The query updates table A and at the same time returns the status of the record before the update and after the update.查询更新表 A,同时返回更新前和更新后记录的状态。

Trigger is not a solution for me as well as SELECT records before and SELECT records after updating.触发器不是我的解决方案,更新之前的 SELECT 记录和更新之后的 SELECT 记录。

Not a direct one, but using RETURNING INTO you will be able to achieve the same effect:不是直接的,但使用RETURNING INTO你将能够达到同样的效果:

CREATE TABLE A(columnA VARCHAR2(10), columnB INT);
INSERT INTO A(columnA, columnB) VALUES ('Test', 10);
INSERT INTO A(columnA, columnB) VALUES ('Row 2', 20);
CREATE TABLE audit_table(col_new VARCHAR2(10),col_old VARCHAR2(10));

DECLARE
   TYPE rec IS RECORD (actual A.columnA%TYPE, old A.columnA%TYPE);
   TYPE col_a_t IS TABLE OF rec;
   v_a col_a_t;
BEGIN
  UPDATE (SELECT A.*, (SELECT A.columnA FROM dual) AS old_columnA FROM A)
  SET columnA = 'XYZ'
  WHERE columnB < 30
  RETURNING columnA, old_columnA BULK COLLECT INTO v_a;
  COMMIT;

  -- printing for debug
  FOR i IN v_a.first .. v_a.last LOOP
     dbms_output.put_line('Old =>' || v_a(i).old || ' new => ' || v_a(i).actual);
  END LOOP;

  -- additional
  FORALL i IN v_a.first .. v_a.last
    INSERT INTO audit_table VALUES v_a(i);
  COMMIT;
END;
/

SELECT * FROM A;
SELECT * FROM audit_table;

DBFiddle Demo DBFiddle 演示


Idea taken from: Returning Old value during update想法取自:在更新期间返回旧值

How would be above code look like in case when using execute immediate?如果使用立即执行,上面的代码会是什么样子? Something like this?像这样的东西? I have skipped the insert part for simplicity.为简单起见,我跳过了插入部分。

DECLARE
    sql_update  VARCHAR2(4000) := NULL;
    TYPE rec IS RECORD (
        actual  a.columna%TYPE,
        old     a.columna%TYPE
    );
    TYPE col_a_t IS
        TABLE OF rec;
    v_a         col_a_t;
BEGIN
    sql_update := 'UPDATE (SELECT A.*, (SELECT A.columnA FROM dual) AS old_columnA FROM A)'
                  || 'SET columnA = ''XYZ'''
                  || 'WHERE columnB < 30'
                  || 'RETURNING columnA, old_columnA BULK COLLECT INTO v_a';
 -- COMMIT;
    EXECUTE IMMEDIATE sql_update;
  -- printing for debug
    FOR i IN v_a.first..v_a.last LOOP
        dbms_output.put_line('Old =>'
                             || v_a(i).old
                             || ' new => '
                             || v_a(i).actual);
    END LOOP;
END;
/

When I execute above code I get当我执行上面的代码时,我得到

ORA-00925: missing INTO keyword

you mean like this?你的意思是这样吗? but I get still the same error:但我仍然得到同样的错误:

DECLARE
    sql_update  VARCHAR2(4000) := NULL;
    TYPE rec IS RECORD (
        actual  a.columna%TYPE,
        old     a.columna%TYPE
    );
    TYPE col_a_t IS
        TABLE OF rec;
    v_a         col_a_t;
BEGIN
    sql_update := ' UPDATE (SELECT A.*, (SELECT A.columnA FROM dual) AS old_columnA FROM A) '
                  || ' SET columnA = ''XYZ'' '
                  || ' WHERE columnB < 30 '
                  || ' RETURNING columnA, old_columnA BULK COLLECT INTO v_a ';
 -- COMMIT;
    EXECUTE IMMEDIATE sql_update;
  -- printing for debug
    FOR i IN v_a.first..v_a.last LOOP
        dbms_output.put_line('Old =>'
                             || v_a(i).old
                             || ' new => '
                             || v_a(i).actual);
    END LOOP;
END;
/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM