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

Posted

技术标签:

【中文标题】如何修复“不正确的字符串值”错误?【英文标题】:How to fix "Incorrect string value" errors? 【发布时间】:2010-11-13 04:09:51 【问题描述】:

在注意到应用程序由于不正确的字符串值错误而倾向于丢弃随机电子邮件后,我尝试并切换了许多文本列以使用 utf8 列字符集和默认列整理 (utf8_general_ci) 以便它接受他们。这修复了大部分错误,并使应用程序在遇到非拉丁电子邮件时也停止收到 sql 错误。

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

内容列是一个MEDIUMTEXT 数据类型,它使用utf8 列字符集和utf8_general_ci 列排序规则。在此列中没有可以切换的标志。

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

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

我考虑过的一件事是在打开二进制标志的情况下切换到 utf8 varchar([some large number]),但我对 mysql 相当陌生,不知道这样的修复是否有意义。

【问题讨论】:

事后分析:RichieHindle's solution 解决了问题,并且在运行时没有引入任何其他问题。这可能有点骇人听闻,但它确实有效,并且让我避免了使用我不完全理解的第 3 方软件弄脏我的手。在这一点上,我们已经更新到一个新版本的软件/架构,它可以正确处理所有这些编码问题(并且足够新以至于它实际上得到了支持),从而使黑客变得不必要。 【参考方案1】:

更新到以下答案:

问这个问题的时候,MySQL 中的“UTF8”表示utf8mb3。同时,添加了utf8mb4,但据我所知,MySQL 的“UTF8”并未切换为表示utf8mb4

