2012-04-27 45 views
5

creé tabla como la de MySQL:comparación de cadenas exacta en MySQL consulta

DROP TABLE IF EXISTS `barcode`; 
CREATE TABLE `barcode` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `code` varchar(40) COLLATE utf8_bin DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 


INSERT INTO `barcode` VALUES ('1', 'abc'); 

INSERT INTO `barcode` VALUES ('2', 'abc '); 

Entonces consultar datos de código de barras tabla:

SELECT * FROM barcode WHERE `code` = 'abc '; 

El resultado es:

+-----+-------+ 
| id | code | 
+-----+-------+ 
| 1 | abc | 
+-----+-------+ 
| 2 | abc | 
+-----+-------+ 

Pero quiero que el conjunto de resultados sea solo 1 registro. Tengo una solución con:

SELECT * FROM barcode WHERE `code` = binary 'abc '; 

El resultado es 1 registro. Pero estoy usando NHibernate con MySQL para generar consultas desde la tabla de mapeo. Entonces, ¿cómo resolver este caso?

+0

La próxima vez, echar un vistazo a cómo su pregunta va a salir (hay un cuadro de vista previa debajo de su campo de texto), y si se ve un lío, solucionarlo :). Use una cantidad generosa del botón '{}' en la parte superior para el código ..... – Nanne

+1

¿Podría proporcionar las asignaciones de NHibenate y los métodos que utiliza para generar una consulta? ¿Por qué usa SQL nativo con NHibernate? Creo que deberías usar Criteria API o HQL. –

+1

de los documentos: ["Todas las intercalaciones MySQL son de tipo PADSPACE. Esto significa que todos los valores CHAR y VARCHAR en MySQL se comparan sin tener en cuenta ningún espacio posterior"] (http://dev.mysql.com/doc/refman/ 5.0/es/char.html) – Kaii

Respuesta

0

estoy asumiendo que usted quiere sólo un resultado, se puede usar LIMIT

SELECT * FROM barcode WHERE `code` = 'abc ' LIMIT 1; 

Para ello cadena exacta de búsqueda adecuados que podría utilizar Collation

SELECT * 
FROM barcode 
WHERE code COLLATE utf8_bin = 'abc'; 
+0

Esto no responde al OP: el problema parece ser que solo quieren tener coincidencias de cadenas exactas, incluidos los espacios iniciales y finales. El uso de 'LIMIT' no logra esto. – Romain

+1

No creo que su uso propuesto de 'COLLATE utf8_general_ci' haga alguna diferencia? – eggyal

+0

'COLLATE binary' haria – Kaii

2

Usted puede tratar con un regular expression matching:

SELECT * FROM barcode WHERE `code` REGEXP 'abc[[:space:]]' 
+1

Cuidado de los detractores para ayudar al resto de nosotros a entender lo que piensa que esta respuesta es incorrecta? – eggyal

+0

Supongo que esta respuesta fue downvoted porque 'REGEXP' deshabilita las búsquedas de índice y siempre da como resultado una exploración de tabla completa. Si * puedes evitar regex * en mysql, no deberías usarlo. – Kaii

0

Puede hacer esto:

SELECT * FROM barcode WHERE `code` = 'abc ' 
AND CHAR_LENGTH(`code`)=CHAR_LENGTH('abc '); 
+0

Cuidados de devaluador para ayudar al resto de nosotros a entender lo que piensa que está mal con esta respuesta? – eggyal

+0

Supongo que esta respuesta fue downvoted porque 'WHERE F (x) = F (y)' está causando una gran sobrecarga computacional, porque la función debe ejecutarse dos veces para cada fila en el conjunto de datos de resultados. En este caso, no es tan malo, porque hay al menos una condición simple 'WHERE'. Si 'F (x) = F (y)' era la condición * solo *, daría como resultado un escaneo completo de la tabla, que es algo que debe evitar. – Kaii

7

No hay otra solución para ello. O bien, especifica una comparación única como binary o establece la conexión de la base de datos completa en binary. (Haciendo SET NAMES binary, que puede tener otros efectos secundarios!)

Básicamente, que la comparación 'perezoso' es una característica de MySQL que está codificado. Para deshabilitarlo (bajo demanda), puede usar una comparación binary, lo que aparentemente ya hace. Esto no es una "solución alternativa" sino la solución real.

del MySQL Manual:

Todas las intercalaciones de MySQL son de tipo PADSPACE. Esto significa que todos los valores CHAR y VARCHAR en MySQL se comparan sin tener en cuenta los espacios finales

Por supuesto que hay muchas otras posibilidades para lograr el mismo resultado a partir de la perspectiva de un usuario, es decir:

  • WHERE field = 'abc ' AND CHAR_LENGTH(field) = CHAR_LENGTH('abc ')
  • WHERE field REGEXP 'abc[[:space:]]'

El problema con estos es que EFF Deshabilite activamente las búsquedas rápidas de índice, de modo que su consulta siempre resulte en un escaneo completo de la tabla. Con enormes conjuntos de datos que hacen una gran diferencia.

De nuevo:PADSPACE es la comparación predeterminada de MySQL [VAR] CHAR. Puede (y debe) deshabilitarlo usando BINARY.Esta es la manera indended de hacer esto.

-1

La sentencia inmediatamente después al citado por Kaii básicamente dice "utilizar LIKE":

“Comparison” in this context does not include the LIKE pattern-matching operator, for which trailing spaces are significant

y el ejemplo a continuación muestra que 'Monty' = 'Monty ' es cierto, pero no 'Monty' LIKE 'Monty '.

Sin embargo, si se utiliza LIKE, tenga cuidado con las cadenas literales que contienen los '%', '_' o '\' caracteres: '%' y '_' son caracteres comodín, '\' se utiliza para las secuencias de escape.

+0

buena captura. pero al usar 'LIKE' uno también debería estar al tanto de los otros efectos secundarios del operador' LIKE'. Ejemplos: '" A "LIKE" a "' es igual a true, '" a "LIKE" _ "' también es verdadero. Como solución a la insensibilidad a mayúsculas y minúsculas de 'LIKE', el manual ofrece una operación' LIKE BINARY' .. Y ahí es donde se cierra el círculo: 'BINARY' es la solución real. Si no me cree, consulte el manual de ['LIKE'] (http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html#operator_like). La única diferencia entre '= BINARY' y' LIKE BINARY' es que 'LIKE' tiene más efectos secundarios. Lo siento;) – Kaii

+0

Ok, gracias por los detalles extra. – LeGEC

+0

'" A "LIKE" a "' depende de la colación, ¿no es así? al igual que '='. Sin embargo, no conocía el carácter especial '' _ "'. Seguro que complica los casos de esquina. Gracias por señalar eso. – LeGEC

0

Estaba trabajando en el caso así al usar LIKE con comodín (%), lo que resultó en un resultado inesperado. Durante la búsqueda también encontré STRCMP(text1, text2) en la función de comparación de cadenas de mysql que compara dos cadenas. sin embargo, usar BINARY con LIKE resolvió el problema para mí.

SELECT * FROM barcode WHERE `code` LIKE BINARY 'abc '; 
+2

FYI: Si bien su respuesta parece plausible, apareció en la cola de "publicaciones de baja calidad" después de marcarse para su eliminación.Sospecho que esto es porque es una respuesta de solo código sin explicación. Para ser claro aquí, no lo señalé, así que no sé por qué estaba marcado. Sin embargo, sí veo muchas respuestas de código único que aparecen en esa cola, por lo que he decidido agregarles comentarios para que el respondedor lo sepa. –

+0

mi mal. debería agregar alguna explicación. gracias por hacérmelo saber. –