Как мне найти в MySQL символы, отличные от ASCII?

124

Я работаю с базой данных MySQL, в которой есть данные, импортированные из Excel . Данные содержат символы, отличные от ASCII (длинное тире и т. Д.), А также скрытые символы возврата каретки или перевода строки. Есть ли способ найти эти записи с помощью MySQL?

Эд Мэйс
источник
8
У Олли Джонса есть гораздо лучший ответ (посмотрите внизу).
Джонатан Аркелл,
1
@JonathanArkell Больше не на дне :)
Brilliand
Поправка .. проверьте середину! ;)
Джонатан Аркелл
Это ответ @Jonathan говорит о stackoverflow.com/a/11741314/792066
Брайам

Ответы:

64

Это зависит именно от того, что вы определяете как «ASCII», но я бы посоветовал попробовать такой вариант запроса:

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

Этот запрос вернет все строки, в которых columnToCheck содержит любые символы, отличные от буквенно-цифровых. Если у вас есть другие допустимые символы, добавьте их в класс символов в регулярном выражении. Например, если точки, запятые и дефисы допустимы, измените запрос на:

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

Наиболее актуальной страницей документации MySQL, вероятно, является 12.5.2 Регулярные выражения .

Чад Берч
источник
3
Не следует ли избегать дефиса и точки? (Поскольку они имеют особое значение в регулярном выражении.) SELECT * FROM tableName WHERE NOT columnToCheck REGEXP '[A-Za-z0-9 \., \ -]';
Tooony
3
@Tooony Нет, внутри набора точка означает сама себя, а тире имеет особое значение только между другими символами. В конце набора это означает только себя.
Майкл Спир
10
Этот запрос находит только все строки в tableName, которые не содержат буквенно-цифровых символов. Это не ответ на вопрос.
Роб Бейли
8
Это касается столбцов, в которых вообще нет никаких символов ascii, поэтому он будет пропускать те, которые содержат как символы ascii, так и символы, отличные от ascii. Приведенный ниже ответ от zende проверяет наличие одного или нескольких символов, отличных от ascii. Это мне по большей части помоглоSELECT * FROM tbl WHERE colname NOT REGEXP '^[A-Za-z0-9\.,@&\(\) \-]*$';
Фрэнк Форте
1
Это работает (по крайней мере для меня) только для поиска строк, которые не содержат НИКАКИХ этих символов. Он не находит строки, содержащие как символы ASCII, так и символы, отличные от ASCII.
Ян
236

MySQL обеспечивает комплексное управление набором символов, которое может помочь в решении такого рода проблем.

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

CONVERT(col USING charset)Функция превращает unconvertable символов в замене символов. Тогда преобразованный и непреобразованный текст будут неравными.

См. Это для более подробного обсуждения. https://dev.mysql.com/doc/refman/8.0/en/charset-repertoire.html

Вы можете использовать любое имя набора символов вместо ASCII. Например, если вы хотите узнать, какие символы некорректно отображаются на кодовой странице 1257 (литовский, латышский, эстонский), используйтеCONVERT(columnToCheck USING cp1257)

О. Джонс
источник
20
Это отличное и гораздо более надежное решение этой проблемы.
CraigDouglas
5
это также полезно для поиска символов с акцентами (á ä и т. д.) или символов, не принадлежащих кодировке
Glasnhost
3
намного лучше, чем использование REGEXP (который, похоже, не работает для меня для поиска акцентов), а также предоставляет простой механизм для повторного создания всего ascii ...
Дирк Конрад
1
Этот ответ отлично работает и вызовет строки, содержащие любые символы, отличные от ASCII, а не только строки, содержащие только символы, отличные от ASCII. Спасибо!
Ян
2
Отличное решение!
Mad Dog Tannen
93

Вы можете определить ASCII как все символы с десятичным значением от 0 до 127 (0x00 - 0x7F) и найти столбцы с символами, отличными от ASCII, используя следующий запрос

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

Это был самый исчерпывающий вопрос, который я мог придумать.

zende
источник
3
Лучший ответ на данный момент, но это еще проще:SELECT * FROM table WHERE LENGTH( column ) != CHAR_LENGTH( column )
Вс,
15
-1 Это может привести к ошибочным результатам. Предположим, например, что у кого-то есть столбец UTF-16, содержащий 'ā'(закодированный последовательностью байтов 0x0101) - он будет считаться «ASCII» с помощью этого теста: ложноотрицательный ; на самом деле, некоторые наборы символов не закодировать символы ASCII в 0x00в результате 0x7fчего это решение дало бы ложноположительный. НЕ ДОВЕРЯЙТЕ НА ЭТОТ ОТВЕТ!
eggyal
2
@sun: Это совсем не помогает - многие наборы символов имеют фиксированную длину и поэтому LENGTH(column)будут постоянно кратными CHAR_LENGTH(column)независимо от значения.
eggyal
49

