DB2 更新触发器

Posted

技术标签:

【中文标题】DB2 更新触发器【英文标题】:DB2 update trigger 【发布时间】:2013-03-21 14:35:39 【问题描述】:

我正在尝试在 DB2 数据库中创建一个触发器,该触发器在更新一个表中的列时运行,然后用某些值填充另一个表。

例如,有一个带有FLEET_ID 列的功率单元表。每次更改FLEET_ID 时,我都需要在TRANS_AUDIT 表中创建一个新行。

TRANS_AUDIT 架构如下:

CREATE TABLE LYNX.TRANS_AUDIT (
    TA_ID INTEGER NOT NULL,
    TA_KEY_VALUE VARCHAR(100),
    TA_TABLE_CHANGED VARCHAR(40),
    TA_FIELD_CHANGED VARCHAR(40),
    TA_OLD_FIELD_VALUE VARCHAR(100),
    TA_NEW_FIELD_VALUE VARCHAR(100),
    TA_USER_WHO_CHANGED VARCHAR(128),
    TA_DATE_CHANGED TIMESTAMP,
    TA_COMMENT VARCHAR(40),
    TA_OLD_FIELD_DOUBLE DOUBLE DEFAULT 0,
    TA_NEW_FIELD_DOUBLE DOUBLE DEFAULT 0,
    PRIMARY KEY (TA_ID)
);

这是我目前所拥有的,但我似乎无法让它工作,我收到了 function sequence 错误。

CREATE TRIGGER PU_UPD_FLEETID
AFTER UPDATE OF FLEET_ID ON PUNIT 
REFERENCING OLD AS O NEW AS N
FOR EACH ROW 
MODE DB2SQL 
BEGIN ATOMIC 

    DECLARE 
    vTA_ID INTEGER;

    IF(N.FLEET_ID <> O.FLEET_ID) THEN

        SELECT MAX(TA_ID)+1 FROM TRANS_AUDIT INTO vTA_ID; --generate a unique sequential id 
            INSERT INTO LYNX.TRANS_AUDIT (TA_ID, TA_KEY_VALUE, TA_TABLE_CHANGED, TA_FIELD_CHANGED, TA_OLD_FIELD_VALUE, TA_NEW_FIELD_VALUE, TA_USER_WHO_CHANGED, TA_DATE_CHANGED, TA_COMMENT, TA_OLD_FIELD_DOUBLE, TA_NEW_FIELD_DOUBLE)
            VALUES (TA_ID, N.UNIT_ID , 'PUNIT', 'FLEET_ID', O.FLEET_ID, N.FLEET_ID , SESSION_USER ,CURRENT TIMESTAMP , '', '0' ,'0' );
    END IF;
END;

【问题讨论】:

我不是 DB2 专家,但 SELECT MAX(TA_ID)+1 INTO vTA_ID; 看起来很可疑。这个语句是从什么中选择的? 我试图生成一个比 TRANS_AUDIT 表中的当前 ID 大一的唯一 ID。这样做的正确方法是什么? 啊,我的错,我不小心复制错了,我忘记了from语句 在我看来vTA_ID的声明后应该有一个BEGIN。 至于“如何生成唯一ID”,我建议你研究一下序列的使用。执行 SELECT MAX(some_field)+1 本质上是危险的 - 考虑如果您有两个进程试图同时生成一个“唯一”数字会发生什么。可以想象,两者都可以生成相同的“唯一”编号并将其插入数据库。一个进程将能够成功插入其数据,但第二个进程将由于唯一密钥违规而失败。这就是所谓的“竞争条件”,两个进程相互竞争,看谁“获胜”。使用序列来避免这种情况。 【参考方案1】:

在您的 INSERT 语句中,我认为 VALUES 中的第一个条目应该是 vTA_ID,而不是 TA_ID

分享和享受。

【讨论】:

以上是关于DB2 更新触发器的主要内容,如果未能解决你的问题,请参考以下文章

DB2 触发器哪个更新

更新错误后的 DB2 触发器

DB2 SQL 代替更新触发器

如何防止 DB2 中的递归触发器调用

db2中的SP是不是等待触发器执行

如何将 DB2 触发器转换为 SQL Server?