实现多列判断的SQL Upsert(存在更新/不存在插入)方案咨询
单条SQL实现下载记录的新增/更新(UPSERT)
要实现你说的「当月首次处理则新增,否则downloads加1」的逻辑,核心是用数据库的UPSERT(插入或更新)语法,前提是给summary表的fileId、month、year三个字段创建唯一联合索引——这是判断记录是否存在的核心依据。
下面分主流数据库给出具体实现:
1. MySQL / MariaDB
使用INSERT ... ON DUPLICATE KEY UPDATE语法:
INSERT INTO summary (fileId, month, year, downloads) VALUES (?, ?, ?, 1) -- ?为占位符,替换为实际的fileId、当月月份、当年年份 ON DUPLICATE KEY UPDATE downloads = downloads + 1;
原理:当插入的(fileId, month, year)组合触发唯一索引冲突时,执行更新操作将downloads加1;无冲突则直接插入新行,downloads初始值设为1。
2. PostgreSQL
使用INSERT ... ON CONFLICT ... DO UPDATE语法,需先创建唯一约束:
-- 先创建唯一约束 ALTER TABLE summary ADD CONSTRAINT unique_file_month_year UNIQUE (fileId, month, year); -- 执行UPSERT INSERT INTO summary (fileId, month, year, downloads) VALUES ($1, $2, $3, 1) ON CONFLICT (fileId, month, year) DO UPDATE SET downloads = summary.downloads + 1;
3. SQL Server
使用MERGE语句:
MERGE INTO summary AS target USING (SELECT ? AS fileId, ? AS month, ? AS year) AS source ON target.fileId = source.fileId AND target.month = source.month AND target.year = source.year WHEN MATCHED THEN UPDATE SET downloads = target.downloads + 1 WHEN NOT MATCHED THEN INSERT (fileId, month, year, downloads) VALUES (source.fileId, source.month, source.year, 1);
关键注意事项
- 必须确保
(fileId, month, year)的唯一约束/索引存在,否则UPSERT逻辑会失效,甚至产生重复数据。 - 针对每日大文件量的场景,可将多条记录合并为一个批量INSERT语句(比如MySQL支持
VALUES (?, ?, ?, 1), (?, ?, ?, 1), ...),能大幅提升处理效率。 - 高并发场景下,部分数据库支持在UPSERT时加锁(如PostgreSQL的
ON CONFLICT ... DO UPDATE SKIP LOCKED),可避免竞态问题。
内容的提问来源于stack exchange,提问作者Murat Colyaran
相关产品推荐
相关产品推荐

