如何修复"不正确的字符串值"错误?

Bri*_*ian 152 mysql

在注意到由于错误的字符串值错误导致应用程序倾向于丢弃随机电子邮件之后,我通过并切换了许多文本列以使用utf8列字符集和默认列collat​​e(utf8_general_ci)以便它接受它们.这解决了大多数错误,并使应用程序在遇到非拉丁语电子邮件时也停止获取sql错误.

尽管如此,一些电子邮件仍然导致程序命中错误的字符串值错误: (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

contents列是一个MEDIUMTEXTdatatybe,它使用utf8列charset和utf8_general_ci列collat​​e.我没有可以在此列中切换的标记.

请记住,除非绝对必要,否则我不想触摸甚至查看应用程序源代码:

  • 是什么导致了这个错误?(是的,我知道电子邮件中充满了随机垃圾,但我认为utf8会非常宽松)
  • 我该如何解决?
  • 这种修复的可能影响是什么?

我考虑过的一件事是在打开二进制标志的情况下切换到utf8 varchar([某些大数字]),但我对MySQL很不熟悉,并且不知道这样的修复是否有意义.

nic*_*nda 127

我不建议Richies回答,因为你搞砸了数据库里面的数据.你不会解决你的问题,但试图"隐藏"它,而不能用垃圾数据执行必要的数据库操作.

如果您遇到此错误,您发送的数据不是UTF-8编码,或者您的连接不是UTF-8.首先,验证数据源(文件,...)确实是UTF-8.

然后,检查数据库连接,连接后应该这样做:

SET NAMES 'utf8';
SET CHARACTER SET utf8;
Run Code Online (Sandbox Code Playgroud)

接下来,验证存储数据的表是否具有utf8字符集:

SELECT
  `tables`.`TABLE_NAME`,
  `collations`.`character_set_name`
FROM
  `information_schema`.`TABLES` AS `tables`,
  `information_schema`.`COLLATION_CHARACTER_SET_APPLICABILITY` AS `collations`
WHERE
  `tables`.`table_schema` = DATABASE()
  AND `collations`.`collation_name` = `tables`.`table_collation`
;
Run Code Online (Sandbox Code Playgroud)

最后,检查您的数据库设置:

mysql> show variables like '%colla%';
mysql> show variables like '%charac%';
Run Code Online (Sandbox Code Playgroud)

如果源,传输和目的地是UTF-8,你的问题就消失了;)

  • 虽然这个答案有助于调查问题,但它没有回答如何解决问题.我看到"latin1"而不是"utf-8". (6认同)
  • 第二个命令应该是`SET CHARACTER SET utf8`(不是CHARACTER_SET) (2认同)
  • 这个答案非常适合解释这个问题但很难详细说明解决方案(这就是OP所要求的).@nicogawenda:为了完全解决问题,要运行哪些SQL查询?如何修复所有预先存在的数据? (2认同)
  • “如果源、传输和目的地是 UTF-8,你的问题就消失了;)”这对我来说是诀窍 (2认同)

moe*_*fju 73

MySQL的utf-8类型实际上并不适合utf-8 - 它每个字符最多只使用三个字节,并且仅支持基本多语言平面(即没有表情符号,没有星体平面等).

如果需要存储更高Unicode平面的值,则需要utf8mb4编码.

  • 我认为这可能是最好的解决办法.升级到5.5并在上面的答案中用utf8mb4替换utf8.我从Twitter插入了utf8数据,其中有emojis或其他需要4个字节的字符. (8认同)
  • 距离最初的问题已经 10 年了。让大家知道 MySQL 的 utf8 编码不是正确的 utf8。使用utf8mb4!MariaDB 也是如此。否则你不能有喜悦的泪水 (2认同)

小智 44

表和字段的编码错误; 但是,您可以将它们转换为UTF-8.

ALTER TABLE logtest CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

ALTER TABLE logtest CHANGE title title VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci;
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是所有人的正确答案。我有两个表,每个表都有 utf8 varchar 格式。其中一个出错,另一个没问题。即使我用户“更新选择”从“好”utf8 列复制到另一个表,也会发生同样的错误。这是因为这两个表是在不同版本的 MySQL 中创建的。 (2认同)
  • 这个答案在这里做什么,应该在顶部 (2认同)
  • 这个很有帮助,它告诉你要尝试什么,而不是可能出错的地方。 (2认同)

Ric*_*dle 38

"\xE4\xC5\xCC\xC9\xD3\xD8"是无效的UTF-8.使用Python测试:

>>> "\xE4\xC5\xCC\xC9\xD3\xD8".decode("utf-8")
...
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2: invalid data
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找一种避免解码数据库中错误的方法,那么cp1252编码(又名"Windows-1252"又名"Windows Western European")是最宽松的编码 - 每个字节值都是有效的代码点.

