【问题标题】:How to use the WITH clause in an SQLite trigger如何在 SQLite 触发器中使用 WITH 子句
【发布时间】:2018-06-07 19:30:59
【问题描述】:

我正在尝试在 SQLite 数据库中创建某些内容的日志。我正在使用触发器执行此操作,但我需要插入多个日志记录,并且它们都需要具有相同的时间戳。为了做到这一点,我尝试使用WITH 子句来获取当前时间戳,然后我可以在多个地方使用它。

我的陈述看起来像这样:

CREATE TRIGGER test7_INSERT AFTER INSERT ON test7 
BEGIN
    WITH t(t) AS (
        SELECT CAST((julianday('now') - 2440587.5)*86400000 
                    AS INTEGER)
    )
    INSERT INTO ChangeLog (t, rowid, field, value)
    VALUES 
    (t.t, 1, 'field1', new.field1),
    (t.t, 1, 'field2', new.field2),
    (t.t, 1, 'field3', new.field3);
END;

但是当我尝试运行此语句时,我在“INSERT”附近收到语法错误。我已重命名其他 INSERT 以将其隔离到触发器本身内的 INSERT 语句。一切都在触发器之外工作,当我查阅TRIGGER 上的 SQLite 文档时,我注意到触发器内只允许更新、插入、删除和选择语句 - 显然省略了 WITH 子句。

我怎样才能达到同样的效果,以便我可以在查询的多个地方重复使用相同的时间戳值?

【问题讨论】:

  • 我相信 WITH 使用 CTE(公用表表达式)并且 TRIGGER 包括 触发器内的语句不支持公用表表达式。
  • 部分CTE可以通过“附加/外部”CTE-viewtrigger中获得:)

标签: sqlite


【解决方案1】:

我会改写为:

INSERT INTO ChangeLog (t, rowid, field, value)
SELECT ":1", ":2", ":3",CAST((julianday('now') - 2440587.5)*86400000  AS INTEGER)
FROM (VALUES
(t.t, 1, 'field1', new.field1),
(t.t, 1, 'field2', new.field1),
(t.t, 1, 'field3', new.field1) ) sub;

DBFiddle Demo

编辑:

WITH cte(c1,c2,c3,c4) AS (
  VALUES  (t.t, 1, 'field1', new.field1),
          (t.t, 1, 'field2', new.field1),
          (t.t, 1, 'field3', new.field1) 
)
INSERT INTO ChangeLog (t, rowid, field, value)
SELECT c1,c2,c3, CAST((julianday('now') - 2440587.5)*86400000  AS INTEGER)
FROM cte;

DBFiddle Demo2


编辑:

INSERT INTO ChangeLog (t, rowid, field, value)
SELECT c1,c2,c3, CAST((julianday('now') - 2440587.5)*86400000  AS INTEGER)
FROM (
    SELECT t.t AS c1, 1 AS c2, 'field1' AS c3, new.field1 AS c4 UNION ALL
    SELECT t.t AS c1, 1 AS c2, 'field2' AS c3, new.field1 AS c4 UNION ALL
    SELECT t.t AS c1, 1 AS c2, 'field3' AS c3, new.field1 AS c4;
) sub

【讨论】:

  • t 似乎位于错误的位置,这很容易修复,但是当它作为触发器运行时,我看到文字“:1”、“:2”等作为字段值。我认为它应该直接替换第一个、第二个等值?
  • 另外,Fiddle 中发生了一些愚蠢的事情,或者至少我不明白......在你的 Fiddle 中,“:1”将进入“t”,我希望是 1, 2, 3。但实际上它是第二列全是 1。这是为什么呢?
  • 我能够通过使用“*”而不是“:1”、“:2”等来使其工作,我在为 SQLite 查找文档时遇到了麻烦,但我认为它们是某些类型的参数绑定可能不允许在触发器内。
  • 你能指出一些关于你正在使用的匿名(“VALUES ...”)和位置(“:1”)值的文档吗?我什么都没有出现,但它们似乎在某种程度上起作用......
  • @Michael 我发布的版本不依赖于:position
猜你喜欢
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 2010-11-25
  • 2021-08-25
  • 1970-01-01
  • 2020-11-18
  • 2014-06-19
相关资源
最近更新 更多