PostgreSQL:执行INSERT后返回同活动参与人数的单SQL实现
嘿,这个需求很实用,单条SQL就能搞定,不过得看你用的是哪种数据库,我给你整理几种主流数据库的实现方式:
MySQL(8.0.19及以上版本)
MySQL从8.0.19开始支持INSERT ... RETURNING语法,配合CTE(公共表表达式)可以在插入的同时获取活动的总参与人数:
WITH inserted AS ( INSERT INTO participations (usr, event_id) VALUES (:usr, :event_id) RETURNING event_id ) SELECT COUNT(*) AS total_participants FROM participations WHERE event_id = (SELECT event_id FROM inserted);
如果你的表有唯一约束(比如同一个用户不能重复报名同一个活动),可以加上ON DUPLICATE KEY UPDATE来处理重复报名的情况,同时依然返回当前活动的总人数:
WITH inserted AS ( INSERT INTO participations (usr, event_id) VALUES (:usr, :event_id) ON DUPLICATE KEY UPDATE usr = usr -- 无实际更新,仅触发RETURNING RETURNING event_id ) SELECT COUNT(*) AS total_participants FROM participations WHERE event_id = (SELECT event_id FROM inserted);
PostgreSQL
PostgreSQL对RETURNING和CTE的支持更成熟,写法和MySQL类似:
WITH inserted AS ( INSERT INTO participations (usr, event_id) VALUES (:usr, :event_id) RETURNING event_id ) SELECT COUNT(*) AS total_participants FROM participations WHERE event_id = (SELECT event_id FROM inserted);
如果要处理重复报名的场景,可以用ON CONFLICT子句:
WITH inserted AS ( INSERT INTO participations (usr, event_id) VALUES (:usr, :event_id) ON CONFLICT (usr, event_id) DO NOTHING -- 重复时不执行操作 RETURNING event_id ) SELECT COUNT(*) AS total_participants FROM participations WHERE event_id = COALESCE((SELECT event_id FROM inserted), :event_id);
这里用COALESCE是因为当重复报名时inserted会是空集,直接取传入的:event_id即可。
SQL Server
SQL Server可以通过OUTPUT子句配合CTE实现需求:
WITH inserted AS ( INSERT INTO participations (usr, event_id) OUTPUT inserted.event_id VALUES (:usr, :event_id) ) SELECT COUNT(*) AS total_participants FROM participations WHERE event_id = (SELECT event_id FROM inserted);
注意事项
- 这些语句都是原子性的,数据库会保证插入操作和计数查询在同一个事务中执行,避免并发场景下的计数不准确。
- 确保你的表结构中
event_id字段有索引,这样COUNT(*)的查询效率会更高,尤其是当参与人数很多的时候。
内容的提问来源于stack exchange,提问作者truvaking
相关产品推荐
相关产品推荐

