暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 触发捕获特定列的插入值之前和之后

askTom 2017-04-24
251

问题描述

嗨,团队,

我必须创建一个触发器,该触发器将在插入的情况下记录旧值和新值。情况是,我有一个应用程序和前端部分,每当发生一些变化,然后xyz_id被改变。在后端,我可以看到插入正在发生。我想在一个历史表中记录旧的xyz_id和新的xyz_id。因此,每当我检查该历史记录表时,我就知道这是旧的xyz_id,并且已更改为新的xyz_id。

请看我正在使用的代码:

CREATE TABLE xyzID_log(
    xyz_id_old number(11,0),
    xyz_id_new number(11,0)
   
);



CREATE OR REPLACE PACKAGE audit_PKG AS
    PROCEDURE CHECK_VAL( TAB_NAME IN VARCHAR2,COL_NAME IN VARCHAR2, NEW_VAL IN VARCHAR2,
 OLD_VAL IN VARCHAR2 ) ;
END;
/


CREATE OR REPLACE PACKAGE BODY audit_PKG AS
PROCEDURE  CHECK_VAL( TAB_NAME IN VARCHAR2, COL_NAME IN VARCHAR2, NEW_VAL IN VARCHAR2, OLD_VAL IN VARCHAR2 )
IS
BEGIN
    IF ( NEW_VAL <> OLD_VAL OR
         (NEW_VAL IS NULL AND OLD_VAL IS NOT NULL) OR
         (NEW_VAL IS NOT NULL AND OLD_VAL IS NULL) )
    THEN
        INSERT INTO xyzID_log (xyz_id_old,xyz_id_new)
        VALUES  (OLD_VAL,NEW_VAL);
    END IF;
   
END;

END audit_PKG;
/

CREATE OR REPLACE TRIGGER xyzAUDTRG_after 
 AFTER INSERT OR DELETE OR UPDATE ON Department FOR EACH ROW
DECLARE 
V_TABLE_NAME VARCHAR2(50);
V_COL_NM VARCHAR2(50);
BEGIN 
V_TABLE_NAME:='Department';
V_COL_NM:=xyz_ID;
    audit_pkg.check_val('Department', 'xyz_ID', :new.xyz_ID, :old.xyz_ID);
END;
/
复制



当我运行这个代码和在前端应用程序插入发生,然后xyzID_log这个表的输出如下:

Xyz _ id _ 旧xyz _ id _ 新
NULL 7

我希望列xyz_id_old也应该有一个值而不是NULL。

我知道,在插入的情况下,我们只能获得新值,旧值将为NULL。但这是我的任务。
我向你解释一种情况:
让我们假设xyz_ID = 5的值
在应用程序中,每当我做一些事情,比如改变一个程序的时间,它的xyz_ID被从5更改为7。因此,在这种情况下,旧的xyz_ID = 5,新的xyz_ID = 7。检查跟踪文件后,我可以看到这种类型的更改发生了插入。

所以在上面的xyzID_log表,对于列xyz_id_old我想它的值应该显示5不为空。

我不能使用滞后函数,因为
就我而言,情况并非如此。例如:
当有人执行应用程序时,xyz_id上会发生一些插入,下面是值

Before_Insert_xyz_id   After_insert_xyz_id     Date 
20                     30                    18 Apr 
50                     10                     19 Apr 
40                     15                     21 Apr 
复制


所以在我的情况下,每当Insert发生时,after_insert值就不会成为before_insert值。这是因为在我们的应用程序中,我们为不同的时间安排了不同的程序。所有程序都有xyz_id。有时插入发生在程序A上,有时发生在程序B上等,因此插入值不同。例如,插入发生在程序A上,然后xyz_id的旧值为20,插入后为30。
一段时间或几天后,程序C上发生了插入,然后xyz_id的旧值为50,插入后为10。

此外,我必须在触发器中实现此功能。我被困住了,无法弄清楚如何实现这一目标。
请引导我。
提前感谢 :)

专家解答

让我强调一下...对于 * 每个 * 插入,: old值为null,因为 * 没有 * old行。

您在触发器中拥有的唯一信息是:

插入-仅新增
更新-旧的和新的
仅删除旧

这是可能的,你的前端应用程序 * 重新解释 * 什么用户 * 感知 * 正在发生,例如,屏幕可能表明一个值正在 “更新”,但代码可能正在做删除-然后-插入来实现它。或者它可能会标记现有记录是 “不再被看到” (通过应用程序),然后插入一个新的 “活动” 记录等。

但是在数据库级别,* 永远不会 * 插入一个旧值-因为它是正在创建的 * 新 * 记录。

您需要将应用程序正在做的事情映射到数据库正在做的事情,以便正确地呈现审计跟踪。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论