Как мне найти в 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])*$';

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


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` !=''


-2

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

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

Не-ASCII символы

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


1
Где связь с вопросом?
Нико Хаасе
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.