最直接有效的方式是在数据库层面添加唯一约束,它强制列或列组合值不重复,由数据库自动校验,比应用层判断更可靠安全。

防止SQL中出现重复数据,最直接有效的方式是在数据库层面添加唯一约束(UNIQUE Constraint),它能强制列或列组合的值不重复,由数据库自动校验,比应用层判断更可靠、更安全。
什么时候该加唯一约束
以下场景建议优先使用唯一约束:
- 用户表中的手机号、邮箱字段——每个用户必须唯一
- 订单表中的外部交易号(如微信pay_no)——避免同一笔支付被重复插入
- 配置表中的code字段——确保配置项标识不冲突
- 联合唯一:如“用户ID + 商品ID”组合,限制一个用户对同一商品只能有一条收藏记录
怎么加唯一约束(以MySQL为例)
建表时定义:
CREATE TABLE users ( id INT PRIMARY KEY, email VARCHAR(255), phone VARCHAR(20), UNIQUE(email), UNIQUE(phone) );
已有表添加约束:
ALTER TABLE users ADD CONSTRAINT uk_users_email UNIQUE(email); ALTER TABLE orders ADD CONSTRAINT uk_orders_trade_no UNIQUE(external_trade_no);
联合唯一约束写法:
ALTER TABLE favorites ADD CONSTRAINT uk_user_item UNIQUE(user_id, item_id);
唯一约束 vs 主键 vs 唯一索引
三者都保证唯一性,但有关键区别:
- 主键(PRIMARY KEY):自动非空(NOT NULL)+ 唯一,每张表只能有一个
- 唯一约束(UNIQUE):允许NULL(多数数据库中,多个NULL不算重复),可有多个
- 唯一索引(UNIQUE INDEX):功能和唯一约束几乎等价,约束本质就是通过唯一索引实现的;部分场景(如函数索引、前缀索引)只能用唯一索引实现
插入重复数据时怎么办
违反唯一约束会报错(如MySQL报错代码1062),应用需合理处理:
- 捕获异常,提示“该邮箱已被注册”等友好信息
- 用 INSERT IGNORE 忽略错误(MySQL),不报错也不插入
- 用 ON DUPLICATE KEY UPDATE 实现“存在则更新”,适合幂等写入
- 用 MERGE(SQL Server/Oracle)或 UPSERT(PostgreSQL)做合并操作
不复杂但容易忽略:唯一约束要覆盖真正业务意义上的“不可重复维度”,比如只给单个字段加约束,却忘了多字段组合才是实际唯一条件。设计时多问一句:“什么才算一条重复记录?”










