2011-06-24 75 views
16

Tôi có một bảng, students, với 3 cột: id, nameage. Tôi có một chỉ số UNIQUEIndex_2 trên các cột nameage.Phân biệt MySQL giữa e và é (e cấp tính) - Chỉ số UNIQUE

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; 

tôi đã cố gắng lựa chọn chèn này:

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

mà hoạt động ok. Hơn tôi đã thử cái này (xem Ane - e cấp):

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

và tôi nhận được thông báo lỗi này:

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

MySQL bằng cách nào đó không thực hiện bất kỳ sự phân biệt giữa "Ane "và" Ané ". Làm thế nào tôi có thể giải quyết điều này và tại sao điều này đang xảy ra?

Bộ ký tự cho học sinh bảng là "utf8" và đối chiếu là "utf8_general_ci".

ALTER TABLE `students` CHARACTER SET utf8 COLLATE utf8_general_ci; 

Sau edit1: @Crozin:

Tôi đã thay đổi để sử dụng đối chiếu utf8_bin:

ALTER TABLE `students` 
CHARACTER SET utf8 COLLATE utf8_bin; 

nhưng tôi nhận được lỗi tương tự.

Nhưng nếu tôi có thể tạo bàn từ đầu với utf8 charset và collation utf8_bin, như thế này:

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; 

cả dưới lệnh chèn làm việc ok:

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

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

này có vẻ là rất lạ.

Sau đó chỉnh sửa 2:

Tôi thấy câu trả lời khác ở đây. Tôi không chắc chắn nếu người dùng bị xóa hoặc bị mất. Tôi chỉ thử nghiệm nó:

Người dùng đã viết rằng đầu tiên ông đã tạo ra 3 bảng với 3 bảng mã khác nhau:

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; 

Kết quả của việc sử dụng bao gồm:

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 

Dưới đây là kết quả của tôi :

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' 

Tôi không chắc chắn lý do tại sao phần này làLệnhhoạt động và tôi không hoạt động.

Ông cũng viết rằng ông đã thử nghiệm điều này trên Mysql trên Linux - phải làm gì đó với điều này ?! Ngay cả tôi cũng không nghĩ vậy.

+0

Không liên quan đến câu hỏi của bạn, nhưng không bao giờ có ý tưởng hay để có khóa duy nhất trên trường tên ... Nhiều người có cùng tên. Bạn dự định làm gì trong trường hợp đó? Điều đó nói rằng, thực tế bạn đã tạo ra một chìa khóa duy nhất dựa trên tên và tuổi sẽ đề nghị một quyết định thiết kế ..... –

+0

Hi Brendan, đây chỉ là một ví dụ, một hư cấu - không giống như tôi có trong dự án Tôi làm! Tôi biết không phải là ok để có một chỉ số duy nhất trên các cột như 'tên' và 'tuổi'. Tôi đã chọn ví dụ này (không phải là một người rất thông minh - tôi quản trị) thay vì chọn ví dụ thực có chứa hơn 10 cột .... – Paul

+0

Điều đó có ý nghĩa. –

Trả lời

12

và collation là "utf8_general_ci".

Và đó là câu trả lời. Nếu bạn đang sử dụng utf8_general_ci (trên thực tế nó áp dụng cho tất cả các utf_..._[ci|cs]) đối chiếu sau đó bỏ dấu được bỏ qua trong comarison, như sau:

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

Kết quả trong 1. Các chỉ số cũng sử dụng đối chiếu.

Nếu bạn muốn phân biệt giữa ąa thì sử dụng collation utf8_bin (hãy nhớ rằng nó cũng phân biệt giữa chữ hoa và chữ thường).


Bằng cách này tên và tuổi không đảm bảo tính duy nhất.

+0

Tôi đã trả lời câu trả lời của bạn bằng cách cập nhật câu hỏi - không có đủ không gian ở đây. Tôi cũng đã thêm phần "Chỉnh sửa sau 2". – Paul

+0

liên quan đến "tên và tuổi tác không đảm bảo bất kỳ sự độc đáo nào", vui lòng xem nhận xét thứ hai của tôi về câu hỏi này - như một phản hồi với Brendan. – Paul

+0

sử dụng collation 'utf_8 bin' hoạt động tốt - vấn đề duy nhất mà tôi có là phân biệt chữ hoa chữ thường và tôi muốn phân biệt chữ hoa chữ thường - bạn có biết giải pháp cho điều này không? Cảm ơn. – Paul

2

Thay đổi collation để latin1_german2_ci

thanh toán collation effects

+0

Downvote: 'utf8_unicode_ci' sẽ gây ra lỗi rất giống nhau. – Crozin

+0

@Shakti Singh: Sử dụng đối chiếu dựa trên latin trên mã hóa Unicode có thể giải quyết được vấn đề trong trường hợp cụ thể này nhưng nó dẫn đến hàng tá vấn đề mới. – Crozin

+0

@Shakti Singh: Tôi vẫn coi đây là câu trả lời sai. – Crozin

2

Tôi biết câu hỏi này hơi cũ, nhưng những gì tôi phải làm là xóa khóa chính trên bảng của tôi và sử dụng chỉ mục thông thường thay thế. Có vẻ như MySQL không tôn trọng sự đối chiếu của utf8_bin trong các khóa chính. Tôi đang sử dụng MySQL 5.5.

4

tôi thấy rằng

ALTER TABLE students CHARACTER SET utf8 COLLATE utf8_bin; 

không làm việc cho tôi, vì nó không thay đổi collation của cột hiện có, như có thể thấy trong các kết quả của truy vấn này:

SHOW FULL COLUMNS from students; 

Tuy nhiên, truy vấn sau đã thực hiện công việc và chuyển đổi các cột hiện tại thành utf8_bin collation:

ALTER TABLE students CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; 

(noti ce "CONVERT TO")

Các vấn đề liên quan