Trường hợp MySQL chọn không nhạy


242

Bất cứ ai có thể cho tôi biết nếu một SELECTtruy vấn MySQL là trường hợp nhạy cảm hoặc trường hợp không nhạy cảm theo mặc định? Và nếu không, tôi sẽ phải gửi truy vấn nào để tôi có thể làm một cái gì đó như:

SELECT * FROM `table` WHERE `Value` = "iaresavage"

Trong thực tế, giá trị thực sự ValueIAreSavage.


44
Cuối cùng, nó phụ thuộc vào đối chiếu được nộp - nếu đó là '_ci' (không phân biệt chữ hoa chữ thường) hoặc '_cs' (phân biệt chữ hoa chữ thường)
Jovan Perovic

15
Đây là một câu hỏi kém;). Một nửa câu trả lời cho bạn thấy làm thế nào để so sánh trường hợp không nhạy cảm, một nửa đang nhắm đến trường hợp nhạy cảm. Và chỉ có 1 cho bạn biết rằng mặc định trong thực tế không nhạy cảm. :) Đáng lưu ý rằng tính không nhạy cảm của trường hợp hoạt động ngay cả khi bạn thực hiện một so sánh như'value' in ('val1', 'val2', 'val3')
SaltyNuts 16/12/13

5
@SaltyNuts người đàn ông, đọc câu hỏi này 7 năm sau và nhận ra tôi đã xấu hổ đến mức nào! Tôi có thể vừa đọc tài liệu và câu trả lời giống như câu đầu tiên về các câu lệnh CHỌN ...
NoodleOfDeath

Để thêm vào những gì @JovanPerovic đã nói, utf8_bin cũng làm cho nó trở nên nhạy cảm. Không chắc chắn nếu điều đó tồn tại trước đó
Chiwda

Câu trả lời:


494

Chúng không phân biệt chữ hoa chữ thường , trừ khi bạn thực hiện so sánh nhị phân .


3
Tôi hầu như đồng ý với nhận xét của Tim, tôi không nghĩ việc thực hiện "thấp hơn ()" đối với các giá trị của bạn ở mọi nơi là cách tốt nhất để xử lý nó, có vẻ như là một cách giải quyết. Nhưng tôi thừa nhận nó đôi khi nó có ý nghĩa và dễ dàng hơn. (Colin đã đề cập đến đối chiếu là tốt hơn) Chúng tôi đã chuyển dữ liệu lịch sử vào bảng mysql đã phá vỡ logic kế thừa do các giá trị cột nhất định có trường hợp không nhạy cảm. Chúng tôi cần biết sự khác biệt giữa "GE1234" và "ge1234", chúng cần phải là duy nhất và được ghi lại theo cách đó. Thay vào đó, chúng tôi đặt cột của chúng tôi trong bảng tạo bảng theo cách này: varchar (20) CHARACTER SET utf8 COLLATE utf8_bin
gregthegeek

19
Tôi không biết tại sao rất nhiều người bỏ phiếu này. Nó nêu rõ ở đây dev.mysql.com/doc/refman/5.0/en/case-sens nhạy.html rằng "... điều này có nghĩa là đối với các ký tự chữ cái, các phép so sánh sẽ phân biệt chữ hoa chữ thường." Vì vậy, nếu tôi tìm kiếm 'DickSavagewood', nó sẽ KHÔNG nhặt được 'khúc gỗ'. Làm tương tự với LOWER () S pick nhặt nó lên. Vì vậy, câu trả lời của tôi cho câu hỏi: trong trường hợp cụ thể của bạn, CHỌN thực sự nhạy cảm với trường hợp.
Luftwaff

10
@ user1961753: Đọc lại: "Đối với các chuỗi nhị phân (varbinary, blob) ... sẽ phân biệt chữ hoa chữ thường".
Marc B

1
@MarcB liên kết này hiện đã bị hỏng. Bạn có thể sửa nó không? :)
Phiên bản

5
Như Jovan đã nói, nó phụ thuộc vào sự đối chiếu, vì vậy câu trả lời này là khá nhiều sai.
phil294

117

Bạn có thể viết thường giá trị và tham số đã truyền:

SELECT * FROM `table` WHERE LOWER(`Value`) = LOWER("IAreSavage")

Một cách khác (tốt hơn) sẽ là sử dụng COLLATEtoán tử như đã nói trong tài liệu


21
Làm thế nào SELECTtuyên bố này sẽ sử dụng COLLATEsau đó?
Có Barry

11
Nó nói, trên trang tài liệu được đề cập ở trên, "so sánh chuỗi không phân biệt là không phân biệt chữ hoa chữ thường".
Per Quested Aronsson

