【问题标题】:MySQL `INSERT INTO SELECT` clause generate Duplicate entry error on unique fieldMySQL `INSERT INTO SELECT` 子句在唯一字段上生成重复输入错误
【发布时间】:2016-12-15 02:27:08
【问题描述】:

我使用INSERT INTO SELECT跨数据库迁移用户数据,但它生成

Duplicate entry '                   ' for key 'users_name_unique'

虽然数据源是另一个唯一索引并且不应包含任何重复数据。('users_name_unique' 是 db2.users 上的索引名称)

这是查询,其中 db2.users 中的 name 字段是 varchar(50) 唯一且非空索引,而 db1.users 中的 name 字段是 varchar(60) 唯一且非空索引。我已经检查了每条记录的字段长度,长度都比50小很多。

INSERT INTO db2.users (name, email, uid) SELECT
    name,
    IF (mail = '', NULL, mail) AS email,
    uid
FROM
    db1.users;

db1.users 的名称字段中有不可打印的空格或空格。

可能是什么问题?

更新

我创建了多个测试表,如下所示,有两个表结构非常相似,没有数据(我故意更改了长度,因为源数据是 varchar(60)),但结果不同。

    mysql> desc ttt3;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(50) | NO   | UNI | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

mysql> desc users;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(60)      | NO   | UNI | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

mysql> show index from ttt3;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| ttt3  |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| ttt3  |          0 | name     |            1 | name        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

mysql> show index from users;
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name          | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| users |          0 | PRIMARY           |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| users |          0 | users_name_unique |            1 | name        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

mysql> insert into ttt3(name) select name from scratch.users where scratch.users.uid != 0;
Query OK, 1556 rows affected (0.24 sec)
Records: 1556  Duplicates: 0  Warnings: 0

mysql> insert into users(name) select name from scratch.users where scratch.users.uid != 0;
ERROR 1062 (23000): Duplicate entry '                   ' for key 'users_name_unique'

更新

原来目标字段的排序规则设置为“utf8_unicode_ci”,而原始字段为“utf8_general_ci”,更改此选项即可解决问题。

【问题讨论】:

  • 我想说要么你的假设是错误的(源查询确实返回了欺骗,这应该很容易验证),要么目标表已经有一些值。
  • @ÁlvaroGonzález 我已经删除了 db2.users 中的所有数据来进行测试。
  • 在 Oracle 中,有时您也需要手动删除由于约束而创建的索引。删除表不会删除索引。该索引保持原样,并且由于其独特的性质,阻止了进一步的进入。 mysql中有这样的概念吗? dba.stackexchange.com/questions/136643/…
  • @ÁlvaroGonzález 我不认为具有唯一索引的字段中可能存在任何重复数据,但我确实将源字段从 utf8 转换为 utf8_mb4 然后将其转换回来,如果这意味着什么。
  • @Serg 原来目标字段的排序规则设置为'utf8_unicode_ci',更改此选项即可解决问题。谢谢!

标签: mysql sql database


【解决方案1】:

原因如下:

目标字段的排序规则设置为“utf8_unicode_ci”(laravel 的默认排序规则),原始字段为“utf8_general_ci”。

这些排序规则有不同的“排序”或“相等”规则。更改此选项可解决问题。

【讨论】:

    猜你喜欢
    • 2012-06-20
    • 2010-10-28
    • 2011-12-04
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 2018-12-27
    • 1970-01-01
    相关资源
    最近更新 更多