在mysql中插入后更新所有行

时间:2020-04-30 23:58:34

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

我正在使用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错误。 / p>

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 ;

我认为无法执行此操作,那么如何更新这些行?

2 个答案:

答案 0 :(得分:0)

触发器无法操作对其触发的表。这是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

这将为您提供始终保持最新状态的列,而无需维护。

答案 1 :(得分:0)

如果只需要最近的行,则可以使用:

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

这将在视图中起作用。

更常见的情况是,您有一个有效的 per 东西-例如“实用程序”之类的东西。在这种情况下,您可以使用辅助表将每个“内容”中的一行与活动帐户的ID一起存储。触发器可以设定这个想法。

在您的情况下,costs表中只有一个活动行,因此辅助表可能被认为是多余的。使用上面的查询,您可以轻松获得当前有效值。

相关问题