9
Thật đáng sợ khi có bao nhiêu người ủng hộ câu trả lời này. Như @Marc giải thích ở trên, so sánh case-insensitive. Bạn cần hiểu các đối chiếu và chỉ mục và định cấu hình chúng một cách chính xác - sử dụng các phép biến đổi chuỗi như LOWER()hoặc một COLLATEmệnh đề tùy ý hoàn toàn có thể bỏ qua một chỉ mục và theo thời gian, khi bảng của bạn phát triển, điều này có thể có ý nghĩa hiệu suất mạnh mẽ. Có khả năng đây là những tên người dùng bạn đang tìm kiếm? Sử dụng đối chiếu không phân biệt chữ hoa chữ thường và thêm một chỉ mục duy nhất vào cột. Sử dụng EXPLAINđể xác nhận rằng chỉ mục đang được sử dụng.
mindplay.dk

1
Tôi đã định nói giống như mindplay.dk ... trên () và dưới () bỏ qua chỉ mục và ảnh hưởng trực tiếp đến hiệu suất trên các bảng cơ sở dữ liệu lớn.
GTodorov

Tôi đồng ý cả ý kiến ​​của mindplay.dk và GTodorov. Hãy cẩn thận bằng cách sử dụng một số phương pháp trên một cột mục tiêu trong mệnh đề where. Chỉ số của cột có thể là vô dụng. Sử dụng GIẢI THÍCH!
kẻ phản bội

51

SỬ DỤNG SỐ TIỀN

Đây là một lựa chọn đơn giản

SELECT * FROM myTable WHERE 'something' = 'Something'

= 1

Đây là một lựa chọn với nhị phân

SELECT * FROM myTable WHERE BINARY 'something' = 'Something'

hoặc là

SELECT * FROM myTable WHERE 'something' = BINARY 'Something'

= 0


3
Khi nào thì có ý nghĩa khi chỉ sử dụng BINary trên một mặt của = (CHỌN * TỪ myTable Ở đâu BINary 'cái gì đó' = 'Cái gì đó')?
Jimmy

@Jimmy Ý bạn là gì? Các mã hoạt động. Khi một bên trong so sánh được chuyển thành nhị phân, việc so sánh được thực hiện nhị phân.
Jori

@Jori Ồ, tôi đoán là tôi đã đọc sai - Tôi nghĩ một trong hai ví dụ có BINary ở cả hai phía bằng nhau.
Jimmy

Tôi chỉ bình chọn điều này bởi vì đây thực sự là câu trả lời đúng. Theo tài liệu tại trang web MySQL, họ nói rằng sử dụng lệnh BINARY tốt hơn là cố gắng đánh máy các từ / yêu cầu của bạn sang một ngôn ngữ cụ thể vì lệnh BINARY nói để lại mọi thứ giống như vậy và sử dụng chính xác như nó được trình bày Vì vậy, khi tôi đi tìm câu trả lời - hai câu trả lời ở đây đã dẫn tôi đến trang web MySQL và xem tài liệu của họ. Sử dụng BINary là tốt hơn. Dịch có thể gây ra vấn đề khác.
Đánh dấu Manning

43

So sánh là trường hợp nhạy cảm khi cột dùng một collation kết thúc với _ci(chẳng hạn như mặc định latin1_general_ci đối chiếu) và họ là trường hợp nhạy cảm khi cột dùng một collation mà kết thúc bằng _cshoặc _bin(như utf8_unicode_csutf8_bincollations).

Kiểm tra đối chiếu

Bạn có thể kiểm tra máy chủ , cơ sở dữ liệu và đối chiếu kết nối bằng cách sử dụng:

mysql> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+

và bạn có thể kiểm tra đối chiếu bảng của mình bằng cách sử dụng:

mysql> SELECT table_schema, table_name, table_collation 
       FROM information_schema.tables WHERE table_name = `mytable`;
+----------------------+------------+-------------------+
| table_schema         | table_name | table_collation   |
+----------------------+------------+-------------------+
| myschema             | mytable    | latin1_swedish_ci |

Thay đổi đối chiếu

Bạn có thể thay đổi cơ sở dữ liệu, bảng hoặc đối chiếu cột của mình thành một trường hợp nhạy cảm như sau:

