在 Informix 中跳过特定用户的触发器

Skip a Trigger for a Specific User in Informix

当特定数据库用户通过 运行 脚本进行更改时是否可以绕过触发器?

在 Informix 触发器的 when 子句中,我们可以这样做吗:

CREATE TRIGGER trigger_name
    update on table_name
    referencing old as olddata new as newdata
    for each row when(USER <> 'a specific database user')
    (…triggered actions…)

关于 Informix 12.10 的文档 CREATE TRIGGER eventually leads to the WHEN condition 描述。

只要您可以预测何时创建触发器,哪些用户不应触发该操作,您就应该能够编写类似 WHEN (USER != 'exempt') 的内容,但要让它发挥作用会更难动态地。您可能能够在 WHEN 条件中调用存储过程,以评估当前用户当前是否免于触发操作。除了在 WHEN 条件下或作为触发操作使用存储过程之外,它可能无法有意义地完成。

概念验证

架构和触发器

DROP TABLE IF EXISTS trigger_test;
CREATE TABLE trigger_test
(
    s   SERIAL NOT NULL PRIMARY KEY,
    t   DATETIME YEAR TO SECOND NOT NULL DEFAULT CURRENT YEAR TO SECOND,
    v   VARCHAR(64) NOT NULL
);

DROP TABLE IF EXISTS trigger_log;
CREATE TABLE trigger_log
(
    log_id  SERIAL NOT NULL PRIMARY KEY,
    old_s   INTEGER NOT NULL,
    old_t   DATETIME YEAR TO SECOND NOT NULL,
    new_t   DATETIME YEAR TO SECOND NOT NULL,
    old_v   VARCHAR(64) NOT NULL,
    new_v   VARCHAR(64) NOT NULL,
    log_t   DATETIME YEAR TO SECOND NOT NULL DEFAULT CURRENT YEAR TO SECOND,
    log_u   VARCHAR(32) NOT NULL DEFAULT USER
);

CREATE TRIGGER skip_user
    UPDATE ON trigger_test
    REFERENCING OLD AS OLD NEW AS NEW
    FOR EACH ROW WHEN(USER != 'informix')
    (INSERT INTO trigger_log(old_s, old_t, new_t, old_v, new_v)
        VALUES(old.s, old.t, new.t, old.v, new.v)
    )
    ;

作为非 informix 用户的操作顺序

我正在使用我的 sqlcmd 程序(可从 ESQL 部分的 IIUG Software Archive 获得 — 它与 Microsoft 的同名 johnny-come-lately 程序截然不同)和自定义工具a6 切换为使用 informix 凭据(实际上类似于 su informixsudo informix)。

$ sqlcmd -d stores -xHTf user-action.sql 
+ INSERT INTO trigger_test(v) VALUES("Hello");
+ SELECT * FROM trigger_test;
s|t|v
SERIAL|DATETIME YEAR TO SECOND|VARCHAR(64)
1|2019-12-19 17:04:04|Hello
+ SELECT * FROM trigger_log;
log_id|old_s|old_t|new_t|old_v|new_v|log_t|log_u
SERIAL|INTEGER|DATETIME YEAR TO SECOND|DATETIME YEAR TO SECOND|VARCHAR(64)|VARCHAR(64)|DATETIME YEAR TO SECOND|VARCHAR(32)
+ UPDATE trigger_test SET t = '2019-12-31 23:59:59', v = 'Farewell to 2019';
+ SELECT * FROM trigger_test;
s|t|v
SERIAL|DATETIME YEAR TO SECOND|VARCHAR(64)
1|2019-12-31 23:59:59|Farewell to 2019
+ SELECT * FROM trigger_log;
log_id|old_s|old_t|new_t|old_v|new_v|log_t|log_u
SERIAL|INTEGER|DATETIME YEAR TO SECOND|DATETIME YEAR TO SECOND|VARCHAR(64)|VARCHAR(64)|DATETIME YEAR TO SECOND|VARCHAR(32)
1|1|2019-12-19 17:04:04|2019-12-31 23:59:59|Hello|Farewell to 2019|2019-12-19 17:04:04|jonathanleffler
+ UPDATE trigger_test SET t = '2038-01-19 03:14:07', v = 'Farewell to 32-bit Unix time';
+ SELECT * FROM trigger_test;
s|t|v
SERIAL|DATETIME YEAR TO SECOND|VARCHAR(64)
1|2038-01-19 03:14:07|Farewell to 32-bit Unix time
+ SELECT * FROM trigger_log;
log_id|old_s|old_t|new_t|old_v|new_v|log_t|log_u
SERIAL|INTEGER|DATETIME YEAR TO SECOND|DATETIME YEAR TO SECOND|VARCHAR(64)|VARCHAR(64)|DATETIME YEAR TO SECOND|VARCHAR(32)
1|1|2019-12-19 17:04:04|2019-12-31 23:59:59|Hello|Farewell to 2019|2019-12-19 17:04:04|jonathanleffler
2|1|2019-12-31 23:59:59|2038-01-19 03:14:07|Farewell to 2019|Farewell to 32-bit Unix time|2019-12-19 17:04:04|jonathanleffler
$

如您所见,我执行的操作记录在 trigger_log table.

作为用户 informix 的操作顺序

$ a6 sqlcmd -d stores -xHTf ifmx-action.sql 
+ UPDATE trigger_test SET t = '2019-01-01 00:00:00', v = 'Welcome to the New Year 2019';
+ SELECT * FROM trigger_test;
s|t|v
SERIAL|DATETIME YEAR TO SECOND|VARCHAR(64)
1|2019-01-01 00:00:00|Welcome to the New Year 2019
+ SELECT * FROM trigger_log;
log_id|old_s|old_t|new_t|old_v|new_v|log_t|log_u
SERIAL|INTEGER|DATETIME YEAR TO SECOND|DATETIME YEAR TO SECOND|VARCHAR(64)|VARCHAR(64)|DATETIME YEAR TO SECOND|VARCHAR(32)
1|1|2019-12-19 17:04:04|2019-12-31 23:59:59|Hello|Farewell to 2019|2019-12-19 17:04:04|jonathanleffler
2|1|2019-12-31 23:59:59|2038-01-19 03:14:07|Farewell to 2019|Farewell to 32-bit Unix time|2019-12-19 17:04:04|jonathanleffler
$

可以看到,更新生效了,但是结果没有记录在trigger_log table.

正如您可能还观察到的,使用的 UPDATE 语句很草率;他们更新所有行。最好也使用 DATETIME YEAR TO FRACTION(5)。我的数据库服务器 运行 的时区设置为 UTC — 因此插入时间也以 UTC 记录。