2011-09-17 6 views
5

Si tengo que encontrar un nombre de cadena "Akito" y se encuentra en la tabla foo continuación siguiente es el procedimiento normal,Comparación de cadenas con uno que tenga espacios vacíos antes, mientras que el otro no

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

intenté registrarme dos variaciones de la misma,

funcionó bien

select * from foo where name = 'Akito ' 

¿no hizo Funcionó bien

select * from foo where name = ' Akito' 

Puede alguien por favor explicar por qué el segundo uno no funcionaba?

Gracias de antemano

+1

Si desea un método (probablemente) lento para realizar esto, use 'select * from foo donde TRIM (nombre) = 'Akito'' – leon

+0

@leon: Gracias por eso :) –

Respuesta

9

tipos CHAR llenan la cadena a la longitud del campo con bytes nulos (mientras VARCHAR añadir delimitadores para indicar el final de la cadena - ignorando así los datos adicionales al final (quiero decir bytes vacío)), y, por lo tanto, las comparaciones que tienen espacios al final las ignorarán. Los espacios iniciales son relevantes ya que alteran la cadena en sí. Ver la respuesta de Christopher.

EDIT: alguna elaboración adicional requerida

Vea algunas pruebas prácticas de abajo. Los tipos VARCHAR agregan espacios a la cadena, mientras que los campos CHAR, aunque llenen la cadena hasta su tamaño con espacios, los ignoran durante las comparaciones. Ver específicamente con la segunda línea de la consulta LENGTH función:

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) 

donde MySQL establece el campo CHAR, con el valor de 'a' a medida que se inserta, sólo tiene 1 carácter de longitud. Por otra parte, si se concatena un poco de datos:

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) 

se puede ver que, desde hace VARCHAR tienda donde termina la cadena, el espacio permanece en concatenaciones - que no son válidas para este tipo CHAR.Ahora, teniendo en cuenta la LENGTH ejemplo anterior, donde la línea dos tiene diferentes longitudes de sus campos A y B, probamos:

mysql> SELECT * FROM test WHERE a=b; 
+------+------+ 
| a | b | 
+------+------+ 
| a | a | 
| a | a | 
| a | a | 
+------+------+ 
3 rows in set (0.00 sec) 

Por lo tanto, podemos resumir diciendo que el tipo de datos CHAR ignora y recorta el espacio extra en al final de su cuerda, mientras que no lo hace VARCHAR - excepto durante las comparaciones :

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) 

por lo tanto, es lo mismo ocurre con el tipo 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) 

que muestra que los CHAR y VARCHAR tipos tienen diferentes métodos de almacenamiento, pero sigue las mismas reglas para la comparación pura cadena. Los espacios finales son ignorados; mientras que los espacios iniciales modifican la cadena en sí.

+0

¿Podría explicar a qué se refiere? por "ignorar datos adicionales al final"? ¿Los espacios no se considerarían parte de la cadena? –

+1

@ Akito, ¿aclararon mi punto? – leon

+0

Inquieta la forma en que VARCHARS conserva sus espacios finales ** pero ignórelos durante las comparaciones **. Solo encontré un problema con este comportamiento. – Timo

7

http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html dice lo siguiente:

En particular, los espacios son significativos, lo cual no es cierto para CHAR o comparaciones VARCHAR realizadas con el operador =:

mysql> SELECT 'a' = 'a ', 'a' LIKE 'a '; 
+------------+---------------+ 
| 'a' = 'a ' | 'a' LIKE 'a ' | 
+------------+---------------+ 
|   1 |    0 | 
+------------+---------------+ 
1 row in set (0.00 sec) 

Trailing significa no conducir. Esos parecen ser relevantes.

Cuestiones relacionadas