我正在建立一个数据库,其中尾随空格对结果很重要。当我查询结果时,我发现
SELECT * where `field` = 'a '
当存在值为 'a' 的字段时返回结果。我希望尾随空格在结果集中很重要。我尝试过使用 Char、Varchar、Text 和 Blob。我会注意到这个字段是我的表的索引。
有人可以告诉我如何以使尾随(和/或前导)空格计数的方式进行查询吗?我是否需要以任何特殊方式格式化我的表格才能完成这项工作?
我正在建立一个数据库,其中尾随空格对结果很重要。当我查询结果时,我发现
SELECT * where `field` = 'a '
当存在值为 'a' 的字段时返回结果。我希望尾随空格在结果集中很重要。我尝试过使用 Char、Varchar、Text 和 Blob。我会注意到这个字段是我的表的索引。
有人可以告诉我如何以使尾随(和/或前导)空格计数的方式进行查询吗?我是否需要以任何特殊方式格式化我的表格才能完成这项工作?
这种行为是设计使然,不仅在 MySQL 中。
您可以使用以下方法在比较中解决它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)
但不多。SELECT
如果空格出现在搜索的用户输入中,这将帮助您处理s;但是如果你想实际输入空格结尾的信息,那将是一个问题(你不能同时拥有'a'和'a'的索引)。
也可以看看
您可以想象反转该列中的字符串,并在显示它们时将它们反转回来。当然,这会破坏基于该列的任何排序,但如果您只测试相等或子字符串的存在,它可能会起作用。前导空格确实很重要。
对于相等搜索,您还可以存储字符串的 base64 编码,它应该保持字典顺序(即 a 和 b 之间的顺序应该保持在 base64(a) 和 base64(b) 之间)。或者您可以在字符串上附加一个终止符(“\n”可能会很好并且不会出现在搜索中)。
最后,但这是有风险的,因为人类无法区分,您可以用 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)
这些行似乎相等,但事实并非如此。请注意,在 HTML 中,空格是空格,而 49824 是
(不间断空格)。这会影响来回转换 HTML 的函数,并且 nbsp 实际上是 UTF8 代码点意味着诚实字符串是两个字节,但被欺骗字符串的长度实际上是3。
最后,您可以声明该列VARBINARY
而不是VARCHAR
,从而完全隐藏正在发生的事情。它看起来是最简单的解决方案,但我担心它可能会在几周或几个月后给你带来麻烦。
我在以下方面取得了成功,但我不确定这是否是一种不稳定的方法。
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 ';
输出
id val
2 'a '
使用 WHERE val = 'a ' 将选择所有条目而不考虑尾随空格,但 LIKE 对我有用。