-- Change database collation
ALTER DATABASE `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;

-- or change table collation
ALTER TABLE `table` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- or change column collation
ALTER TABLE `table` CHANGE `Value` 
    `Value` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;

So sánh của bạn bây giờ nên phân biệt chữ hoa chữ thường.


25

So sánh chuỗi trong cụm từ WHERE không phân biệt chữ hoa chữ thường. Bạn có thể thử so sánh bằng

WHERE `colname` = 'keyword'

hoặc là

WHERE `colname` = 'KeyWord'

và bạn sẽ nhận được kết quả tương tự . Đó là hành vi mặc định của MySQL.

Nếu bạn muốn so sánh phân biệt chữ hoa chữ thường , bạn có thể thêm COLLATEnhư thế này:

WHERE `colname` COLLATE latin1_general_cs = 'KeyWord'

SQL đó sẽ cho kết quả khác với cái này: WHERE colnameCOLLATE latin1_general_cs = 'keyword'

latin1_general_cs là đối chiếu phổ biến hoặc mặc định trong hầu hết các cơ sở dữ liệu.


16

Đối chiếu bạn chọn đặt cho dù bạn có phân biệt chữ hoa chữ thường hay không.


9

Mặc định là không phân biệt chữ hoa chữ thường, nhưng điều quan trọng nhất tiếp theo bạn nên xem là cách bảng được tạo ở vị trí đầu tiên, bởi vì bạn có thể chỉ định độ nhạy trường hợp khi bạn tạo bảng.

Kịch bản dưới đây tạo ra một bảng. Chú ý ở phía dưới có ghi "THU THẬP Latin1_general_cs". Mà cs ở cuối có nghĩa là trường hợp nhạy cảm. Nếu bạn muốn bảng của mình không phân biệt chữ hoa chữ thường, bạn sẽ bỏ phần đó ra hoặc sử dụng "COLLATE latin1_general_ci".

   CREATE Table PEOPLE (

       USER_ID  INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,

       FIRST_NAME  VARCHAR(50) NOT NULL,
       LAST_NAME  VARCHAR(50) NOT NULL,

       PRIMARY KEY (USER_ID)

   )

   ENGINE=MyISAM DEFAULT CHARACTER SET latin1
    COLLATE latin1_general_cs AUTO_INCREMENT=0;

Nếu dự án của bạn là như vậy mà bạn có thể tạo bảng của riêng bạn, thì sẽ hợp lý khi chỉ định tùy chọn độ nhạy trường hợp của bạn khi bạn tạo bảng.




2

Cũng lưu ý rằng tên bảng có phân biệt chữ hoa chữ thường trên Linux trừ khi bạn đặt lower_case_table_namechỉ thị cấu hình thành 1 . Điều này là do các bảng được biểu thị bằng các tệp phân biệt chữ hoa chữ thường trong Linux.

Đặc biệt là hãy cẩn thận với sự phát triển trên Windows không phân biệt chữ hoa chữ thường và triển khai đến nơi sản xuất. Ví dụ:

"SELECT * from mytable" 

chống lại bảng myTable sẽ thành công trong Windows nhưng một lần nữa lại thất bại trong Linux, trừ khi chỉ thị nói trên được thiết lập.

Tham khảo tại đây: http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sens nhạy.html


1
+1 - Kịch bản viết các truy vấn không nhạy cảm trong trường hợp và sau đó thất bại trên Linux đã xảy ra rất nhiều trong dự án của chúng tôi
Vic

@Vic Tôi đang gặp vấn đề tương tự với dự án của tôi. Bạn vui lòng cho tôi biết làm thế nào bạn sửa chữa nó?
Kamran Ahmed

@KamranAhmed, bạn cần sử dụng vỏ tên bảng chính xác như chúng xuất hiện trong tập lệnh tạo
Vic

@Vic đó sẽ là phương sách cuối cùng, vì tôi phải sửa đổi hàng tấn truy vấn theo nghĩa đen. Tôi đã tự hỏi, nếu có bất kỳ cách dễ dàng để làm điều đó. Cảm ơn mặc dù!
Kamran Ahmed

@KamranAhmed, hãy thử thay đổi lower_case_table_namenhư được chỉ định trong câu trả lời mà chúng tôi đang nhận xét
Vic

1

Các giải pháp hiện đang được chấp nhận là chủ yếu là chính xác.

Nếu bạn đang sử dụng một chuỗi không phân biệt (CHAR, VARCHAR, TEXT), các phép so sánh không phân biệt chữ hoa chữ thường , theo đối chiếu mặc định.

Nếu bạn đang sử dụng một chuỗi nhị phân (BINary, VARBINARY, BLOB), các phép so sánh có phân biệt chữ hoa chữ thường, vì vậy bạn sẽ cần sử dụng LOWERnhư được mô tả trong các câu trả lời khác.

Nếu bạn không sử dụng đối chiếu mặc định và bạn đang sử dụng một chuỗi không phân biệt, độ nhạy trường hợp được quyết định bởi đối chiếu đã chọn.

Nguồn: https://dev.mysql.com/doc/refman/8.0/en/case-sens nhạy.html . Đọc kỹ. Một số người khác đã nhầm lẫn khi nói rằng so sánh nhất thiết phải phân biệt chữ hoa chữ thường hoặc không nhạy cảm. Đây không phải là trường hợp.


0

Bạn có thể thử nó. hy vọng nó sẽ hữu ích

SELECT * FROM `table` WHERE `Value` COLLATE latin1_general_cs = "IAreSavage"

0

Các trường chuỗi với bộ cờ nhị phân sẽ luôn luôn phân biệt chữ hoa chữ thường. Nếu bạn cần tìm kiếm phân biệt chữ hoa chữ thường cho trường văn bản không nhị phân, hãy sử dụng: CHỌN 'test' REGEXP BINary 'TEST' NHƯ KẾT QUẢ;

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.