触发插入旧值

Posted

技术标签:

【中文标题】触发插入旧值【英文标题】:Trigger to insert old values 【发布时间】:2012-05-27 12:23:29 【问题描述】:

我的表上有以下触发器,我面临的问题是在my_hist 表中,当条件变为updated = 'Y' 时,新旧值都被插入。

当条件变为updated = 'Y' 时,如何有效地将旧值插入 my_hist 表中。

谢谢

CREATE OR REPLACE TRIGGER mytrig
    AFTER UPDATE
    ON mytab
    FOR EACH ROW
WHEN (
new.updated = 'Y'
      )
BEGIN
    INSERT INTO my_hist
      VALUES   (
                        :old.id,
                        :old.no,                        
                        :old.start_date,
                        :old.end_date,
                        SYSDATE
                  );
END mytrig;
/

更新 1

如果我正在更新updated = 'Y',那么如果我有记录

id = 3, start_date='01-Jan-2014' and end_date='31-Jan-2014' 和更新的数据 id = 3, start_date=='01-Jan-2014' and end_date='31-Mar-2014' 那么我的 my_hist 表中有两条记录是

id = 3 and start_date='01-Jan-2014' and end_date='31-Jan-2014'

id = 3 and start_date='01-Jan-2014' and end_date='31-Mar-2014'

理想情况下,my_hist 表中应该只有id = 3 and start_date='01-Jan-2014' and end_date='31-Jan-2014',而不是end_date='31-Mar-2014' 的第二行,因为那是新数据。

【问题讨论】:

从这么多的信息中很难说,但也许何时(new.updated = 'Y' and old.Updated = 'N') 问题是旧值和新值都被插入到 my_hist 表中。那么(new.updated = 'Y' and old.Updated = 'N') 会解决这个问题吗? new.Updated = 'Y' 用于新旧记录。同样,如果您这样做并更新已更新为 Y 且仍为 Y 的位置,它也会再次进入。你想要从 N 到 Y 的过渡。不过这是一个猜测。 我在上面的更新 1 中解释了我的想法。谢谢 我解决了这个问题,这是由于我在更新字段Updated = 'Y' 的过程中出现了错误情况。非常感谢。 【参考方案1】:

您的描述中缺少某些内容。如果您按照您所说的去做,那么您的历史记录表将只有一行,并且将包含旧数据。如果您还有一个包含新数据的历史记录行,则说明您的触发器正在执行与您发布的内容不同的操作,或者您有其他内容(即另一个触发器)正在写入历史记录表。

创建两个表

SQL> ed
Wrote file afiedt.buf

  1  create table my_tab (
  2    id number,
  3    start_date date,
  4    end_date date,
  5    no number,
  6    updated varchar2(1)
  7* )
SQL> /

Table created.

SQL> ed
Wrote file afiedt.buf

  1  create table my_hist (
  2    id number,
  3    start_date date,
  4    end_date date,
  5    no number,
  6    updated varchar2(1),
  7    update_date date
  8* )
SQL> /

填充初始数据

SQL> ed
Wrote file afiedt.buf

  1  insert into my_tab
  2*   values( 3, date '2014-01-01', date '2014-01-31', 1, 'Y' )
SQL> /

1 row created.

创建触发器

SQL> ed
Wrote file afiedt.buf

  1  CREATE OR REPLACE TRIGGER mytrig
  2      AFTER UPDATE
  3      ON my_tab
  4      FOR EACH ROW
  5  WHEN (
  6  new.updated = 'Y'
  7        )
  8  BEGIN
  9      INSERT INTO my_hist( id,
 10                           no,
 11                           start_date,
 12                           end_date,
 13                           update_date )
 14        VALUES   (
 15                          :old.id,
 16                          :old.no,
 17                          :old.start_date,
 18                          :old.end_date,
 19                          SYSDATE
 20                    );
 21* END mytrig;
SQL> /

Trigger created.

现在,当我更新行时

SQL> update my_tab
  2     set end_date = date '2014-03-31'
  3   where id = 3;

1 row updated.

MY_HIST 表中只有一行,并且该行将包含 MY_TAB 中行中的旧值

SQL> select * from my_hist;

        ID START_DAT END_DATE          NO U UPDATE_DA
---------- --------- --------- ---------- - ---------
         3 01-JAN-14 31-JAN-14          1   27-MAY-12

如果您看到两行,则其他内容正在写入第二行。我的猜测是您定义了另一个触发器。

【讨论】:

我解决了这个问题,这是由于我在更新字段 Updated = 'Y' 的过程中出现了错误情况。非常感谢。

以上是关于触发插入旧值的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2017 触发器将旧值作为更新后的新值

如果在更新触发之前未在 oracle 中进行更新,则新值与旧值相同

半计算列只能在插入触发器后使用?

如何在 SQL Server 的触发器中获取多个字段的旧值和新值?

使用 MSSQL 中的触发器跟踪和存储新旧值

如何使用触发器将基表的所有更新列添加到审计表的多行?