如何在MySQL中找到非ASCII字符?


124

我正在使用从Excel导入一些数据的MySQL数据库。数据包含非ASCII字符(破折号等)以及隐藏的回车符或换行符。有没有办法使用MySQL查找这些记录?


8
奥利·琼斯(Ollie Jones)有一个更好的答案(请检查底部)。
乔纳森·阿奎尔

1
@JonathanArkell不再不在底部了:)
Brilliand

更正..检查中间!;)
Jonathan Arkell

这是答案@Jonathan在谈论stackoverflow.com/a/11741314/792066
Braiam

Answers:


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 \。,\-]';
2009年

3
@Tooony不,在集合内,句号仅表示自身,而破折号在其他字符之间仅具有特殊含义。在集合的最后,它仅表示自身。
Michael Speer 2012年

10
此查询仅查找tableName中不包含字母数字字符的所有行。这不能回答问题。
罗伯·贝利

8
那是针对根本没有任何ascii字符的列,因此它将错过那些混合了ascii和非ascii字符的列。zende的以下答案将检查一个或多个非ASCII字符。这在很大程度上帮助了我SELECT * FROM tbl WHERE colname NOT REGEXP '^[A-Za-z0-9\.,@&\(\) \-]*$';
Frank Forte 2015年

1
(无论如何对我来说)这仅适用于查找不包含这些字符的字符串。它找不到包含ASCII和非ASCII字符混合的字符串。
伊恩

236

MySQL提供了全面的字符集管理,可以帮助解决此类问题。

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

CONVERT(col USING charset)功能将不可转换的字符转换为替换字符。这样,转换后的文本和未转换的文本将不相等。

看到这个更多的讨论。https://dev.mysql.com/doc/refman/8.0/zh-CN/charset-repertoire.html

您可以使用任何希望的字符集名称代替ASCII。例如,如果要在代码页1257(立陶宛语,拉脱维亚语,爱沙尼亚语)中找出哪些字符不能正确呈现,请使用CONVERT(columnToCheck USING cp1257)


20
这是解决此问题的极好方法,并且更加可靠。
CraigDouglas 2012年

5
这对于查找带有重音符号(
áä

3
比使用REGEXP更好(对于我来说,寻找重音似乎不起作用),并且还提供了一种简单的机制来再次使所有的ascii ...
Dirk Conrad Coetsee

1
这个答案奇妙的作品,并会弹出包含任何非ASCII字符,而不是只包含字符串的字符串非ASCII字符。谢谢!
伊恩(Ian)

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 )
2012年

15
-1 这会产生错误的结果。 例如,假设某人的UTF-16列包含'ā'(由字节序列编码0x0101)-在此测试中将其视为“ ASCII”:假阴性;实际上,某些字符集未在其中编码ASCII字符0x000x7f因此此解决方案将产生误报。 不要仅仅依靠这个答案!
eggyal 2014年

2
@sun:这根本没有帮助-许多字符集都是固定长度的,因此无论值如何,LENGTH(column)它都是常数倍CHAR_LENGTH(column)
eggyal 2014年

49

这可能是您要寻找的:

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

它应返回COLUMN包含非ASCII字符(或不可打印的ASCII字符,例如换行符)的所有行。


7
对我来说很棒。“ regexp'[^-〜]'”表示其字符位于空格“”之前或“〜”或ASCII 32-126之后。所有字母,数字和符号,但没有不可打印的内容。
乔什

您甚至可以将其作为T恤衫来获得;) catonmat.net/blog/my-favorite-regex
SamGoody

1
注意警告的文件:“ REGEXPRLIKE。运营商在逐字节的方式工作,所以它们不是多字节安全和可能产生的多字节字符集意想不到的效果另外,这些运营商通过它们的字节值进行比较的字符和即使给定的归类将带重音符号的字符视为相等,也是如此。
eggyal 2014年

1
谢谢你 我想知道的是如何替换替换字符-例如
mars-o

1
@ mars-o-黑色菱形表示无效的utf8字符。这里有
Rick James

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。因此,保证总是匹配。也^$可能不是您想要的。
里克·詹姆斯

绝对是找到所有8位字符的最佳REGEXP解决方案,但不如CONVERT(col USING字符集)解决方案那样好,该解决方案还可以控制字符,同时将显示字符限制为特定字符集。
伊恩

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 zoo的问题:
查找由PETERGRÜNBERG赢得的奖金的所有详细信息

非ASCII字符

回答:从诺贝尔奖获得者*“ P%GR%_%berg”等获胜者;


1
问题的联系在哪里?
Nico Haase
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.