2008-12-30 16 views
90

Estoy trabajando con una base de datos MySQL que tiene algunos datos importados de Excel. Los datos contienen caracteres que no son ASCII (guiones, etc.), así como retornos de carro ocultos o alimentaciones de línea. ¿Hay alguna manera de encontrar estos registros usando MySQL?¿Cómo puedo encontrar caracteres que no sean ASCII en MySQL?

+7

Ollie Jones tiene una respuesta mucho mejor (marque la parte inferior). –

+0

@JonathanArkell Ya no está en el fondo :) – Brilliand

+0

Corrección ... ¡revisa el centro! ;) –

Respuesta

48

Depende exactamente lo que se está definiendo como "ASCII", pero sugeriría probar una variante de una consulta como esta:

SELECT * FROM tableName WHERE NOT columnToCheck REGEXP '[A-Za-z0-9]'; 

Esa consulta devolverá todas las filas en columnToCheck contiene ninguna no alfanumérico caracteres. Si tiene otros caracteres que son aceptables, agréguelos a la clase de caracteres en la expresión regular. Por ejemplo, si puntos, comas y guiones están bien, cambiar la consulta a:

SELECT * FROM tableName WHERE NOT columnToCheck REGEXP '[A-Za-z0-9.,-]'; 

La página más relevante de la documentación de MySQL es probablemente 12.5.2 Regular Expressions.

+0

Gracias - Voy a echar un vistazo a eso. No tengo mucha experiencia con expresiones regulares en SQL, así que esta será una buena oportunidad para aprender. –

+3

¿No deberías escapar del guión y punto? (Ya que tienen significados especiales en una expresión regular.) SELECCIONE * FROM tableName DONDE NO columnToCheck REGEXP '[A-Za-z0-9 \., \ -]'; – Tooony

+2

El "NO" debe estar al frente en el "REGEXP". Esto solo funcionó para mí cuando el "NO" estaba en ese lugar. –

41

Esto es probablemente lo que usted está buscando:

select * from TABLE where COLUMN regexp '[^ -~]'; 

Debe devolver todas las filas en columna contiene caracteres no ASCII (o caracteres ASCII no imprimibles tales como salto de línea).

+6

Funciona muy bien para mí. "regexp '[^ - ~]'" significa que tiene un carácter que está antes del espacio "" o después de "~" o ASCII 32 - 126. Todas las letras, números y símbolos, pero no elementos imprimibles. – Josh

+0

Incluso puede obtenerlo como una camiseta;) http://www.catonmat.net/blog/my-favorite-regex/ – SamGoody

+1

