Сравнение строк с одним пустым пространством раньше, в то время как другое не - PullRequest
5 голосов
/ 17 сентября 2011

Если мне нужно найти имя строки "Akito", и оно лежит в таблице foo, то следующая обычная процедура:

select * from foo where `name = 'Akito'`

Я попытался проверить два варианта этого,

Работал нормально

select * from foo where name = 'Akito   '

Не работал нормально

select * from foo where name = '    Akito'

Может кто-нибудь объяснить, почему не работал 2-й??

Заранее спасибо

Ответы [ 2 ]

9 голосов
/ 17 сентября 2011

Типы 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)

где 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)

вы можете видеть, что, поскольку 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)

Таким образом, мы можем подвести итог, заявив, что тип данных 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)

То же самое относится и к типу 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)

Показывает, что типы CHAR и VARCHAR имеют разные методы хранения, но следуют тем же правилам для простого сравнения строк . Конечные пробелы игнорируются; в то время как начальные пробелы изменяют саму строку.

7 голосов
/ 17 сентября 2011

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)

Трейлинг означает не ведущий. Те, кажется, актуальны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...