2012-04-27 63 views
5

Tôi tạo ra bảng như thế trong MySQL:Chuỗi so sánh chính xác trong MySQL truy vấn

DROP TABLE IF EXISTS `barcode`; 
CREATE TABLE `barcode` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `code` varchar(40) COLLATE utf8_bin DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 


INSERT INTO `barcode` VALUES ('1', 'abc'); 

INSERT INTO `barcode` VALUES ('2', 'abc '); 

Sau đó, tôi truy vấn dữ liệu từ bảng mã vạch:

SELECT * FROM barcode WHERE `code` = 'abc '; 

Kết quả là:

+-----+-------+ 
| id | code | 
+-----+-------+ 
| 1 | abc | 
+-----+-------+ 
| 2 | abc | 
+-----+-------+ 

Nhưng tôi muốn tập kết quả chỉ là 1 bản ghi. Tôi giải quyết sự cố với:

SELECT * FROM barcode WHERE `code` = binary 'abc '; 

Kết quả là 1 bản ghi. Nhưng tôi đang sử dụng NHibernate với MySQL để tạo truy vấn từ bảng ánh xạ. Vì vậy, làm thế nào để giải quyết trường hợp này?

+0

Lần tiếp theo, hãy xem câu hỏi của bạn sẽ ra sao (có hộp xem trước bên dưới trường văn bản) và nếu có vẻ lộn xộn, hãy khắc phục sự cố :). Sử dụng một số lượng lớn của nút '{}' trên đầu trang cho mã ..... – Nanne

+1

Bạn có thể cung cấp ánh xạ NHibenate và phương pháp bạn sử dụng để tạo truy vấn không? Tại sao bạn sử dụng native-SQL với NHibernate. Tôi nghĩ, bạn nên sử dụng API tiêu chí hoặc HQL. –

+1

