DB2 触发器新视图不反映以前触发器更新的数据
DB2 trigger new view doesn't reflect data updated by previous triggers
假设我创建了以下 tables:
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 table 进行任何更新后,触发器 INC_COL_A
增加的 COL_A 最新值不是在触发器 REPLICATE_UPDATED_DATA 处理期间反映到 newrow
中。例如,如果我有以下数据:
INSERT INTO SAMPLE (ID, COL_A, COL_B) VALUES (1, 1, 100);
样本
ID
COL_A
COL_B
1
1
100
SAMPLE_CLONE
ID
COL_A
COL_B
1
1
100
然后,在 运行 执行以下命令后:
UPDATE SAMPLE SET COL_B = 200 WHERE ID = 1;
我在这些 table 上得到以下结果:
样本
ID
COL_A
COL_B
1
2
200
SAMPLE_CLONE
ID
COL_A
COL_B
1
1
200
请注意 SAMPLE_CLONE.COL_A
上的记录没有被 REPLICATE_UPDATED_DATA
触发器复制,因为它没有得到 INC_COL_A
触发器所做的更新。
我在使用 DB2 11.5 时遇到了这个问题
这不是让更新(或插入)触发器更改正在写入的值的正确方法...您想使用 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 ;
共享事件、时间和目标的触发器按创建顺序执行。每个 BEFORE
触发器都可以修改 NEW ROW
,后续 BEFORE
触发器将使用修改后的行。每个 AFTER
个触发器都将收到相同的最后一行,其中 none 个可以修改它。
这里INC_COL_A
和REPLICATE_UPDATED_DATA
是按照这个顺序执行的
所以当 UPDATE SAMPLE SET COL_B = 200 WHERE ID = 1;
是 运行
- DB2 使用
COLB_B = 200
生成一个中间行
INC_COL_A
被触发,执行UPDATE SAMPLE SET COL_A = 2
- 此更新再次触发
INC_COL_A
,但由于 COL_A
在旧行和新行中相同,因此没有任何反应
REPLICATE_UPDATED_DATA
用 COL_A = 2, COL_B = 200
处理行并将其复制到 SAMPLE_CLONE
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);
假设我创建了以下 tables:
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 table 进行任何更新后,触发器 INC_COL_A
增加的 COL_A 最新值不是在触发器 REPLICATE_UPDATED_DATA 处理期间反映到 newrow
中。例如,如果我有以下数据:
INSERT INTO SAMPLE (ID, COL_A, COL_B) VALUES (1, 1, 100);
样本
ID | COL_A | COL_B |
---|---|---|
1 | 1 | 100 |
SAMPLE_CLONE
ID | COL_A | COL_B |
---|---|---|
1 | 1 | 100 |
然后,在 运行 执行以下命令后:
UPDATE SAMPLE SET COL_B = 200 WHERE ID = 1;
我在这些 table 上得到以下结果:
样本
ID | COL_A | COL_B |
---|---|---|
1 | 2 | 200 |
SAMPLE_CLONE
ID | COL_A | COL_B |
---|---|---|
1 | 1 | 200 |
请注意 SAMPLE_CLONE.COL_A
上的记录没有被 REPLICATE_UPDATED_DATA
触发器复制,因为它没有得到 INC_COL_A
触发器所做的更新。
我在使用 DB2 11.5 时遇到了这个问题
这不是让更新(或插入)触发器更改正在写入的值的正确方法...您想使用 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 ;
共享事件、时间和目标的触发器按创建顺序执行。每个 BEFORE
触发器都可以修改 NEW ROW
,后续 BEFORE
触发器将使用修改后的行。每个 AFTER
个触发器都将收到相同的最后一行,其中 none 个可以修改它。
这里INC_COL_A
和REPLICATE_UPDATED_DATA
是按照这个顺序执行的
所以当 UPDATE SAMPLE SET COL_B = 200 WHERE ID = 1;
是 运行
- DB2 使用
COLB_B = 200
生成一个中间行
INC_COL_A
被触发,执行UPDATE SAMPLE SET COL_A = 2
- 此更新再次触发
INC_COL_A
,但由于COL_A
在旧行和新行中相同,因此没有任何反应 REPLICATE_UPDATED_DATA
用COL_A = 2, COL_B = 200
处理行并将其复制到SAMPLE_CLONE
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);