如何防止SQL表主键重复_通过触发器实现逻辑ID分配

张开发
2026/4/7 3:20:59 15 分钟阅读

分享文章

如何防止SQL表主键重复_通过触发器实现逻辑ID分配
主键重复时触发器无法阻止报错因主键约束在校验阶段早于触发器执行逻辑ID应存入独立字段避免干扰自增主键PostgreSQL触发器必须显式RETURN NEWMySQL则无需并发下逻辑ID生成需防重复推荐应用层ID生成数据库落库。主键重复时触发器根本拦不住 INSERT 报错触发器无法阻止主键冲突报错因为 PRIMARY KEY 约束在触发器执行前就已校验。哪怕你在 BEFORE INSERT 里改了 id只要原始语句带了冲突值比如显式插入 id 100MySQL/PostgreSQL 会在触发器前直接抛出 ERROR 1062 (23000): Duplicate entry 100 for key PRIMARY。实操建议所有 INSERT 必须省略主键字段让数据库自动生成或统一走存储过程封装触发器只用于「生成逻辑ID」场景如业务编号 ORD202405200001不能替代主键约束本身若必须显式指定主键得先 SELECT ... FOR UPDATE 查重加锁再 INSERT触发器此时已无意义用 BEFORE INSERT 触发器生成逻辑ID要避开自增冲突常见错误是表设了 AUTO_INCREMENT 主键又在触发器里手动赋值 NEW.id结果下次 INSERT 用默认值时自增值跳变、甚至报错。使用场景需要同时保留数字主键用于关联、排序和可读逻辑ID存入 logic_id 字段。实操建议主键仍用 INT AUTO_INCREMENT另加一个 VARCHAR 字段存逻辑ID如 order_no触发器只写 NEW.order_no : CONCAT(ORD, DATE_FORMAT(NOW(), %Y%m%d), LPAD(next_seq : next_seq 1, 4, 0));别碰 NEW.id —— 让自增机制自己管注意MySQL 中 next_seq 是会话级变量高并发下需用 SELECT MAX(...) 1 FROM ... FOR UPDATE 替代PostgreSQL 的 BEFORE INSERT 触发器必须返回 NEW现象触发器函数写了但逻辑ID没生效查表发现还是 NULL 或默认值。原因是函数末尾漏了 RETURN NEW;。 跃问 跃问是由阶跃星辰开发的免费AI智能问答助手随时帮你智能搜索、高效阅读、识图理解、和你畅聊感兴趣的话题。

更多文章