Вероятно, это то, что вы ищете:

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

Он должен возвращать все строки, в которых COLUMN содержит символы, отличные от ASCII (или непечатаемые символы ASCII, такие как новая строка).

Питер Мортенсен
источник
7
У меня отлично работает. «regexp '[^ - ~]'» означает, что в нем есть символ перед пробелом «» или после «~» или ASCII 32–126. Все буквы, числа и символы, но без непечатных вещей.
Джош
Вы даже можете получить его как футболку;) catonmat.net/blog/my-favorite-regex
SamGoody
1
Обратите внимание на предупреждение в документации : « Операторы REGEXPи RLIKEработают побайтно, поэтому они не являются многобайтовыми и могут давать неожиданные результаты с многобайтовыми наборами символов. Кроме того, эти операторы сравнивают символы по их байтовым значениям и символы с диакритическими знаками не могут сравниваться как равные, даже если данное сопоставление рассматривает их как равные. "
eggyal
1
Спасибо за это. что мне интересно, так это как заменить заменяющий символ - например, â
марс-о
1
@ mars-o - черный ромб указывает на недопустимый символ utf8. Больше обсуждения здесь
Рик Джеймс
14

Во всех приведенных выше примерах отсутствует один символ завершения (\ 0). Это невидимо для вывода консоли MySQL и не может быть обнаружено ни одним из вышеупомянутых запросов. Запрос на его поиск очень простой:

select * from TABLE where COLUMN like '%\0%';
Роб Бейли
источник
4

Основываясь на правильном ответе, но с учетом управляющих символов ASCII, решение, которое сработало для меня, таково:

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

Он делает то же самое: ищет нарушения диапазона ASCII в столбце, но позволяет вам также искать управляющие символы, поскольку он использует шестнадцатеричную нотацию для кодовых точек. Поскольку нет сравнения или преобразования (в отличие от ответа @Ollie), это тоже должно быть значительно быстрее. (Особенно, если MySQL выполняет раннее завершение запроса регулярного выражения, что определенно должно быть.)

Это также позволяет избежать возврата полей нулевой длины. Если вам нужна немного более длинная версия, которая может работать лучше, вы можете использовать вместо этого:

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

Он выполняет отдельную проверку длины, чтобы избежать результатов с нулевой длиной, не учитывая их для прохода регулярного выражения. В зависимости от количества имеющихся записей нулевой длины это может быть значительно быстрее.

Обратите внимание: если ваш набор символов по умолчанию является чем-то странным, где 0x00-0xFF не соответствует тем же значениям, что и ASCII (существует ли где-нибудь такой набор символов?), Это вернет ложное срабатывание. В противном случае наслаждайтесь!

Махмуд Аль-Кудси
источник
1
00-FF включает в себя все возможные 8-битные значения, которые REGEXPи проверяются. Следовательно, всегда соответствие гарантировано. Также ^$, вероятно, это не то, что вы хотели.
Рик Джеймс
Определенно лучшее решение REGEXP для поиска всех 8-битных символов, но не такое хорошее, как решение CONVERT (col USING charset), которое также позволяет управлять символами, ограничивая отображаемые символы определенной кодировкой.
Ян
1

Попробуйте использовать этот запрос для поиска записей специальных символов

SELECT *
FROM tableName
WHERE fieldName REGEXP '[^a-zA-Z0-9@:. \'\-`,\&]'
Сэчин
источник
0

Ответ @zende был единственным, который охватывал столбцы со смесью символов ascii и не ascii, но также имел эту проблемную шестнадцатеричную вещь. Я использовал это:

SELECT * FROM `table` WHERE NOT `column` REGEXP '^[ -~]+$' AND `column` !=''
chiliNUT
источник
0

В Oracle мы можем использовать ниже.

SELECT * FROM TABLE_A WHERE ASCIISTR(COLUMN_A) <> COLUMN_A;
Малака Гунавардхана
источник
-2

для этого вопроса мы также можем использовать этот метод:

Вопрос от sql zoo:
Найдите все подробности приза, выигранного ПИТЕРОМ ГРЮНБЕРГОМ

Не-ASCII символы

ans: выберите * from nobel, где победитель вроде "P% GR% _% berg";

hemu123
источник
1
Где связь с вопросом?
Нико Хаасе