【问题标题】:update all rows after insertion in mysql插入mysql后更新所有行
【发布时间】:2020-04-30 23:58:34
【问题描述】:

我正在使用 mysql,并且我有一个具有以下结构的表(摘要):

CREATE TABLE `costs` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `utility` DECIMAL(9,2) UNSIGNED NOT NULL,
    `tax` DECIMAL(9,2) UNSIGNED NOT NULL,
    `active` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
)

插入时活动字段默认为 1,然后我想在保存新记录时所有其他行都将活动字段更新为 0,所以我尝试为此创建触发器,但出现 mysql 错误。

DELIMITER //
CREATE TRIGGER after_costs_insert AFTER INSERT ON costs FOR EACH ROW 
BEGIN
  UPDATE costs SET active = 0 WHERE id <> NEW.id;
END;
//
DELIMITER ;

我认为不可能做到这一点,那么如何更新这些行?

【问题讨论】:

  • 如果您总是希望最后一行处于活动状态,为什么还需要这个活动列?每次插入后更新每一行的成本很高,因此您可以缓存活动的行 ID。

标签: mysql sql database sql-insert database-trigger


【解决方案1】:

触发器无法操作触发它的表。这是 SQL 中的一个典型限制,主要是为了防止调用时出现无限循环(查询触发触发器、执行查询、触发触发器等等)。

在这里,我实际上建议使用在查询时动态计算列的视图,而不是实际存储此派生信息。

如果您运行的是 MySQL 8.0:

create view costs_view as
select 
    id, 
    utility, 
    tax, 
    row_number() over(order by id desc) = 1 active,
    created_at,
    updated_at
from costs

在早期版本中:

create view costs_view as
select 
    id, 
    utility, 
    tax, 
    id = (select max(id) from costs) active,
    created_at,
    updated_at
from costs

这为您提供了一个始终是最新的列,您无需维护。

【讨论】:

    【解决方案2】:

    如果你只想要最近的一行,那么你可以使用:

    select c.*
    from costs c
    order by id desc   -- or created_at
    limit 1;
    

    这将在视图中起作用。

    更常见的情况是,您有一个活动的per 东西——例如“实用程序”或其他任何东西。在这种情况下,您可以使用辅助表来存储每个“某物”的一行以及活动帐户的 ID。触发器可以设置这个想法。

    在您的情况下,costs 表中只有一个活动行,因此辅助表可能被认为是矫枉过正。您可以使用上述查询轻松获取当前活动值。

    【讨论】:

      猜你喜欢
      • 2016-01-13
      • 1970-01-01
      • 2014-06-19
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多