如果我必须找到一个字符串名称"Akito"并且它位于表foo中,那么以下是正常的过程,
select * from foo where `name = 'Akito'`
Run Code Online (Sandbox Code Playgroud)
我试着检查它的两个变种,
工作得很好
select * from foo where name = 'Akito '
Run Code Online (Sandbox Code Playgroud)
工作不好
select * from foo where name = ' Akito'
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释为什么第二个不起作用?
提前致谢
CHAR类型使用空字节将字符串填充到字段的长度(而VARCHAR添加分隔符以指示字符串的结尾 - 因此忽略末尾的额外数据(我的意思是空字节)),因此比较具有空格的字符串结束将忽略那些.前导空格是相关的,因为它们改变了字符串本身.见克里斯托弗的答案.
编辑:需要进一步细化
看下面的一些实际测试.VARCHAR类型确实为字符串添加了空格,而CHAR字段,即使它们用空格填充字符串大小,在比较期间忽略它们.具体请参见LENGTH函数查询的第二行:
mysql> create table test (a VARCHAR(10), b CHAR(10));
Query OK, 0 rows affected (0.17 sec)
mysql> insert into test values ('a', 'a'), ('a ', 'a '), (' a', ' a');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select a, LENGTH(a), b, LENGTH(b) FROM test;
+------+-----------+------+-----------+
| a | LENGTH(a) | b | LENGTH(b) |
+------+-----------+------+-----------+
| a | 1 | a | 1 |
| a | 2 | a | 1 |
| a | 2 | a | 2 |
+------+-----------+------+-----------+
3 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
MySQL声明CHAR字段,其中插入的值为'a',长度只有1个字符.此外,如果我们连接一些小数据:
mysql> select CONCAT(a, '.'), CONCAT(b, '.') FROM test;
+----------------+----------------+
| CONCAT(a, '.') | CONCAT(b, '.') |
+----------------+----------------+
| a. | a. |
| a . | a. |
| a. | a. |
+----------------+----------------+
3 rows in set (0.00 sec)
mysql> select CONCAT(a, b), CONCAT(b, a) FROM test;
+--------------+--------------+
| CONCAT(a, b) | CONCAT(b, a) |
+--------------+--------------+
| aa | aa |
| a a | aa |
| a a | a a |
+--------------+--------------+
3 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
你可以看到,因为VARCHAR确实存储了字符串结束的位置,所以空间仍然存在于连接中 - 这对于CHAR类型不适用.现在,请记住上一个LENGTH示例,其中第二行的字段a和b的长度不同,我们测试:
mysql> SELECT * FROM test WHERE a=b;
+------+------+
| a | b |
+------+------+
| a | a |
| a | a |
| a | a |
+------+------+
3 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
因此,我们可以总结说明CHAR数据类型忽略并修剪其字符串末尾的额外空间,而VARCHAR则不会 - 除了在比较期间:
mysql> select a from test where a = 'a ';
+------+
| a |
+------+
| a |
| a |
+------+
2 rows in set (0.00 sec)
mysql> select a from test where a = 'a';
+------+
| a |
+------+
| a |
| a |
+------+
2 rows in set (0.00 sec)
mysql> select a from test where a = ' a';
+------+
| a |
+------+
| a |
+------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
那么,CHAR类型也是如此吗?
mysql> select a from test where b = 'a ';
+------+
| a |
+------+
| a |
| a |
+------+
2 rows in set (0.00 sec)
mysql> select a from test where b = 'a';
+------+
| a |
+------+
| a |
| a |
+------+
2 rows in set (0.00 sec)
mysql> select a from test where b = ' a';
+------+
| a |
+------+
| a |
+------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
其中显示CHAR和VARCHAR类型具有不同的存储方法,但遵循相同的规则进行纯粹的字符串比较.尾随空格被忽略; 前导空格修改字符串本身.
http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html说明如下:
特别是,尾随空格很重要,但对于使用=运算符执行的CHAR或VARCHAR比较则不然:
mysql> SELECT 'a' = 'a ', 'a' LIKE 'a ';
+------------+---------------+
| 'a' = 'a ' | 'a' LIKE 'a ' |
+------------+---------------+
| 1 | 0 |
+------------+---------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
尾随意味着不领先.这似乎是相关的.