【问题标题】:how can i access a value that's being updated by a trigger?如何访问触发器正在更新的值?
【发布时间】:2017-07-11 18:12:51
【问题描述】:

这是由序列生成并通过 ACCOUNT_NUMBER_TRIG 触发器插入到 ACCOUNTS 表中的 ACCOUNT_NUMBER 的值,我需要通过触发器 ACCOUNTS_TRANSCATION_TRIG_1 将其插入到 TRANSACTION TABLE 中

CREATE OR REPLACE TRIGGER ACCOUNT_NUMBER_TRIG
  BEFORE INSERT 
  ON ACCOUNTS
  FOR EACH ROW
  WHEN (NEW.ACCOUNT_NUMBER is not null)
DECLARE
  V_ACC_NO ACCOUNTS.ACCOUNT_NUMBER%TYPE;
BEGIN
  SELECT ACCOUNT_NO_SEQ.nextvaL INTO V_ACC_NO FROM DUAL;
  :NEW.ACCOUNT_NUMBER := V_ACC_NO;

END ACCOUNT_NUMBER_TRIG;

------------------------------------------------------------------------------

CREATE OR REPLACE TRIGGER ACCOUNTS_TRANSCATION_TRIG_1 AFTER
  INSERT ON ACCOUNTS FOR EACH ROW DECLARE CURSOR ACCOUNTS_CUR IS
  SELECT ACCOUNT_NUMBER FROM ACCOUNTS;
  DECLARE 
  TEMP_1 NUMBER(5,0);
  BEGIN
  SELECT ACCOUNTS.ACCOUNT_NUMBER FROM INSERTED INTO TEMP_1
    OPEN ACCOUNTS_CUR;
    INSERT
    INTO TRANSACTIONS VALUES
      (
         SYSDATE,
      - :NEW.ACCOUNT_NUMBER,
        'NEW ACCOUNT',
        0
      );
    CLOSE ACCOUNTS_CUR;
  END ACCOUNTS_TRANSCATION_TRIG_1;

【问题讨论】:

  • 您是否尝试添加一个通过诸如 column_trigger 之类的触发器更新或插入的列?当触发器工作时,更新或插入此列 = 1 或 true。
  • 问题是我需要插入一条包含更新列的值的新记录

标签: sql oracle plsql database-trigger


【解决方案1】:
CREATE TABLE accounts(
   ACCOUNT_NUMBER number,
   ACCOUNT_NAME varchar2(20)
);

CREATE SEQUENCE ACCOUNT_NO_SEQ;


CREATE OR REPLACE TRIGGER ACCOUNT_NUMBER_TRIG
  BEFORE INSERT 
  ON ACCOUNTS
  FOR EACH ROW
  WHEN (NEW.ACCOUNT_NUMBER is not null)
BEGIN
  :NEW.ACCOUNT_NUMBER :=ACCOUNT_NO_SEQ.nextvaL;
END ACCOUNT_NUMBER_TRIG;
/

CREATE TABLE transactions(
  TR_DATE  date,
  TR_ACCOUNT_NUMBER number,
  TR_TYPE varchar2(20),
  TR_somenumber int
);

CREATE OR REPLACE TRIGGER ACCOUNTS_TRANSCATION_TRIG_1 AFTER
  INSERT ON ACCOUNTS FOR EACH ROW 
  BEGIN
    INSERT INTO TRANSACTIONS( TR_DATE, TR_ACCOUNT_NUMBER, TR_TYPE, TR_somenumber )
    VALUES
      (
         SYSDATE,
        :NEW.ACCOUNT_NUMBER,
        'NEW ACCOUNT',
        0
      );
  END ACCOUNTS_TRANSCATION_TRIG_1;
  /

INSERT INTO accounts( ACCOUNT_NUMBER, ACCOUNT_NAME ) VALUES (1111,'My Name' );

select * from  accounts;
ACCOUNT_NUMBER ACCOUNT_NAME        
-------------- --------------------
             2 My Name  

select * from transactions;
TR_DATE    TR_ACCOUNT_NUMBER TR_TYPE              TR_SOMENUMBER
---------- ----------------- -------------------- -------------
2017/07/11                 2 NEW ACCOUNT                      0

【讨论】:

    【解决方案2】:

    您可以使用 CURVAL 获取 NEXTVAL 返回的最新值:

    CREATE OR REPLACE TRIGGER ACCOUNTS_TRANSCATION_TRIG_1 AFTER
      INSERT ON ACCOUNTS FOR EACH ROW DECLARE CURSOR ACCOUNTS_CUR IS
      BEGIN
        INSERT
        INTO TRANSACTIONS VALUES
          (
             SYSDATE,
           - ACCOUNT_NO_SEQ.curval,
            'NEW ACCOUNT',
            0
          );
        CLOSE ACCOUNTS_CUR;
      END ACCOUNTS_TRANSCATION_TRIG_1;
    

    但是在这种情况下没有必要,因为它已用于设置 ACOUNT_NUMBER:

        INSERT
        INTO TRANSACTIONS VALUES
          (
             SYSDATE,
           - :NEW.ACCOUNT_NUMBER,
            'NEW ACCOUNT',
            0
          );
    

    顺便说一句,除非您使用的是旧版本的 Oracle,否则这应该适用于第一个触发器:

    CREATE OR REPLACE TRIGGER ACCOUNT_NUMBER_TRIG
      BEFORE INSERT 
      ON ACCOUNTS
      FOR EACH ROW
      WHEN (NEW.ACCOUNT_NUMBER is not null)
    BEGIN
      :NEW.ACCOUNT_NUMBER := ACCOUNT_NO_SEQ.nextvaL;
    END ACCOUNT_NUMBER_TRIG;
    

    (我怀疑 WHEN 子句是错误的 - 应该是当 is 为空的时候?)

    【讨论】:

    • 在这种情况下应该不需要访问序列currval,因为之前的触发器已经将序列值放入了account_number列。
    猜你喜欢
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多