这意味着,如果您是认真的,您需要专门输入“utf8mb4”(并且您应该使用utf8mb4

我将把它保留在这里,而不是仅仅编辑答案,以明确说“UTF8”时仍然存在差异

原创

我不建议 Richies 回答,因为您正在搞砸数据库中的数据。您不会解决您的问题,而是尝试“隐藏”它,并且无法对这些垃圾数据执行基本的数据库操作。

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

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

SET NAMES 'utf8mb4';
SET CHARACTER SET utf8mb4;

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

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`
;

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

mysql> show variables like '%colla%';
mysql> show variables like '%charac%';

如果源、传输和目的地是utf8mb4,你的问题就没有了;)

【讨论】:

@Kariem:这很奇怪,因为这个设置被SET NAMES命令覆盖了,相当于调用了SET character_set_client, SET character_set_results, SET character_set_connection dev.mysql.com/doc/refman/5.1/en/charset-connection.html 第二个命令应该是SET CHARACTER SET utf8(不是CHARACTER_SET) 虽然这个答案有助于调查问题,但它没有回答如何解决它。我看到的是“latin1”而不是“utf-8”。 这个答案很好地解释了问题,但在详细说明解决方案方面却很差(这是 OP 所要求的)。 @nicogawenda:为了彻底解决问题,要运行哪些 SQL 查询?如何修复所有预先存在的数据? “如果源、传输和目标是 UTF-8,你的问题就解决了;)”这对我来说是个窍门【参考方案2】:

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

如果您需要存储来自更高 Unicode 平面的值,则需要 utf8mb4 encodings。

【讨论】:

我认为这可能是最好的解决方法。升级到 5.5 并在上述答案中将 utf8 替换为 utf8mb4。我从 Twitter 插入 utf8 数据,其中包含表情符号或其他需要 4 个字节的字符。 假设我们不会升级到 5.5。我们如何抑制错误? 对于这个最有用的答案,我滚动得太远了 距离最初的问题已有 10 年了。让我们知道 MySQL 的 utf8 编码不是正确的 utf8。使用 utf8mb4! MariaDB 也是如此。否则你不会有喜悦的泪水? 这是最好的解决方法。即使在 2021 年!【参考方案3】:

表格和字段编码错误;但是,您可以将它们转换为 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;

【讨论】:

我认为这是所有正确答案。我有两个表,每个表都有一个 utf8 varchar 格式。其中一个有错误,另一个很好。即使我用户“更新选择”从“好”utf8 列复制到另一个表,也会发生同样的错误。这是因为这两个表是在不同版本的 MySQL 中创建的。 是的!这也是我的数据库表中的错误配置。我认为这个答案应该是正确的。我的问题是选择的排序规则是 utf8_unicode_ci 而不是 utf8_general_ci。谢谢:) 这个答案在这里做什么,应该在顶部 这个有帮助,它告诉你应该尝试什么,而不是什么可能出错。 谢谢!它对我帮助很大 【参考方案4】:

"\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

如果您正在寻找一种方法来避免数据库中的解码错误,cp1252 编码(又名“Windows-1252”又名“Windows 西欧”)是最宽松的编码 - 每个字节值都是有效的代码点。

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

【讨论】:

你的意思是,“当然它不会再理解真正的 UTF-8 了?” @Brian:如果你告诉它你给它 cp1252,而你实际上给它 UTF-8,比如说,café,它会误解为café。它不会崩溃,但它会误解高位字符。 @Richie:数据库可以随意调用数据,但如果抓取它的 php 代码将其填充到字符串中,那不会有太大区别……会吗?我看不出对 UTF-8 缺乏理解的确切影响。 @Brian:不,你是对的。它会产生影响的时间将在数据库中,例如,如果您在 SQL 中使用 ORDER BY 子句 - 在您有非 ASCII 字符的地方排序会很不稳定。 请将此答案取消标记为解决方案,隐藏错误不是任何解决方案。从你的车上取下过热灯,你会看到。【参考方案5】:

我今天通过将列更改为存储原始字节而不是 UTF-8 字符的“LONGBLOB”类型解决了这个问题。

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

有关 TEXT/LONGTEXT 和 BLOB/LONGBLOB 之间区别的更多详细信息,请参阅此页面 http://dev.mysql.com/doc/refman/5.0/en/blob.html。网络上还有许多其他争论在讨论这两者。

【讨论】:

这个解决方案似乎是最简单的方法。我尝试了其他几种编码都没有成功。【参考方案6】:

首先检查你的 default_character_set_name 是否为 utf8。

SELECT default_character_set_name FROM information_schema.SCHEMATA S WHERE schema_name = "DBNAME";

如果结果不是 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

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

ALTER DATABASE DBNAME CHARACTER SET utf8 COLLATE utf8_general_ci;

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

【讨论】:

【参考方案7】:

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

当我有 TRIGGER 时出现此错误,由于某种原因它继承了服务器的排序规则。 mysql 的默认值是(至少在 Ubuntu 上)带有瑞典排序规则的 latin-1。 即使我将数据库和所有表都设置为 UTF-8,我还没有设置 my.cnf:

/etc/mysql/my.cnf:

[mysqld]
character-set-server=utf8
default-character-set=utf8

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

select TRIGGER_SCHEMA, TRIGGER_NAME, CHARACTER_SET_CLIENT, COLLATION_CONNECTION, DATABASE_COLLATION from information_schema.TRIGGERS

这里列出的一些变量也应该有 utf-8-*(没有 latin-1 或其他编码):

show variables like 'char%';

【讨论】:

【参考方案8】:

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

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)  
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

【讨论】:

【参考方案9】:

我遇到了类似的错误 (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)只是剪切了一个没有错误的文本。

【讨论】:

MySQL 我也厌倦了很多东西,意识到这个版本的 mysql 不支持 4 字节 utf-8 解码,并且很想了解是什么原因造成的。改变类型显然是答案,一个立竿见影的解决方案。【参考方案10】:

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

在实践中,后一个问题是由 MySQL UTF-8 实现引起的,该实现只支持以 UTF-8 表示时需要 1-3 个字节的 UNICODE 字符。有关详细信息,请参阅"Incorrect string value" when trying to insert UTF-8 into MySQL via JDBC?。诀窍是使用列类型utf8mb4 而不是类型utf8,尽管名称实际上并不支持所有UTF-8。前一种类型是适用于所有 UTF-8 字符串的正确类型。

【讨论】:

【参考方案11】:

当我遇到这个不正确的字符串值:'\xF8' for column error using scriptcase 时,我的解决方案是确保我的数据库是为 utf8 通用 ci 设置的,我的字段排序规则也是如此。然后,当我对 csv 文件进行数据导入时,我将 csv 加载到 UE Studio 中,然后将其保存为 utf8 格式,瞧!它就像一个魅力,有 29000 条记录,没有错误。以前我试图导入一个 excel 创建的 csv。

【讨论】:

【参考方案12】:

我已经尝试了上述所有解决方案(它们都带来了有效的分数),但没有什么对我有用。

直到我发现我在 C# 中的 MySQL 表字段映射使用了不正确的类型:MySqlDbType.Blob。我把它改成了 MySqlDbType.Text,现在我可以写出我想要的所有 UTF8 符号了!

附言我的 MySQL 表字段属于“LongText”类型。但是,当我使用 MyGeneration 软件自动生成字段映射时,它会自动将字段类型设置为 C# 中的 MySqlDbType.Blob。

有趣的是,我已经使用带有 UTF8 字符的 MySqlDbType.Blob 类型数月来没有遇到任何问题,直到有一天我尝试编写一个包含一些特定字符的字符串。

希望这对正在努力寻找错误原因的人有所帮助。

【讨论】:

【参考方案13】:

在我的情况下,Incorrect string value: '\xCC\x88'...,问题在于 o-umlaut 处于分解状态。 This question-and-answer 帮助我理解了 ö 之间的区别。在 PHP 中,我的解决方法是使用 PHP's Normalizer library。例如,Normalizer::normalize('o¨', Normalizer::FORM_C)

【讨论】:

【参考方案14】:

我在列名前添加了二进制并解决了字符集错误。

插入tableA值(二进制字符串colname1);

【讨论】:

【参考方案15】:

您好,当我使用 Godaddy 服务器上的在线数据库时,我也遇到了这个错误 我认为它具有 5.1 或更高版本的 mysql 版本。但是当我从本地服务器(版本 5.7)执行此操作时,我从本地服务器创建表并使用 mysql yog 复制到在线服务器我认为问题出在字符集上

Screenshot Here

【讨论】:

【参考方案16】:

为了修复这个错误,我将我的 MySQL 数据库升级到了支持完整 Unicode 字符集的 utf8mb4,遵循 this detailed tutorial。我建议仔细阅读它,因为有很多陷阱(例如,索引键可能会由于新编码而变得太大,之后您必须修改字段类型)。

【讨论】:

【参考方案17】:

这里有很好的答案。我只是添加我的,因为我遇到了同样的错误,但事实证明这是一个完全不同的问题。 (也许表面上相同,但根本原因不同。)

对我来说,以下字段发生了错误:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
private URI consulUri;

这最终作为URI 类的二进制序列化存储在数据库中。这并没有引发单元测试(使用 H2)或 CI/集成测试(使用 MariaDB4j)的任何标志,它在我们类似生产的设置中爆炸了。 (不过,一旦理解了问题,就很容易在 MariaDB4j 实例中看到错误的值;它只是没有破坏测试。)解决方案是构建一个自定义类型映射器:

package redacted;

import javax.persistence.AttributeConverter;
import java.net.URI;
import java.net.URISyntaxException;

import static java.lang.String.format;

public class UriConverter implements AttributeConverter<URI, String> 
    @Override
    public String convertToDatabaseColumn(URI attribute) 
        return attribute.toString();
    

    @Override
    public URI convertToEntityAttribute(String field) 
        try 
            return new URI(field);
        
        catch (URISyntaxException e) 
            throw new RuntimeException(format("could not convert database field to URI: %s", field));
        
    

如下使用:

@Column(nullable = false, columnDefinition = "VARCHAR(255)")
@Convert(converter = UriConverter.class)
private URI consulUri;

就涉及到 Hibernate 而言,它似乎有一堆provided type mappers,包括java.net.URL,但没有java.net.URI(这是我们这里需要的)。

【讨论】:

【参考方案18】:

在我的情况下,通过将 Mysql 列编码更改为“二进制”来解决问题(数据类型将自动更改为 VARBINARY)。可能我无法使用该列进行过滤或搜索,但我不需要。

【讨论】:

【参考方案19】:

如果您碰巧在保存之前使用某个字符串函数处理了该值,请确保该函数可以正确处理多字节字符。无法做到这一点并且尝试截断的字符串函数可能会在中间拆分单个多字节字符之一,这可能会导致此类字符串错误情况。

例如,在 PHP 中,您需要从 substr 切换到 mb_substr

【讨论】:

【参考方案20】:

就我而言,首先我遇到了一个'???'在我的网站中,然后我检查了Mysql的字符集,现在是拉丁文,所以我将其更改为utf-8,然后我重新启动我的项目,然后我遇到了同样的错误,然后我发现我忘记更改数据库的字符集换成 utf-8,嘭,成功了。

【讨论】:

【参考方案21】:

我几乎尝试了这里提到的每一个步骤。没有工作。下载了mariadb。有效。我知道这不是解决方案,但这可能有助于某人快速识别问题或提供临时解决方案。

Server version: 10.2.10-MariaDB - MariaDB Server
Protocol version: 10
Server charset: UTF-8 Unicode (utf8)

【讨论】:

【参考方案22】:

1 - 您必须在您的连接中声明编码 UTF8 的属性。 http://php.net/manual/en/mysqli.set-charset.php.

2 - 如果您使用 mysql commando line 执行脚本,则必须使用标志,例如: Cmd: C:\wamp64\bin\mysql\mysql5.7.14\bin\mysql.exe -h localhost -u root -P 3306 --default-character-set=utf8 omega_empresa_parametros_336 &lt; C:\wamp64\www\PontoEletronico\PE10002Corporacao\BancoDeDadosModelo\omega_empresa_parametros.sql

【讨论】:

以上是关于如何修复“不正确的字符串值”错误?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL抛出不正确的字符串值错误

在 MySQL 中存储 emoji 得到不正确的字符串值错误

从 MS SQL-Server 迁移数据库时出现 MYSQL Workbench“不正确的字符串值”错误

SQL Server - MySQL 迁移错误:不正确的字符串值:'\xF4\x80\x82\x83...'

错误 1366 (HY000):不正确的字符串值:第 1 行的列 'comment' 的 '\xF0\x9F\x98\x9C'

不正确的字符串值:列的“\xEF\xBF\xBD”