查询MySQL中的字符串比较精确

时间:2012-04-27 07:44:37

标签: mysql comparison collation

我在MySQL中创建了这样的表:

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 ');

然后我查询表条形码中的数据:

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

结果是:

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

但我希望结果集只有1条记录。我解决了:

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

结果是1条记录。但我正在使用NHibernate和MySQL从映射表生成查询。那么如何解决这个案子呢?

6 个答案:

答案 0 :(得分:8)

没有其他修复方法。您可以将单个比较指定为binary,也可以将整个数据库连接设置为binary。 (做SET NAMES binary,可能有其他副作用!)

基本上,'懒惰'比较是MySQL的功能,它是硬编码的。要禁用它(按需!),您可以使用binary比较,您显然已经做了。这不是“解决方法”,而是真正的解决方法。

来自MySQL Manual

  

所有MySQL排序规则都是PADSPACE类型。这意味着MySQL中的所有CHAR和VARCHAR值都会进行比较,而不考虑任何尾随空格

当然,从用户的角度来看,还有很多其他的可能性来实现相同的结果,即:

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

问题这些问题是它们有效地禁用了快速索引查找,因此您的查询始终会导致全表扫描。巨大的数据集会带来很大的不同。

再次: PADSPACE是MySQL [VAR] CHAR比较的默认值。您可以(并且应该)使用BINARY禁用它。这是这种做法的有效方式。

答案 1 :(得分:2)

您可以尝试使用regular expression matching

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

答案 2 :(得分:0)

我假设你只想要一个结果,你可以使用LIMIT

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

要进行精确的字符串匹配,您可以使用Collation

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

答案 3 :(得分:0)

你可以这样做:

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

答案 4 :(得分:0)

我正在研究案例就像使用LIKE和通配符(%)一样导致意外结果。在搜索时我还发现STRCMP(text1, text2)在mysql的字符串比较功能下比较了两个字符串。然而,使用BINARY和LIKE解决了我的问题。

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

答案 5 :(得分:-1)

Kaii引用的句子之后的句子基本上是“使用LIKE”:

  

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

以下示例显示'Monty' = 'Monty '为真,但不是'Monty' LIKE 'Monty '

但是,如果您使用LIKE,请注意包含'%''_''\'字符的文字字符串:'%''_'是通配符,'\'用于转义序列。