在多行插入语句 sqlite 上使用触发器

Posted

技术标签:

【中文标题】在多行插入语句 sqlite 上使用触发器【英文标题】:Using a trigger on a multi-row insert statement sqlite 【发布时间】:2014-06-19 17:49:31 【问题描述】:

我正在使用一个表,出于此问题的目的,该表的定义如下

CREATE TABLE players (match_id, hero_id, player_slot);

此表更新非常频繁(每 20 分钟左右一个事务,大约有 1000 次插入)。它包含约 600 万行 atm,但会不断增长。我想(再次,非常频繁地)从最新表中读取以下 SELECT 语句。

SELECT t1.match_id,
    GROUP_CONCAT(hero_id) AS team,
    COUNT(DISTINCT hero_id) AS team_size
FROM (SELECT match_id, hero_id
      FROM players
      WHERE player_slot in (1, 2, 3, 4, 5)
      ORDER BY hero_id) t1
GROUP BY t1.match_id;

这是一个相当简化的查询版本,但每次我想要更新版本时运行它仍然很慢。因此,我希望建立一个单独的表并在插入“玩家”表时触发。幸运的是,我将始终在单个语句中插入具有给定 match_id 的所有记录,例如

INSERT INTO players (match_id, hero_id, player_slot) VALUES
    (1, 2, 3),
    (1, 4, 4),
    (1, 8, 5);

我想写一个触发这些插入的触发器;排序,然后对插入的行进行分组。我还没有找到如何在任何地方做到这一点。似乎不可能将所有插入的行作为一个可以执行 GROUP BY 和 ORDER BY 的表。有没有一种有效的方法来做到这一点?如果没有,是否有足够快的解决方法?

【问题讨论】:

您的 SELECT 查询不是有效的 SQL。 如果这就是您所指的,错过了几个逗号。正如我所说,这是一个更大查询的要点,我很确定它是有效的,因为我一直在使用它。 你不能在 WHERE 之前有 ORDER BY,这在子查询中没有意义。 啊,是的,我颠倒了这两个的顺序。但是 ORDER BY 在子查询中绝对有意义,因为子查询返回的值的顺序是连接它们的顺序,这会影响返回表的值。也就是说,在以后的查询中,我将按“团队”列进行分组,并且无论排列如何,我都需要团队是等效的,因此在连接之前进行排序。 详细说明,这就是我不能只为每个玩家插槽创建一列并在每个插入的行上触发 upsert 的原因。我需要订购插入到多行插入中的所有 hero_id,然后将它们连接起来以获得正确的团队。 【参考方案1】:

这个查询不能加快速度; WHERE 和 ORDER BY 子句冲突,不能使用相同的索引;并且rule 15 防止了内部查询的扁平化(这可能允许外部查询使用某些索引)。


documentation 说:

目前 SQLite 仅支持 FOR EACH ROW 触发器,不支持 FOR EACH STATEMENT 触发器。

所以无法自动填充缓存表;编写match_id 后,您必须从代码中更新缓存。

【讨论】:

是的,我已经在我的代码中实现了非 sql 解决方法。不幸的是,这不能在数据库中自动完成。感谢您的尝试! 点赞!新手,这是否意味着即使在执行单个批量插入时,触发器也会针对插入中的每一行运行,而不是插入的单个操作? @PirateApp “FOR EACH ROW”中的“ROW”确实意味着“行”,而不是“语句”。

以上是关于在多行插入语句 sqlite 上使用触发器的主要内容,如果未能解决你的问题,请参考以下文章

插入后使用触发器更新多行(sql server)

SQLite - 将 MySQL 触发器转换为在 SQLite 上工作

我可以在sqlite中插入触发器之前更新New in吗?

INSTEAD OF与AFTER触发器

触发器根据多对多关系插入多行

新旧列中的触发器