我在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从映射表生成查询。那么如何解决这个案子呢?
答案 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
”:
以下示例显示'Monty' = 'Monty '
为真,但不是'Monty' LIKE 'Monty '
。
但是,如果您使用LIKE
,请注意包含'%'
,'_'
或'\'
字符的文字字符串:'%'
和'_'
是通配符,'\'
用于转义序列。