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

SQL批量插入多行时如何逐行校验记录不存在才执行插入

逐行校验不存在才插入多行的实现方案

核心逻辑是先把待插入的多行数据构造成可查询的临时结果集,再对每一行单独做存在性判断,筛选出不存在的行再执行插入,避免直接写VALUES加全局WHERE导致的全量生效问题。


方案1:通用CTE写法(兼容绝大多数支持SQL:2003标准的数据库:PostgreSQL、SQL Server、MySQL 8.0+、SQLite 3.8.3+等)

-- 先通过CTE定义所有待插入的行,结构和目标表字段一一对应
WITH pending_insert_rows (promotion_name, discount, start_date, expired_date) AS (
    VALUES
        ('2019 Summer Promotion', 0.15, '20190601', '20190901'),
        ('2019 Fall Promotion',   0.20, '20191001', '20191101'),
        ('2019 Winter Promotion', 0.25, '20191201', '20200101')
)
INSERT INTO sales.promotions (promotion_name, discount, start_date, expired_date)
SELECT  pir.promotion_name,
        pir.discount,
        pir.start_date,
        pir.expired_date
FROM pending_insert_rows pir
-- 逐行判断是否已存在
WHERE NOT EXISTS (
    SELECT 1
    FROM sales.promotions sp
    -- 这里替换成你实际判定重复的唯一条件,多字段联合唯一就加多个等值判断
    WHERE sp.promotion_name = pir.promotion_name
);

方案2:低版本兼容写法(适用于不支持CTE的旧版数据库,比如MySQL 5.x)

用UNION ALL把多行值拼接成派生表,实现和CTE一样的效果:

INSERT INTO sales.promotions (promotion_name, discount, start_date, expired_date)
SELECT  pir.promotion_name,
        pir.discount,
        pir.start_date,
        pir.expired_date
FROM (
    SELECT '2019 Summer Promotion' AS promotion_name, 0.15 AS discount, '20190601' AS start_date, '20190901' AS expired_date
    UNION ALL
    SELECT '2019 Fall Promotion', 0.20, '20191001', '20191101'
    UNION ALL
    SELECT '2019 Winter Promotion', 0.25, '20191201', '20200101'
) pir
WHERE NOT EXISTS (
    SELECT 1
    FROM sales.promotions sp
    WHERE sp.promotion_name = pir.promotion_name
);

注意事项

  • 重复判定条件必须和业务唯一规则对齐:如果业务上要求活动名+开始时间联合唯一,就把NOT EXISTS里的条件改成sp.promotion_name = pir.promotion_name AND sp.start_date = pir.start_date,不要只写单个字段导致漏判。
  • 高并发写入场景下,必须给判定重复的字段建唯一索引做兜底:NOT EXISTS的校验是查询时的快照判断,并发写入时可能出现两个事务同时查到不存在、都插入成功的竞态问题,唯一索引能从数据库层阻止重复数据写入。
  • 如果你用的数据库支持原生Upsert语法(比如MySQL的INSERT ... ON DUPLICATE KEY UPDATE、PostgreSQL的INSERT ... ON CONFLICT DO NOTHING),也可以直接用对应语法实现相同效果,性能通常更好,但上面的写法是跨数据库通用的标准SQL,不需要依赖数据库特有关键字。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 10:15:30