当然,它不会再理解真正的UTF-8,也不会理解任何其他非cp1252编码,但听起来你并不太关心它?

  • 请取消标记此答案作为解决方案,隐藏错误不是任何解决方案.从车上取下过热灯,你会看到. (8认同)
  • @Brian:不,你说得对.它会产生差异的时间是在数据库中,例如,如果在SQL中使用了ORDER BY子句 - 在非ASCII字符的情况下排序会很糟糕. (7认同)
  • 究竟是什么意思,"当然,它不会再理解真正的UTF-8了?" (4认同)
  • @Brian:如果你告诉它你正在给它cp1252,你实际上给它的UTF-8,比如说,'café`,它会误解为'café`.它不会崩溃,但它会误解高位字符. (4认同)
  • @Richie:数据库可以随心所欲地调用数据,但是如果抓住它的php代码将它填充到一个字符串中,那就不会有太大的区别......是吗?我没有看到对UTF-8缺乏理解产生影响的确切位置. (3认同)
  • @Gaelle:如果数据库“由[您的]应用程序生成和管理”,那么您应该确保只向其提供有效的UTF-8,并且您不会看到此问题。没有办法“关闭”一条告诉您正在执行无效操作的消息 - 如果您承诺 UTF-8 但提供其他内容,数据库将正确拒绝它。 (2认同)
  • 对于任何偶然发现这个答案的人:__这在所有方面都是完全错误的__。即使“演示”字符串不是“有效的 utf8”也是完全错误的,无论 python 版本如何(在 2.7 中,您应该使用 unicode 字符串,在这两种情况下,正确的操作都是 __encode__ 为 utf8。 (2认同)

fra*_*aka 21

我今天通过将列更改为'LONGBLOB'类型来解决此问题,该类型存储原始字节而不是UTF-8字符.

这样做的唯一缺点是你必须自己处理编码.如果您的应用程序的一个客户端使用UTF-8编码而另一个客户端使用CP1252,则可能会使用不正确的字符发送您的电子邮件.为避免这种情况,请始终在所有应用程序中使用相同的编码(例如UTF-8).

有关TEXT/LONGTEXT和BLOB/LONGBLOB之间差异的更多详细信息,请参阅此页面http://dev.mysql.com/doc/refman/5.0/en/blob.html.网上还有许多其他论点在讨论这两个问题.

  • 这个解决方案似乎是最简单的方法。我尝试了一些其他编码但没有成功。 (3认同)

Ond*_*žka 8

通常,当您将字符串插入具有不兼容的编码/排序规则的列时会发生这种情况.

当我有TRIGGER时出现这个错误,TRIGGER由于某种原因继承了服务器的排序规则.并且mysql的默认值是(至少在Ubuntu上)latin-1和swedish collat​​ion.即使我有数据库和所有表设置为UTF-8,我还没有设置my.cnf:

/etc/mysql/my.cnf:

[mysqld]
character-set-server=utf8
default-character-set=utf8
Run Code Online (Sandbox Code Playgroud)

这必须用utf8-*列出所有触发器:

select TRIGGER_SCHEMA, TRIGGER_NAME, CHARACTER_SET_CLIENT, COLLATION_CONNECTION, DATABASE_COLLATION from information_schema.TRIGGERS
Run Code Online (Sandbox Code Playgroud)

并且由此列出的一些变量也应该具有utf-8-*(没有latin-1或其他编码):

show variables like 'char%';
Run Code Online (Sandbox Code Playgroud)


小智 7

首先检查default_character_set_name是否为utf8.

SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = "DBNAME";
Run Code Online (Sandbox Code Playgroud)

如果结果不是utf8,则必须转换数据库.首先,您必须保存转储.

要将指定数据库中的所有表的字符集编码更改为UTF-8,请在命令行中键入以下命令.将DBNAME替换为数据库名称:

mysql --database=DBNAME -B -N -e "SHOW TABLES" | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' | mysql --database=DBNAME
Run Code Online (Sandbox Code Playgroud)

要将数据库本身的字符集编码更改为UTF-8,请在mysql >提示符下键入以下命令.将DBNAME替换为数据库名称:

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;
Run Code Online (Sandbox Code Playgroud)

您现在可以重试将utf8字符写入数据库.当我尝试将200000行csv文件上传到我的数据库时,此解决方案可以帮助我.


Sam*_*ghe 6

虽然您的排序规则设置为utf8_general_ci,但我怀疑数据库,表格甚至列的字符编码可能不同.

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)  
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
Run Code Online (Sandbox Code Playgroud)


Mik*_*nen 5

该错误意味着您的字符串编码不正确(例如,您尝试将 ISO-8859-1 编码字符串输入到 UTF-8 编码列中),或者该列不支持您尝试输入的数据。

实际上,后一个问题是由 MySQL UTF-8 实现引起的,该实现仅支持以 UTF-8 表示时需要 1-3 个字节的 UNICODE 字符。尝试通过 JDBC 将 UTF-8 插入 MySQL 时,请参阅“不正确的字符串值”?详情。诀窍是使用列类型utf8mb4而不是类型utf8,尽管名称实际上并不支持所有 UTF-8。前一种类型是用于所有 UTF-8 字符串的正确类型。


小智 5

我遇到了类似的错误 ( Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1)。我试图将列的字符集更改为utf8mb4,之后错误已更改为'Data too long for column 'content' at row 1'.
原来,mysql 向我显示了错误的错误。我将列的字符集转回,并将列的utf8类型更改为MEDIUMTEXT. 之后,错误消失了。
我希望它可以帮助某人。
顺便说一句,MariaDB 在相同的情况下(我在那里测试了相同的 INSERT)只是剪切了一个文本而没有错误。