简体   繁体   English

MySQL 5.5在查询中丢失尾随空格

[英]MySQL 5.5 losing trailing spaces in query

I am building a database in which trailing space is important to the results. 我正在构建一个数据库,其中尾随空格对结果很重要。 When I query for a result I find that 当我查询结果时,我发现了

SELECT * where `field` = 'a ' 

Returns a result when there is a field who's value is 'a'. 当存在值为'a'的字段时返回结果。 I want the trailing space to matter in the result set. 我希望结尾空间在结果集中很重要。 I have tried using Char, Varchar, Text, and Blob. 我尝试过使用Char,Varchar,Text和Blob。 I will note that this field is the index of my table. 我会注意到这个字段是我的表的索引。

Can someone show me how to query in a way that makes trailing (and/or leading) spaces count? 有人能告诉我如何以一种使尾随(和/或前导)空间计数的方式进行查询吗? Do I need to format my table in any special way to make this work? 我是否需要以任何特殊方式格式化我的表格以使其工作?

This behaviour is by design, not only in MySQL. 此行为是设计使然,不仅在MySQL中。

You can work around it in comparisons by using BINARY : 您可以使用BINARY比较中解决它:

mysql> select version(), 'a' = 'a ', BINARY 'a' = BINARY 'a ';
+-------------+------------+--------------------------+
| version()   | 'a' = 'a ' | BINARY 'a' = BINARY 'a ' |
+-------------+------------+--------------------------+
| 5.5.25a-log |          1 |                        0 |
+-------------+------------+--------------------------+
1 row in set (0.00 sec)

but not much more. 但不多。 This will help you with SELECT s if whitespaces appear eg in user input to a search; 如果空格出现在例如搜索的用户输入中,这将帮助您使用SELECT ; but if you want to actually input whitespace-trailed information, it will be a problem (you can't have an index with both 'a' and 'a '). 但是如果你想要实际输入空白跟踪信息,那么这将是一个问题(你不能拥有同时包含'a'和'a'的索引)。

See also 也可以看看

Trailing whitespace in varchar needs to be considered in comparison 在比较中需要考虑varchar中的尾随空格

You could conceivably reverse the strings in that column, and reverse them back when displaying them. 您可以想象地反转该列中的字符串,并在显示它们时将其反转。 Of course this will wreck any ordering based on that column, but if you only test equality or substring existence, it just might work. 当然,这将破坏基于该列的任何排序,但如果您只测试相等或子串存在,它可能会起作用。 Leading spaces do count. 领先的空间确实很重要

For equality searches you might also store the base64 encoding of the string, which ought to maintain the lexicographical order (ie, the order between a and b ought to be maintained between base64(a) and base64(b)). 对于相等搜索,您还可以存储字符串的base64编码,该编码应该保持字典顺序(即,a和b之间的顺序应该保持在base64(a)和base64(b)之间)。 Or you might append a terminator on the string ("\\n" could do well and not appear in searches). 或者你可以在字符串上附加一个终结符(“\\ n”可以做得很好而不会出现在搜索中)。

Finally, but it's risky because humans can't tell the difference, you could replace spaces with the UTF8 char(49824): 最后,但它有风险因为人类无法区分,你可以用UTF8 char替换空格(49824):

mysql> select concat ('\'a', char(49824),'\'') AS tricked,
              concat ('\'a', ' '        ,'\'') as honest,
              concat ('\'a', char(49824),'\'') =
              concat ('\'a', ' '        ,'\'') as equals;

+---------+--------+--------+
| tricked | honest | equals |
+---------+--------+--------+
| 'a '    | 'a '   |      0 |
+---------+--------+--------+
1 row in set (0.00 sec)

The rows seem to be equal, but they are not. 似乎相等,但它们不是。 Note that in HTML the space is a space, and 49824 is   请注意,在HTML中,空格是一个空格,而49824是  (nonbreaking space). (不间断的空间)。 This affects functions that convert to and fro HTML, and the nbsp being actually an UTF8 codepoint means that honest string is two bytes, but length of tricked string is actually three . 这会影响转换为HTML的函数,而实际上是UTF8代码点意味着诚实字符串是两个字节,但欺骗字符串的长度实际上是三个

Finally you can declare the column VARBINARY instead of VARCHAR , thus completely hiding what's happening. 最后,您可以声明列VARBINARY而不是VARCHAR ,从而完全隐藏正在发生的事情。 It looks like the easiest solution, but I fear it might bite you some weeks or months down the line. 它看起来是最简单的解决方案,但我担心这可能会让你感到困扰几周或几个月。

I have had success doing the following, but I'm not sure if it is an unstable approach. 我已经成功地完成了以下工作,但我不确定它是否是一种不稳定的方法。

CREATE TEMPORARY TABLE test (
  PRIMARY KEY(id),
  id INT AUTO_INCREMENT,
  val VARCHAR(20)
);

INSERT INTO test VALUES
(NULL, 'a'),
(NULL, 'a '),
(NULL, 'a  '),
(NULL, 'a   ');

SELECT * FROM test
WHERE val LIKE 'a ';

Output 产量

id  val
2   'a '

Using WHERE val = 'a ' will select all entries without taking trailing spaces into consideration, but LIKE works for me. 使用WHERE val ='a'将选择所有条目而不考虑尾随空格,但LIKE适用于我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM