HSQLDB 删除触发器导致子查询出现问题
Posted
技术标签:
【中文标题】HSQLDB 删除触发器导致子查询出现问题【英文标题】:HSQLDB delete trigger is causing problem in subquery 【发布时间】:2021-01-28 07:35:49 【问题描述】:我在 HSQLDB 删除触发器中遇到问题,不知何故它没有按预期工作。
我正在尝试实现数据库中每次更改的日志。
对于示例测试,我执行以下 SQL 语句:
CREATE TABLE msg (
id INTEGER IDENTITY PRIMARY KEY,
name VARCHAR(80)
);
CREATE TABLE log (
id INTEGER IDENTITY PRIMARY KEY,
row_id INTEGER,
op VARCHAR(30),
status VARCHAR(30)
);
insert into msg (id, name) values (0, 'First Test Message');
insert into log (id, row_id, op, status) values (0, 0, 'insert', 'pending');
update log set status = 'done' where id = 0;
现在,我创建一个删除触发器并从msg
表中删除行:
CREATE TRIGGER update_log_delete_msg
AFTER DELETE ON msg REFERENCING OLD ROW AS old_row FOR EACH ROW
BEGIN ATOMIC
INSERT INTO log(row_id, op, status)
SELECT old_row.id, 'delete', CASE status WHEN 'pending' THEN 'cancel' ELSE 'pending' END FROM log
WHERE row_id = old_row.id AND NOT status = 'cancel' ORDER BY id DESC LIMIT 1;
UPDATE log SET status = 'cancel'
WHERE row_id = old_row.id AND op = 'insert' AND status = 'pending';
END
delete from msg where id = 0;
到目前为止,它按预期工作:
insert into msg values (0, 'Test Message Again');
insert into log (row_id, op, status) values (0, 'insert', 'pending');
这个,时间删除会出问题:
delete from msg where id = 0;
日志中状态的预期行为应该是cancel
而不是pending
,为什么会导致问题?
【问题讨论】:
您可以通过检查触发器 hsqldb.org/doc/2.0/guide/… 内的 INSERT 和 UPDATE 语句返回的 ROW_COUNT 来调试它 @fredt 我认为,行被更新/插入得很好,只有在插入状态完成之前,删除它才会导致最后一次删除操作出错。 我的意思是 CREATE TRIGGER 中的 INSERT 和 UPDATE。 【参考方案1】:如果您不重复使用 ID 值零,这似乎可行。当您重用该值时,log
表中的旧行会导致意外结果。
insert into msg values (1, 'Test Message Again');
insert into log (row_id, op, status) values (1, 'insert', 'pending');
delete from msg where id = 1;
-- dump of the log table
0,0,insert,done
1,0,delete,pending
2,1,insert,cancel
3,1,delete,cancel
【讨论】:
日志表的精确结果应该是这样的 ``` 0,1,insert,done 1,1,delete,pending 2,1,insert,cancel 3,1,delete,cancel ` `` 诀窍是,在Insert
之后,如果插入操作正在等待另一个表,则不需要Delete
操作相同的 id,但是如果它在另一个表中完成,那么删除操作应该是挂起的......
如果您在“日志”表中记录多个表,除了日志文件中的行 ID 之外,您还需要包含表的名称。您还需要避免在同一个表中重复使用行 ID。如果你不做这些事情,你会得到与现有 SQL 触发器代码混淆的结果。
大多数情况下我不重用相同的 ID,但有时不得不重用,我仍然无法思考,为什么我的逻辑在状态完成时会导致问题,但其他方面它运行良好。看截图
我的最终解决方案,如果没有完成状态:i.stack.imgur.com/GYaoF.png,但状态完成时的逻辑相同,看起来是最后一个问题:i.stack.imgur.com/jjtJw.png以上是关于HSQLDB 删除触发器导致子查询出现问题的主要内容,如果未能解决你的问题,请参考以下文章