【发布时间】:2018-06-08 07:44:50
【问题描述】:
我正在尝试将更新记录到 SQLite 表中的字段。我已经可以使用类似这样的方式登录INSERTs:
CREATE TRIGGER _test7_INSERT AFTER INSERT ON test7
BEGIN
INSERT INTO ChangeLog (rid, field, value, tms)
SELECT *,CAST((julianday('now') - 2440587.5)*86400000 AS INTEGER)
FROM (VALUES
(new.rowid, 'field1', new.field1),
(new.rowid, 'field2', new.field2),
(new.rowid, 'field3', new.field3)
) sub;
END;
这显然是使用匿名值,我无法找到具体的文档,但它似乎可以创建一个静态表,然后我可以选择插入到日志表中。
但是,对于更新,我只想记录实际更改的字段,因此,例如,如果一个表有 20 个字段并且由于更新而仅更改了 1 个字段,我只希望将 1 行添加到更改表中,而不是 20 个。我有一个如下所示的触发器:
CREATE TRIGGER _test7_UPDATE AFTER UPDATE on test7
BEGIN
INSERT INTO ChangeLog (rid, field, value, tms)
SELECT "" AS rid,
":1" AS field,
":2" AS value,
CAST((julianday('now') - 2440587.5)*86400000 AS INTEGER) AS tms
FROM (VALUES
(old.rowid, 'field1', new.field1, new.field1=old.field1),
(old.rowid, 'field2', new.field2, new.field2=old.field2),
(old.rowid, 'field3', new.field3, new.field3=old.field3)
) sub
WHERE ":4"=1;
END;
但是当我进行更新时,什么都没有插入!如果我删除额外的比较字段并删除“WHERE”子句,我会看到添加了三行,但没有添加 rid、field 和 value,而是看到文字值“”、“: 1”和“:2”。我没有找到很多关于这些编号参数的文档——“参数”部分下的SQLite language page 顺便提到了它们,但提供的信息很少——实际上它甚至没有解释为什么“:1”实际上是second 参数和 "" 是第一个!我应该补充一点,我已经尝试在触发器之外使用非常相似的 SELECT ,将常量值放入 VALUES 表中,并且效果很好!具体来说:
SELECT "" AS a, ":1" AS b, ":2" AS c, ":3" AS d
FROM (VALUES
(11,22,33,44),
(111,122,133,144),
(211,222,233,244)
) sub;
返回一个表,其中包含文字值、标记为“a”、“b”、“c”和“d”的列。但触发器中的相同基本结构返回带有冒号的文字字符串,而不是预期的实际值。
我有一个聪明的想法,即创建一个带有额外字段的临时表,选择其中的所有内容,然后选择除比较之外的所有内容到真实日志表中。这不起作用,因为触发器中不支持 CREATE)
我还尝试创建 ChangeLog 以有一个额外的字段来保存比较中的第五个字段(例如 new.fieldx = old.fieldx),但是当我使用 WHERE 子句仅选择更改的字段时,我又回到了没有再次插入。
我还有其他方法可以解决这个问题,还是我在处理位置参数的方式上做错了什么?
更新:我一直在试验,发现在某些情况下位置参数实际上是有值的,但是它们相当荒谬:
具体来说,""字段返回second参数的值,":1"字段返回第四参数的值。为什么?如何引用第一个和第三个参数?
更新 2:在玩了一会儿之后,似乎 ""、":1"、":2" 等参数工作正常,只要只有VALUES 表中的常量值。我插入的任何实际值,例如来自新的、旧的等 - 我实际需要的列 - 都被完全忽略,就好像这些列甚至不存在一样!
【问题讨论】:
标签: sqlite