Tenga en cuenta la ** advertencia ** en la [documentación] (https://dev.mysql.com/doc/es/regexp.html): "* Los operadores' REGEXP' y 'RLIKE' funcionan de forma byte, por lo que no son seguros en varios bytes y pueden producir resultados inesperados con múltiples juegos de caracteres de bytes.Además, estos operadores comparan caracteres por sus valores de bytes y los caracteres acentuados no se pueden comparar como iguales, incluso si una colación dada los trata como iguales. * " – eggyal

91

Puede definir ASCII como todos los caracteres que tienen un valor decimal de 0 - 127 (0x00 - 0x7F) y encontrar columnas con caracteres no ASCII usando la siguiente consulta

SELECT * FROM TABLE WHERE NOT HEX(COLUMN) REGEXP '^([0-7][0-9A-F])*$'; 

Esta fue la consulta más completa Podría venir con.

+2

La mejor respuesta hasta ahora, pero es incluso más fácil así: 'SELECCIONAR * FROM tabla WHERE LENGTH (columna)! = CHAR_LENGTH (columna)' – SuN

+11

-1 ** Esto puede arrojar resultados erróneos. ** Supongamos, por ejemplo, que uno tiene un U La columna TF-16 que contiene ''ā'' (codificada por la secuencia de bytes' 0x0101') - se consideraría "ASCII" utilizando esta prueba: * un falso negativo *; de hecho, algunos conjuntos de caracteres no codifican caracteres ASCII dentro de '0x00' a' 0x7f', por lo que esta solución arrojaría un falso positivo. ** ¡NO CONFÍES EN ESTA RESPUESTA! ** – eggyal

+2

@sun: Eso no ayuda en absoluto, muchos juegos de caracteres son de longitud fija y por lo tanto 'LENGTH (columna)' será un múltiplo constante de 'CHAR_LENGTH (columna)' independientemente del valor. – eggyal

150

MySQL proporciona una administración integral de conjuntos de caracteres que pueden ayudar con este tipo de problemas.

SELECT whatever 
    FROM tableName 
WHERE columnToCheck <> CONVERT(columnToCheck USING ASCII) 

La función CONVERT(col USING charset) voluntad convierte los caracteres unconvertable en caracteres de reemplazo. Entonces, el texto convertido y no convertido será desigual.

Consulte esto para obtener más información. http://dev.mysql.com/doc/refman/5.7/en/charset-repertoire.html

Puede utilizar cualquier nombre de conjunto de caracteres que desee en lugar de ASCII. Por ejemplo, si desea saber qué caracteres no se mostrarán correctamente en la página de códigos 1257 (lituano, letón, estonio) use CONVERT(columnToCheck USING cp1257)

+12

Esta es una excelente solución a este problema y mucho más robusta. – CraigDouglas

+4

esto también es útil para encontrar caracteres con acentos (á ä etc) o caracteres que no pertenecen a la codificación – Glasnhost

+0

mucho mejor que usar REGEXP (que no parece funcionar para encontrar acentos) y también proporciona un mecanismo simple para hacer todo Ascii otra vez ... –

11

Un carácter que falta en los ejemplos anteriores es el carácter de terminación (\ 0). Esto es invisible para la salida de la consola MySQL y no es detectable por ninguna de las consultas mencionadas anteriormente. La consulta para encontrar que es simplemente:

select * from TABLE where COLUMN like '%\0%'; 
1

Sobre la base de la respuesta correcta, pero teniendo en caracteres de control cuenta ASCII, así, la solución que funcionó para mí es la siguiente:

SELECT * FROM `table` WHERE NOT `field` REGEXP "[\\x00-\\xFF]|^$"; 

lo hace el Lo mismo: busca violaciones del rango ASCII en una columna, pero también le permite buscar caracteres de control, ya que usa la notación hexadecimal para los puntos de código. Como no hay comparación o conversión (a diferencia de la respuesta de @ Ollie), esto también debería ser mucho más rápido. (Especialmente si MySQL finaliza anticipadamente en la consulta de expresiones regulares, que definitivamente debería.)

También evita devolver campos que son de longitud cero. Si quieres una versión ligeramente más largo que podría funcionar mejor, puede utilizar esto en su lugar:

SELECT * FROM `table` WHERE `field` <> "" AND NOT `field` REGEXP "[\\x00-\\xFF]"; 

Se hace un cheque por separado para la longitud para evitar resultados de longitud cero, sin tener en cuenta que para un pase de expresiones regulares. Dependiendo de la cantidad de entradas de longitud cero que tenga, esto podría ser significativamente más rápido.

Tenga en cuenta que si su juego de caracteres predeterminado es algo extraño donde 0x00-0xFF no se correlaciona con los mismos valores que ASCII (¿existe un juego de caracteres en alguna parte?), Esto devolvería un falso positivo. De lo contrario, disfruta!

+1

00-FF incluye todos los valores posibles de 8 bits, que es lo que 'REGEXP' está comprobando. Por lo tanto, se garantiza que siempre coincida. También '^ $' probablemente no sea lo que querías. –

0

trate de usar esta consulta para buscar los registros de caracteres especiales

SELECT * 
FROM tableName 
WHERE fieldName REGEXP '[^[email protected]:. \'\-`,\&]' 
0

@ respuesta de Zende fue el único que cubría las columnas con una mezcla de caracteres ASCII y no ASCII, pero también tenía esa cosa hexagonal problemática. Utilicé esto:

SELECT * FROM `table` WHERE NOT `column` REGEXP '^[ -~]+$' AND `column` !='' 
Cuestiones relacionadas