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

MySQL不使用DUPLICATE语法 多条件判断存在更新否则插入咨询

问题结论

你编写的SQL不可行,原因如下:

  • SELECT 语句仅用于数据查询,无法直接执行UPDATE/INSERT这类DML修改操作
  • MySQL的IF表达式只能返回值,不支持嵌套执行DML语句,该写法本身就存在语法错误

正确实现方案

方案1:优先添加联合唯一键(推荐)

如果业务逻辑本身要求student_id + date的组合唯一(不存在同一个学生同一天有多条考勤记录的合理场景),优先给表加联合唯一约束:

ALTER TABLE `attendance` ADD UNIQUE KEY `uk_stu_date` (`student_id`, `date`);

之后直接用ON DUPLICATE KEY UPDATE语法实现需求,性能最高且天然支持原子性:

INSERT INTO `attendance` (`student_id`, `date`, `attendance`)
VALUES (7, '2021-10-04', 0)
ON DUPLICATE KEY UPDATE `attendance` = 0;

方案2:确实无法加唯一键的实现方式

如果因业务特殊原因不能加联合唯一键,用以下两种方法实现:

方式A:先查询后判断执行

适合并发量极低的场景:

  1. 先执行查询判断记录是否存在:
SELECT COUNT(*) AS cnt FROM `attendance` WHERE student_id = 7 AND `date` = '2021-10-04';
  1. 如果返回的cnt大于0,执行UPDATE:
UPDATE `attendance` SET `attendance` = 0 WHERE student_id = 7 AND `date` = '2021-10-04';
  1. 如果返回的cnt等于0,执行INSERT:
INSERT INTO `attendance` (`student_id`, `date`, `attendance`) VALUES (7, '2021-10-04', 0);

注意:高并发场景下这种写法会出现竞态条件,可能插入重复数据,需要配合事务+锁使用。

方式B:事务包裹先更新后插入

比先查后改少一次查询,性能更好:

-- 开启事务
START TRANSACTION;
-- 先执行更新
UPDATE `attendance` SET `attendance` = 0 WHERE student_id = 7 AND `date` = '2021-10-04';
-- 判断更新行数,如果为0则执行插入
IF ROW_COUNT() = 0 THEN
    INSERT INTO `attendance` (`student_id`, `date`, `attendance`) VALUES (7, '2021-10-04', 0);
END IF;
-- 提交事务
COMMIT;

如果是在应用代码中实现,逻辑同理:先执行UPDATE,拿到驱动返回的影响行数,若为0再执行INSERT即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 00:45:01