Як я можу знайти символи, що не належать до ASCII, у MySQL?


124

Я працюю з базою даних MySQL, яка містить деякі дані, імпортовані з Excel . Дані містять символи, що не належать до ASCII (em-тире та ін.), А також приховані повернення каретки або канали рядків. Чи є спосіб знайти ці записи за допомогою MySQL?


8
Оллі Джонс має набагато кращу відповідь (перевірити нижню частину).
Джонатан Аркелл

1
@JonathanArkell Більше не на дні :)
Brilliand

Виправлення .. перевірити середину! ;)
Джонатан Аркелл

Це відповідь @ Джонатан каже про stackoverflow.com/a/11741314/792066
Braiam

Відповіді:


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
Цей запит знаходить лише всі рядки таблиціName, які не містять буквено-цифрового символу. Це не дає відповіді на запитання.
Роб Бейлі

8
Це стосується стовпців, у яких взагалі відсутні символи ascii, тож вони пропустять ті, у кого поєднуються символи ascii та non-ascii. Відповідь нижче від zende перевіряє на наявність одного або декількох символів, які не мають права. Це мені допомогло здебільшого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 знову ...
Dirk Conrad Coetsee

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
Зверніть увагу на попередження в документації : " і . Оператори працюють в побайтно чином, щоб вони не багатобайтові і можуть привести до непередбачуваних результатів з багатобайтові наборами символів Крім того, ці оператори порівняння символів їх значення байт і символи з наголосом можуть не порівнюватись із рівними, навіть якщо дане порівняння розглядає їх як рівні ".REGEXPRLIKE
eggyal

1
спасибі за це. що мені цікаво, як замінити замінювальний персонаж - наприклад ,
mars-o

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 у стовпці, але дозволяє також шукати контрольні символи, оскільки він використовує шістнадцяткову позначення для кодових точок. Оскільки немає порівняння чи перетворення (на відміну від відповіді @ Оллі), це теж повинно бути значно швидшим. (Особливо, якщо 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 та non ascii, але вона також мала цю проблематичну шестигранну річ. Я використав це:

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


-2

для цього питання ми також можемо використовувати цей метод:

Питання від sql зоопарку:
Знайдіть усі деталі призу, який виграв PETER GRÜNBERG

Не символи ASCII

ans: виберіть * від nobel, де переможець на зразок'P% GR% _% berg ';


1
Де зв’язок із питанням?
Ніко Хааз
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.