từ tài liệu: ["Tất cả các collations của MySQL đều thuộc loại PADSPACE. Điều này có nghĩa là tất cả các giá trị CHAR và VARCHAR trong MySQL được so sánh không liên quan đến bất kỳ dấu cách nào"] (http://dev.mysql.com/doc/refman/ 5.0/en/char.html) – Kaii

Trả lời

0

Tôi giả sử bạn chỉ muốn một kết quả, bạn có thể sử dụng LIMIT

SELECT * FROM barcode WHERE `code` = 'abc ' LIMIT 1; 

Để làm chuỗi chính xác phù hợp với bạn có thể sử dụng Collation

SELECT * 
FROM barcode 
WHERE code COLLATE utf8_bin = 'abc'; 
+0

Điều này không trả lời OP - vấn đề có vẻ là họ chỉ muốn có các kết quả khớp chuỗi chính xác, bao gồm cả khoảng trắng phía trước và cuối. Sử dụng 'LIMIT' không đạt được điều này. – Romain

+1

Tôi không nghĩ rằng bạn sử dụng đề xuất của 'COLLATE utf8_general_ci' sẽ tạo ra bất kỳ sự khác biệt nào? – eggyal

+0

'COLLATE binary' sẽ làm – Kaii

2

Bạn có thể thử với một regular expression matching:

SELECT * FROM barcode WHERE `code` REGEXP 'abc[[:space:]]' 
+1

Dịch vụ giữ trẻ để giúp phần còn lại của chúng tôi hiểu bạn nghĩ gì sai với câu trả lời này? – eggyal

+0

Tôi đoán câu trả lời này đã bị bỏ qua vì 'REGEXP' vô hiệu hóa việc tìm kiếm chỉ mục và luôn dẫn đến việc quét toàn bộ bảng. Nếu bạn * có thể tránh regex * trong mysql, bạn không nên sử dụng nó. – Kaii

0

Bạn có thể thực hiện việc này:

SELECT * FROM barcode WHERE `code` = 'abc ' 
AND CHAR_LENGTH(`code`)=CHAR_LENGTH('abc '); 
+0

Dịch vụ chăm sóc người giúp việc để giúp phần còn lại của chúng tôi hiểu những gì bạn nghĩ là sai với câu trả lời này? – eggyal

+0

Tôi đoán câu trả lời này đã bị bỏ qua vì 'WH F (x) = F (y)' đang gây ra rất nhiều chi phí tính toán, bởi vì hàm phải được thực thi hai lần cho mỗi hàng trong tập dữ liệu kết quả. Trong trường hợp này nó không quá tệ, vì có ít nhất một điều kiện 'WHERE' đơn giản. Nếu 'F (x) = F (y)' là điều kiện * duy nhất *, nó sẽ dẫn đến việc quét toàn bộ bảng, đó là điều bạn nên tránh. – Kaii

7

Không còn cách khắc phục nào khác. Hoặc bạn chỉ định một so sánh đơn lẻ là binary hoặc bạn đặt toàn bộ kết nối cơ sở dữ liệu thành binary. (Làm SET NAMES binary, trong đó có thể có tác dụng phụ khác!)

Về cơ bản, đó là lười biếng 'so sánh là một tính năng của MySQL được cứng mã hoá. Để vô hiệu hóa nó (theo yêu cầu!), Bạn có thể sử dụng một so sánh binary, những gì bạn dường như đã làm. Đây không phải là một 'workaround' nhưng sửa chữa thực sự.

từ MySQL Manual:

Tất cả collations MySQL là loại PADSPACE. Điều này có nghĩa rằng tất cả các giá trị CHAR và VARCHAR trong MySQL được so sánh mà không quan tâm đến bất kỳ dấu trailing

Tất nhiên có rất nhiều possiblities khác để đạt được kết quả tương tự từ quan điểm của người dùng, ví dụ:

  • WHERE field = 'abc ' AND CHAR_LENGTH(field) = CHAR_LENGTH('abc ')
  • WHERE field REGEXP 'abc[[:space:]]'

vấn đề với những là họ EFF ectively vô hiệu hóa nhanh chóng tìm kiếm chỉ mục, do đó, truy vấn của bạn luôn luôn kết quả trong một bảng đầy đủ quét. Với bộ dữ liệu khổng lồ tạo nên sự khác biệt lớn.

Một lần nữa:PADSPACE là mặc định cho so sánh [VAR] CHAR của MySQL. Bạn có thể (và nên) vô hiệu hóa nó bằng cách sử dụng BINARY.Đây là cách để làm điều này.

-1

Câu ngay sau khi một trích dẫn bởi Kaii về cơ bản nói "sử dụng LIKE":

“Comparison” in this context does not include the LIKE pattern-matching operator, for which trailing spaces are significant

và ví dụ dưới đây cho thấy 'Monty' = 'Monty ' là đúng, nhưng không 'Monty' LIKE 'Monty '.

Tuy nhiên, nếu bạn sử dụng LIKE, hãy cẩn thận của các chuỗi chữ chứa '%', '_' hoặc '\' ký tự: '%''_' là ký tự đại diện, '\' được sử dụng để thoát khỏi chuỗi.

+0

bắt thú vị. nhưng khi sử dụng 'LIKE' cũng nên biết về các tác dụng phụ khác của toán tử' LIKE'. Ví dụ: '" A "LIKE" a "' bằng true, '" a "LIKE" _ "' cũng bằng true. Như một cách giải quyết cho trường hợp-insensitivity của 'LIKE' hướng dẫn cung cấp một hoạt động' LIKE BINARY' .. Và đó là nơi vòng tròn được đóng lại: 'BINARY' là sửa chữa thực sự. Nếu bạn không tin tôi, hãy xem hướng dẫn cho ['LIKE'] (http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html#operator_like). Sự khác biệt duy nhất giữa '= BINARY' và' LIKE BINARY' là 'LIKE' có nhiều tác dụng phụ hơn. Xin lỗi;) – Kaii

+0

Ok, thx để biết thêm chi tiết. – LeGEC

+0

'" A "LIKE" a "' phụ thuộc vào collation, phải không? giống như '='. Mặc dù vậy, tôi không biết về ký tự đặc biệt của '" _ "'. Nó chắc chắn làm phức tạp các trường hợp góc. Cảm ơn bạn đã chỉ ra điều đó. – LeGEC

0

tôi chỉ đang xử lý trường hợp giống như khi sử dụng LIKE với ký tự đại diện (%) dẫn đến kết quả không mong muốn. Trong khi tìm kiếm tôi cũng tìm thấy STRCMP(text1, text2) dưới tính năng so sánh chuỗi của mysql so sánh hai chuỗi. Tuy nhiên bằng cách sử dụng BINARY với LIKE giải quyết vấn đề cho tôi.

SELECT * FROM barcode WHERE `code` LIKE BINARY 'abc '; 
+2

FYI: Mặc dù câu trả lời của bạn có vẻ hợp lý, nhưng nó đã xuất hiện trong hàng đợi 'bài đăng chất lượng thấp' sau khi được gắn cờ để xóa.Tôi nghi ngờ điều này là bởi vì nó là một mã chỉ trả lời mà không cần giải thích. Để rõ ràng ở đây, tôi đã không gắn cờ nó vì vậy tôi không biết tại sao nó bị gắn cờ. Tuy nhiên tôi thấy rất nhiều câu trả lời chỉ xuất hiện trong hàng đợi đó, vì vậy tôi đã thực hiện để thêm nhận xét cho họ để người trả lời nhận thức được điều này. –

+0

xấu của tôi. tôi nên thêm một số lời giải thích. Cảm ơn vì đã cho tôi biết. –