如何解决“字符串值错误”错误?


162

在注意到一个应用程序倾向于由于不正确的字符串值错误而丢弃随机电子邮件之后,我仔细检查并切换了许多文本列,以使用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并不熟悉,也不知道这样的修复是否有意义。


3
验后:RichieHindle的解决方案解决了该问题,并且在运行时未引入任何其他问题。可能有点骇客,但它确实起作用,并让我避免使用我不完全了解的第三方软件。在这一点上,我们已经更新了软件/模式的更新版本,可以正确处理所有这些编码问题(并且足够新,可以实际支持),因此无需进行黑客攻击。
布莱恩

Answers:


43

"\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 Western European”)是最宽松的编码-每个字节值都是一个有效的代码点。

当然,它不再会理解真正的UTF-8,也不会理解任何其他非cp1252编码,但是听起来您不太在意这一点?


4
您到底是什么意思,“当然不再要了解真正的UTF-8了吗?”
布赖恩

5
@Brian:如果您告诉您它给的是cp1252,而您实际上给它的是UTF-8,例如café,它将被误解为café。它不会崩溃,但是会误解高位字符。
RichieHindle

3
@Richie:数据库可以随心所欲地调用数据,但是如果抓取到它的php代码将其塞入字符串中,那不会有太大的不同……会吗?我不知道缺乏对UTF-8的理解会在哪里产生影响。
布赖恩

7
@布赖恩:不,你是对的。差异发生的时间将发生在数据库中,例如,如果您在SQL中使用了ORDER BY子句,则在您具有非ASCII字符的地方排序会很奇怪。
RichieHindle

11
请取消标记此答案作为解决方案,隐藏错误不是任何解决方案。从汽车上卸下过热灯,您将看到。
David Vartanian

133

我不建议Richies回答,因为您正在破坏数据库中的数据。您将无法解决问题,但会尝试“隐藏”该问题,并且无法使用受限数据执行基本的数据库操作。

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

然后,检查数据库连接,连接后应执行以下操作:

SET NAMES 'utf8';
SET CHARACTER SET utf8;

接下来,验证存储数据的表是否具有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`
;

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

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

如果源,传输和目标是UTF-8,则您的问题就不存在了;)


1
@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
nico gawenda 2013年

2
第二个命令应该是SET CHARACTER SET utf8(not CHARACTER_SET)
编码器

6
尽管此答案有助于调查问题,但并不能解决该问题。我看到的是“ latin1”而不是“ utf-8”。
Vanuan 2014年

2
这个答案很好地解释了问题,但是在详细说明解决方案(这是OP所要求的)方面却非常糟糕。@nicogawenda:要完全解决问题,要运行哪些SQL查询?如何修复所有现有数据?
克林特·伊斯特伍德

1
“如果源,运输和目的地都是UTF-8,那么您的问题
就不

80

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

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


9
我认为这可能是最好的解决方法。升级到5.5,并在上述答案中将utf8替换为utf8mb4。我正在从Twitter插入utf8数据,其中包含表情符号或其他需要4个字节的字符。
rmarscher 2014年

假设我们不会升级到5.5。我们如何抑制错误?
用户

我滚动路太远了这个最有用的答案
handheldblender

1
自原始问题以来的10年。众所周知,MySQL的utf8编码是不正确的utf8。使用utf8mb4!MariaDB也是如此。否则,您就无法拥有喜悦的眼泪😂–
Liam

51

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

1
我认为这是所有人的正确答案。我有两个表,每个表都有一个utf8 varchar格式。其中一个收到错误,另一个很好。即使我用户'update select'将'good'utf8列中的副本复制到另一个表中,也会发生相同的错误。这是因为两个表是在不同版本的MySQL中创建的。
爱世光

是! 这也是我数据库表中的配置错误。我认为这个答案应该是正确的。我的问题是所选的排序规则是utf8_unicode_ci而不是utf8_general_ci。谢谢:)
jprivillaso

2
这里的答案是什么,应该放在顶部
Sagun Shrestha

1
这对您有所帮助,它会告诉您要尝试什么,而不是什么可能是错误的。
维克多·迪

谢谢!它改变了我的表排序规则蚂蚁,这对我很有帮助,我认为应该这样做,但是字段仍然是ascii排序规则……
Radu

25

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

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

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


1
这种解决方案似乎是最简单的方法。我尝试了其他几种编码,但均未成功。
Simeon Abolarinwa'2

10

首先检查您的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文件上传到数据库中时,此解决方案对我有帮助。


8

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

当我有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%';

6

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

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

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)只是剪切了一个文本而没有错误。


MySQL我也太累了,意识到这个版本的mysql不支持4字节utf-8编码,并且非常想了解是什么原因造成的。答案显然是改变类型,这是一个立即的解决方案。
丽莎


2

当遇到此错误字符串值:'\ xF8'(使用脚本案例解决列错误)时,对我的解决方案是确保我的数据库设置为utf8 general ci,而我的字段归类也是如此。然后,当我导入csv文件的数据时,我将csv加载到UE Studio中,然后将其保存为utf8和Voila格式!它像一个超级按钮一样工作,其中29000条记录没有错误。以前,我尝试导入Excel创建的csv。


2

我已经尝试了上述所有解决方案(都带来了有效的观点),但是没有任何工作对我有用。

直到发现C#中的MySQL表字段映射使用了错误的类型:MySqlDbType.Blob。我将其更改为MySqlDbType.Text,现在我可以编写所有想要的UTF8符号了!

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

有趣的是,我使用UTF8字符的MySqlDbType.Blob类型已经好几个月了,没有麻烦,直到有一天我尝试编写包含某些特定字符的字符串。

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


1

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

插入tableA值(二进制stringcolname1);


1

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

屏幕截图在这里


1

要解决此错误,请按照本详细教程将MySQL数据库升级到支持完整Unicode字符集的utf8mb4 。我建议仔细检查它,因为其中有很多陷阱(例如,由于新的编码,索引键可能变得太大,之后您必须修改字段类型)。


1

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

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

@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而言,似乎有很多提供的类型映射器,包括for java.net.URL,但没有for java.net.URI(这是我们在这里需要的)。


1

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

例如,在PHP中,您需要从切换substrmb_substr


0

就我而言,首先我遇到一个“ ???” 在我的网站上,然后我检查了现在是拉丁的Mysql字符集,因此我将其更改为utf-8,然后重新启动我的项目,然后遇到相同的错误,然后我发现我忘记更改数据库的字符集然后换成utf-8,繁荣,它奏效了。


0

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

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

0

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


0

在我的情况下,Incorrect string value: '\xCC\x88'...问题是o型变音符号处于分解状态。这个问题和解答帮助我理解之间的差异ö。在PHP中,对我而言,解决方法是使用PHP的Normalizer库。例如Normalizer::normalize('o¨', Normalizer::FORM_C)


-2

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

2-如果使用mysql命令行执行脚本,则必须使用标志,例如: 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 < C:\wamp64\www\PontoEletronico\PE10002Corporacao\BancoDeDadosModelo\omega_empresa_parametros.sql

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.