You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

虚拟宠物网站库存表数量为0时自动删除的SQL实现问询

解决方案:用存储过程封装库存更新与清理逻辑

MySQL不允许在同一张表的AFTER UPDATE触发器中执行DELETE操作,因为这会触发表锁冲突和循环触发检测。辅助表方案也会因同事务内的关联操作被拦截,更稳妥的方式是用存储过程封装完整的库存更新逻辑,替代直接更新inventory表的操作。

具体实现步骤

1. 创建存储过程

这个存储过程接收用户ID、物品ID和数量变化值(比如-1代表使用1个物品,+5代表新增5个物品),完成以下操作:

  • 计算更新后的库存数量
  • 同步更新用户的库存空间
  • 若更新后数量≤0,自动删除该库存记录
DELIMITER //
CREATE PROCEDURE update_inventory(
    IN p_user_id INT,
    IN p_item_id INT,
    IN p_quantity_change INT
)
BEGIN
    DECLARE current_quantity INT;
    DECLARE new_quantity INT;
    START TRANSACTION;

    -- 获取当前库存数量,无记录则初始化为0
    SELECT COALESCE(quantity, 0) INTO current_quantity
    FROM inventory
    WHERE user_id = p_user_id AND item_id = p_item_id;

    SET new_quantity = current_quantity + p_quantity_change;

    IF new_quantity > 0 THEN
        -- 数量仍有效,更新或插入库存记录
        INSERT INTO inventory(user_id, item_id, quantity)
        VALUES(p_user_id, p_item_id, new_quantity)
        ON DUPLICATE KEY UPDATE quantity = new_quantity;

        -- 同步用户库存空间:空间变化 = 原数量 - 新数量
        UPDATE user
        SET inventory_space = inventory_space + (current_quantity - new_quantity)
        WHERE user_id = p_user_id;
    ELSE
        -- 数量≤0,删除库存记录
        DELETE FROM inventory
        WHERE user_id = p_user_id AND item_id = p_item_id;

        -- 释放原数量占用的库存空间
        UPDATE user
        SET inventory_space = inventory_space + current_quantity
        WHERE user_id = p_user_id;
    END IF;

    COMMIT;
END //
DELIMITER ;

2. 业务层调用存储过程

后续业务逻辑不再直接执行UPDATE inventory,而是调用这个存储过程完成操作:

CALL update_inventory(123, 45, -1); -- 用户123使用1个物品45

替代方案:定时清理(适合非实时场景)

如果业务允许延迟清理,可使用MySQL事件调度器定时删除quantity≤0的记录:

-- 开启事件调度器
SET GLOBAL event_scheduler = ON;

DELIMITER //
CREATE EVENT clean_zero_quantity_inventory
ON SCHEDULE EVERY 1 MINUTE -- 可根据需求调整执行频率
DO
BEGIN
    DELETE FROM inventory
    WHERE quantity <= 0;
END //
DELIMITER ;

该方案实现简单,但无法实时清理库存,适合对实时性要求不高的场景。

原方案失败原因

  • MySQL的AFTER UPDATE触发器执行时,原表处于事务锁定状态,不允许对同一张表执行写操作(DELETE/UPDATE),否则会触发死锁检测或循环触发限制。
  • 辅助表方案中,触发器插入辅助表后,辅助表的触发器去删除原表记录属于同一事务内的关联操作,MySQL仍会判定为对原表的非法操作,导致执行失败。

内容的提问来源于stack exchange,提问作者Jerad Beauregard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:42:15