MYSQL插入处理重复键值的几种方法

本文介绍了MySQL中处理插入重复值的三种方法:REPLACE INTO、INSERT INTO ON DUPLICATE KEY UPDATE和IGNORE INTO,并通过实例展示了每种方法的具体应用。
当unique列在一个UNIQUE键上插入包含重复值的记录时,默认insert的时候会报1062错误,MYSQL有三种不同的处理方法,下面我们分别介绍。

先建立2个测试表,在id列上创建unique约束。
mysql> create table test1(id int,name varchar(5),type int,primary key(id));
Query OK, 0 rows affected (0.01 sec)

mysql> create table test2(id int,name varchar(5),type int,primary key(id));
Query OK, 0 rows affected (0.01 sec)


mysql> select * from test1;
+-----+------+------+
| id  | name | type |
+-----+------+------+
| 101 | aaa  |    1 | 
| 102 | bbb  |    2 | 
| 103 | ccc  |    3 | 
+-----+------+------+
3 rows in set (0.00 sec)

mysql> select * from test2;
+-----+------+------+
| id  | name | type |
+-----+------+------+
| 201 | aaa  |    1 | 
| 202 | bbb  |    2 | 
| 203 | ccc  |    3 | 
| 101 | xxx  |    5 | 
+-----+------+------+
4 rows in set (0.00 sec)

1、REPLACE INTO
发现重复的先删除再插入,如果记录有多个字段,在插入的时候如果有的字段没有赋值,那么新插入的记录这些字段为空。
mysql> replace into test1(id,name)(select id,name from test2);
Query OK, 5 rows affected (0.04 sec)
Records: 4  Duplicates: 1  Warnings: 0

mysql> select * from test1;
+-----+------+------+
| id  | name | type |
+-----+------+------+
| 101 | xxx  | NULL | 
| 102 | bbb  |    2 | 
| 103 | ccc  |    3 | 
| 201 | aaa  | NULL | 
| 202 | bbb  | NULL | 
| 203 | ccc  | NULL | 
+-----+------+------+
6 rows in set (0.00 sec)

需要注意的是,当你replace的时候,如果被插入的表如果没有指定列,会用NULL表示,而不是这个表原来的内容。如果插入的内容列和被插入的表列一样,则不会出现NULL。例如
mysql> replace into test1(id,name,type)(select id,name,type from test2);
Query OK, 8 rows affected (0.04 sec)
Records: 4  Duplicates: 4  Warnings: 0

mysql> select * from test1;
+-----+------+------+
| id  | name | type |
+-----+------+------+
| 101 | xxx  |    5 | 
| 102 | bbb  |    2 | 
| 103 | ccc  |    3 | 
| 201 | aaa  |    1 | 
| 202 | bbb  |    2 | 
| 203 | ccc  |    3 | 
+-----+------+------+
6 rows in set (0.00 sec)

如果INSERT的时候,需要保留被插入表的列,只更新指定列,那么就可以使用第二种方法。

2、INSERT INTO ON DUPLICATE KEY UPDATE
发现重复的是更新操作。在原有记录基础上,更新指定字段内容,其它字段内容保留。例如我只想插入test2表的id,name字段,但是要保留test1表的type字段:
mysql> insert into test1(id,name,type)(select id,name,type from test2) on DUPLICATE KEY UPDATE test1.name=test2.name;
Query OK, 5 rows affected (0.04 sec)
Records: 4  Duplicates: 1  Warnings: 0

mysql> select * from test1;
+-----+------+------+
| id  | name | type |
+-----+------+------+
| 101 | xxx  |    1 | 
| 102 | bbb  |    2 | 
| 103 | ccc  |    3 | 
| 203 | ccc  |    3 | 
| 202 | bbb  |    2 | 
| 201 | aaa  |    1 | 
+-----+------+------+
6 rows in set (0.00 sec)

如果INSERT的时候,只想插入原表没有的数据,那么可以使用第三种方法。

3、IGNORE INTO
判断是否存在,存在不插入,否则插入。很容易理解,当插入的时候,违反唯一性约束,MySQL不会尝试去执行这条语句。例如:
mysql> insert ignore into test1(id,name,type)(select id,name,type from test2);
Query OK, 3 rows affected (0.01 sec)
Records: 4  Duplicates: 1  Warnings: 0

mysql> select * from test1;
+-----+------+------+
| id  | name | type |
+-----+------+------+
| 101 | aaa  |    1 | 
| 102 | bbb  |    2 | 
| 103 | ccc  |    3 | 
| 203 | ccc  |    3 | 
| 202 | bbb  |    2 | 
| 201 | aaa  |    1 | 
+-----+------+------+

6 rows in set (0.00 sec)


### MySQL 批量插入 UUID 重复问题的解决方案 在处理 MySQL 数据库批量插入操作时,如果使用 `REPLACE(UUID(), '-', '')` 方法生成主键值,则可能会遇到主冲突的情况。这是因为 `UUID()` 函数在某些场景下可能只被调用一次,从而导致生成的 UUID 值相同[^5]。 以下是几种可行的解决方案: #### 方案一:使用 MD5 或 SHA1 替代 UUID 可以改用更短且唯一的字符串来替代原始的 UUID。通过组合 `MD5()` 和 `UUID()` 函数,能够生成一个固定长度为 32 的十六进制字符串,这不仅解决了 `-` 符号的问题,还减少了存储空间的需求。 ```sql INSERT INTO target_table (id, column1, column2) SELECT MD5(UUID()), source_column1, source_column2 FROM source_table; ``` 此方法利用了 `MD5()` 对唯一性的增强特性,有效避免了因 UUID 不变而导致的主冲突问题[^2]。 #### 方案二:调整 SQL 模式以支持每次独立计算 UUID 确认当前会话或全局变量是否启用了仅缓存单次函数结果的行为。可以通过以下命令验证并更改配置项: ```sql SET SESSION sql_mode = 'ANSI'; SHOW VARIABLES LIKE '%sql_mode%'; ``` 上述设置可确保每条记录单独触发 `UUID()` 计算逻辑而非共享同一个返回值。不过需要注意的是不同版本间可能存在行为差异,因此建议测试后再部署到生产环境[^1]。 #### 方案三:采用自定义序列代替 UUID 对于频繁写入需求较高的业务场景来说,依赖随机数或者哈希算法未必是最优解法。此时引入递增型整数列作为主或许更为合适。创建前缀索引配合 AUTO_INCREMENT 属性即可实现高效分配机制而无需担心碰撞风险。 ```sql CREATE TABLE example ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, ... ); ``` 尽管这种方法丧失了一定程度上的分布式能力(即跨多个实例同步),但对于单一节点而言却是简单可靠的选择之一[^4]。 #### 性能考量与扩展性分析 无论采取何种策略都需要权衡其利弊之处。例如基于散列的方法虽然提供了较好的分布均匀度却增加了额外运算开销;而单纯依靠自动增长字段则面临分片后的重新映射难题。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值