MySQL区分e和é(急性) - UNIQUE索引

时间:2011-06-24 11:09:46

标签: mysql character-encoding indexing constraints

我有一个表students,有3列:idnameage。 我在列UNIQUEIndex_2上有一个name索引age

CREATE TABLE `bedrock`.`students` (  
    `id` INTEGER UNSIGNED NOT NULL
    AUTO_INCREMENT,   `name` VARCHAR(45)
    NOT NULL,   `age` INTEGER UNSIGNED NOT
    NULL,   PRIMARY KEY (`id`),   UNIQUE
    INDEX `Index_2` USING BTREE(`name`,
    `age`) ) ENGINE = InnoDB;

我尝试了这个插入选项:

insert into students (id, name, age)
values (1, 'Ane', 23);

哪作得好。比我尝试过这个(见Ané - 急性):

insert into students (id, name, age)
values (2, 'Ané', 23);

我收到此错误消息:

"Duplicate entry 'Ané-23' for key 'Index_2'"

MySQL以某种方式不区分“Ane”和“Ané”。我如何解决这个问题以及为什么会这样?

桌上学生的charset是“utf8”,校对是“utf8_general_ci”。

ALTER TABLE `students` CHARACTER SET utf8 COLLATE utf8_general_ci;

稍后编辑1:@Crozin:

我已经改为使用collat​​ion utf8_bin:

ALTER TABLE `students`
CHARACTER SET utf8 COLLATE utf8_bin;

但我收到同样的错误。

但是如果我从charset utf8和collat​​ion utf8_bin开始创建表,就像这样:

CREATE TABLE `students2` ( 
`id` INTEGER UNSIGNED AUTO_INCREMENT, 
`name` VARCHAR(45),   `age`
VARCHAR(45),   PRIMARY KEY (`id`),  
UNIQUE INDEX `Index_2` USING
BTREE(`name`, `age`) ) ENGINE = InnoDB
CHARACTER SET utf8 COLLATE utf8_bin;

以下两个插入命令都可以正常工作:

insert into students2 (id, name, age)
values (1, 'Ane', 23); // works ok

insert into students2 (id, name, age)
values (2, 'Ané', 23); // works ok

这似乎很奇怪。

稍后编辑2:

我在这里看到了另一个答案。我不确定用户是否已删除或丢失。 我只是测试它:

用户写道,他首先创建了3个包含3个不同字符集的表:

CREATE TABLE `utf8_bin` (   `id`
int(10) unsigned NOT NULL
AUTO_INCREMENT,   `name` varchar(45)
COLLATE utf8_bin NOT NULL,   `age`
int(10) unsigned NOT NULL,   PRIMARY
KEY (`id`),   UNIQUE KEY `Index_2`
(`name`,`age`) USING BTREE )
ENGINE=InnoDB DEFAULT CHARSET=utf8
COLLATE=utf8_bin;

CREATE TABLE `utf8_unicode_ci` (  
`id` int(10) unsigned NOT NULL
AUTO_INCREMENT,   `name` varchar(45)
COLLATE utf8_unicode_ci NOT NULL,  
`age` int(10) unsigned NOT NULL,  
PRIMARY KEY (`id`),   UNIQUE KEY
`Index_2` (`name`,`age`) USING BTREE )
ENGINE=InnoDB DEFAULT CHARSET=utf8
COLLATE=utf8_unicode_ci;

CREATE TABLE `utf8_general_ci` (  
`id` int(10) unsigned NOT NULL
AUTO_INCREMENT,   `name` varchar(45)
COLLATE utf8_general_ci NOT NULL,  
`age` int(10) unsigned NOT NULL,  
PRIMARY KEY (`id`),   UNIQUE KEY
`Index_2` (`name`,`age`) USING BTREE )
ENGINE=InnoDB DEFAULT CHARSET=utf8
COLLATE=utf8_general_ci;

用户的结果是:

Insert commands: INSERT INTO utf8_bin
VALUES (1, 'Ane', 23), (2, 'Ané', 23);
Query OK, 2 rows affected (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 0

INSERT INTO utf8_unicode_ci VALUES (1,
'Ane', 23), (2, 'Ané', 23); Query OK,
2 rows affected (0.01 sec) Records: 2 
Duplicates: 0  Warnings: 0

INSERT INTO utf8_general_ci VALUES (1,
'Ane', 23), (2, 'Ané', 23); Query OK,
2 rows affected (0.01 sec) Records: 2 
Duplicates: 0  Warnings: 0

以下是我的结果:

INSERT INTO utf8_bin VALUES (1, 'Ane',
23), (2, 'Ané', 23);        //works ok
INSERT INTO utf8_unicode_ci VALUES (1,
'Ane', 23), (2, 'Ané', 23); //
Duplicate entry 'Ané-23' for key
'Index_2'

INSERT INTO utf8_general_ci VALUES (1,
'Ane', 23), (2, 'Ané', 23);
//Duplicate entry 'Ané-23' for key
'Index_2'

我不确定为什么这个INSERT命令有效并且对我来说不起作用。

他还写道,他在Linux上的Mysql上测试了这个 - 必须对此做些什么?!即使我不这么认为。

4 个答案:

答案 0 :(得分:14)

  

和整理是“utf8_general_ci”。

这就是答案。如果你正在使用utf8_general_ci(实际上它适用于所有utf_..._[ci|cs])整理,那么变音符号会被旁路,因此:

SELECT "e" = "é" AND "O" = "Ó" AND "ä" = "a"

1中的结果。索引也使用整理。

如果您想区分ąa,请使用utf8_bin排序规则(请记住它也区分大写和小写字符)。


顺便说一句,姓名和年龄不保证任何独特性。

答案 1 :(得分:5)

我找到了

ALTER TABLE students CHARACTER SET utf8 COLLATE utf8_bin;

对我来说不起作用,因为它没有更改现有列的排序规则,这可以在此查询的结果中看到:

SHOW FULL COLUMNS from students;

但是,以下查询执行了该作业并将现有列转换为utf8_bin collat​​ion:

ALTER TABLE students CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

(注意“CONVERT TO”)

答案 2 :(得分:2)

将归类更改为latin1_german2_ci

结帐collation effects

答案 3 :(得分:2)

我知道这个问题现在有些陈旧,但我要做的就是删除我桌子上的主键并使用常规索引。似乎MySQL不尊重utf8_bin在主键中的排序规则。我正在使用MySQL 5.5。