DB2触发器新视图不反映由以前的触发器更新的数据

ffscu2ro  于 2022-11-07  发布在  DB2
关注(0)|答案(2)|浏览(203)

假设我创建了以下表:

create table SAMPLE (
    ID INTEGER,
    COL_A INTEGER,
    COL_B INTEGER
);
create table SAMPLE_CLONE (
    ID INTEGER,
    COL_A INTEGER,
    COL_B INTEGER
);

我创建了以下触发器:

-- Increment COL_A on every update
CREATE TRIGGER INC_COL_A AFTER UPDATE ON SAMPLE
REFERENCING  OLD AS oldrow  NEW AS newrow  
FOR EACH ROW MODE DB2SQL 
WHEN (oldrow.COL_A = newrow.COL_A)
UPDATE SAMPLE SET COL_A = COL_A+1 WHERE ID = oldrow.ID;

-- Replicate inserts from SAMPLE to SAMPLE_CLONE
CREATE TRIGGER REPLICATE_INSERTED_DATA
AFTER INSERT ON SAMPLE
REFERENCING NEW AS newrow
FOR EACH ROW MODE DB2SQL
INSERT INTO SAMPLE_CLONE (ID, COL_A, COL_B) VALUES (newrow.ID, newrow.COL_A, newrow.COL_B);

-- Replicate updates from SAMPLE to SAMPLE_CLONE
CREATE TRIGGER REPLICATE_UPDATED_DATA
AFTER UPDATE ON SAMPLE
REFERENCING NEW AS newrow OLD AS oldrow
FOR EACH ROW MODE DB2SQL
UPDATE SAMPLE_CLONE SET COL_A = newrow.COL_A, COL_B = newrow.COL_B WHERE ID = newrow.ID;

我遇到的问题是,在SAMPLE表上运行任何更新后,由触发器INC_COL_A递增的COL_A最新值在触发器REPLICATE_UPDATED_DATA处理期间没有反映到newrow中。例如,如果我有以下数据:

INSERT INTO SAMPLE (ID, COL_A, COL_B) VALUES (1, 1, 100);

样品
| 识别码|列_A|列_B|
| - -|- -|- -|
| 一个|一个|100个|
样本克隆
| 识别码|列_A|列_B|
| - -|- -|- -|
| 一个|一个|100个|
然后,在运行以下命令后:

UPDATE SAMPLE SET COL_B = 200 WHERE ID = 1;

我在这些表上得到了以下提交结果:
样品
| 识别码|列_A|列_B|
| - -|- -|- -|
| 一个|2个|二百个|
样本克隆
| 识别码|列_A|列_B|
| - -|- -|- -|
| 一个|一个|二百个|
请注意,SAMPLE_CLONE.COL_A上的记录没有被REPLICATE_UPDATED_DATA触发器复制,因为它没有获得INC_COL_A触发器所做的更新。
我在使用DB2 11.5时遇到了这个问题

tag5nh1u

tag5nh1u1#

共享事件、时间和目标的触发器按其创建顺序执行。每个BEFORE触发器都可以修改NEW ROW,后续的BEFORE触发器将使用修改后的行。每个AFTER触发器都将接收相同的最终行,它们都不能修改它。
这里,INC_COL_AREPLICATE_UPDATED_DATA按此顺序执行。
所以当UPDATE SAMPLE SET COL_B = 200 WHERE ID = 1;运行时

  1. DB2生成一个中间行,其中COLB_B = 200
  2. INC_COL_A被触发,执行UPDATE SAMPLE SET COL_A = 2
    1.此更新将再次触发INC_COL_A,但由于COL_A在旧行和新行中相同,因此不会发生任何情况
  3. REPLICATE_UPDATED_DATA使用COL_A = 2, COL_B = 200处理行,并将其复制到SAMPLE_CLONE
  4. INC_COL_A内部的UPDATE语句现在已经完成,但是REPLICATE_UPDATED_DATA仍然需要处理COL_A = 1, COL_B = 200
    最后,COL_A = 1和遵循一个逻辑。在**INC_COL_A之前创建REPLICATE_UPDATED_DATA**,您的触发器将按预期工作。
    检查实际行值是否与旧行值匹配可能是这里的一个解决方案,但可能不是您在真实的应用程序中所需要的。
CREATE TRIGGER REPLICATE_UPDATED_DATA
AFTER UPDATE ON SAMPLE
REFERENCING NEW AS newrow OLD AS oldrow
FOR EACH ROW MODE DB2SQL
UPDATE SAMPLE_CLONE SET COL_A = newrow.COL_A, COL_B = newrow.COL_B
  WHERE ID = newrow.ID
        and (col_a, col_b) = (old_row.col_a, old_row.col_b);
5lhxktic

5lhxktic2#

这不是让更新(或插入)触发器更改写入的值的正确方法...您需要使用BEFORE更新(插入)触发器

-- Increment COL_A on every update
CREATE TRIGGER INC_COL_A BEFORE UPDATE ON SAMPLE
REFERENCING  OLD AS oldrow  NEW AS newrow  
FOR EACH ROW MODE DB2SQL 
WHEN (oldrow.COL_A = newrow.COL_A)
 SET newrow.COL_A = oldrow.COL_A+1 ;

相关问题