2012-09-22 16 views
6

Estoy construyendo una base de datos en la que el espacio final es importante para los resultados. Cuando consulto un resultado, encuentro queMySQL 5.5 Perdiendo espacios al final en la consulta

SELECT * where `field` = 'a ' 

Devuelve un resultado cuando hay un campo cuyo valor es 'a'. Quiero que el espacio final sea importante en el conjunto de resultados. He intentado usar Char, Varchar, Text y Blob. Notaré que este campo es el índice de mi tabla.

¿Alguien me puede mostrar cómo consultar de forma que los espacios finales (y/o iniciales) cuenten? ¿Debo formatear mi mesa de alguna manera especial para que esto funcione?

Respuesta

5

Este comportamiento es por diseño, no solo en MySQL.

Puede trabajar alrededor de ella en comparaciones utilizando 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) 

pero no mucho más. Esto lo ayudará con SELECT s si aparecen espacios en blanco, p. en la entrada del usuario a una búsqueda; pero si realmente quiere ingresar información rastreada en blanco, será un problema (no puede tener un índice con 'a' y 'a').

Ver también

Trailing whitespace in varchar needs to be considered in comparison

Se podría concebiblemente inversa las cuerdas de esa columna, y revertir de nuevo al mostrarlos. Por supuesto, esto arruinará cualquier pedido basado en esa columna, pero si solo prueba la existencia de igualdad o subcadena, podría funcionar. Los principales espacios cuentan.

Para búsquedas de igualdad también puede almacenar la codificación base64 de la cadena, que debe mantener el orden lexicográfico (es decir, el orden entre a y b debe mantenerse entre base64 (a) y base64 (b)). O puede agregar un terminador en la cadena ("\ n" podría funcionar bien y no aparecer en las búsquedas).

Por último, pero es arriesgado, porque los seres humanos no pueden ver la diferencia, que podrían sustituir los espacios con el carbón UTF8 (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) 

Las filas parecen a ser igual, pero no son . Tenga en cuenta que en HTML el espacio es un espacio, y 49824 es   (espacio de no separación). Esto afecta a las funciones que convierten un lado a otro HTML, y siendo el nbsp en realidad un punto de código UTF-8 significa que honesta cadena es de dos bytes, pero la longitud de engañado cadena es en realidad tres .

Finalmente puede declarar la columna VARBINARY en lugar de VARCHAR, ocultando por completo lo que está sucediendo. Parece la solución más fácil, pero me temo que podría morderte algunas semanas o meses más adelante.

+0

Me doy cuenta de que, en la mayoría de los casos, un db querría eliminar los espacios iniciales y finales, pero en mi caso son importantes. En mi caso '' (2 espacios) y '' (3 espacios) son entradas válidas y necesito distinguirlas, así es como buscaría en la tabla. ¿De acuerdo con esta información, cualquiera de los languges SQL puede no ser una solución? ¿Hay alguna manera de lograr lo que estoy buscando? No estoy bloqueado en mySQL. Desafortunadamente, mis entradas pueden tener espacios AND leaking. – taggedzi

+0

'Muchos de estos hacks son posibles' ... He enumerado algunos. Ninguna es scot o libre de riesgos, desafortunadamente. – LSerni

+0

Gracias por la información puedo usar la codificación base64 Me olvidé por completo de que no la he usado en bastante tiempo. Gracias, veré si eso funciona. – taggedzi

1

He tenido éxito haciendo lo siguiente, pero no estoy seguro de si se trata de un enfoque inestable.

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 '; 

salida

id val 
2 'a ' 

utilizando, cuando val = 'a' seleccionará todas las entradas sin tomar en consideración los espacios finales, pero al igual que funciona para mí.

+0

Funciona; pero luego es más rápido usar 'SELECT * FROM test WHERE val = BINARY 'a';' ('LIKE' es un poco más lento). El gran problema en el enfoque de OP es la mantenibilidad. Es fácil olvidar que algunas columnas están acolchadas. Y el problema principal (el campo es una clave principal) no está resuelto de ninguna manera. En otras circunstancias, la tuya es una solución rápida; +1 por eso. – LSerni

Cuestiones relacionadas