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

在注意到一个应用程序由于不正确的字符串值错误而倾向于丢弃随机的电子邮件之后,我尝试切换了许多文本列,使用 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 ([一些大数字]) ,但是我对 MySQL 相当不熟悉,并且不知道这样的修复是否有意义。

433667 次浏览

"\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编码,但是听起来您似乎并不太关心这个问题?

在使用 scriptcase 运行这个错误的字符串值: “ xF8”表示列错误时,我的解决方案是确保我的数据库设置为 utf8 general ci,字段排序也是如此。然后,当我做我的数据导入一个 csv 文件,我加载到 UE 工作室的 csv,然后保存为 utf8和瞧!它的工作像一个魅力,29000记录在那里没有错误。之前我试图导入一个 Excel 创建的 csv。

更新的回答如下:

问这个问题的时候,“ UTF8”在 MySQL 中的意思是 utf8mb3。与此同时,增加了 utf8mb4,但据我所知,MySQL 的“ UTF8”没有切换到意味着 utf8mb4

这意味着,如果您是认真的,那么您需要特别输入“ utf8mb4”(并且您应该使用 utf8mb4)

我将把这个保留在这里,而不是仅仅编辑答案,以表明在说“ UTF8”时仍然有区别

原创的

我不建议里奇回答,因为你正在搞砸数据库中的数据。您不会修复您的问题,但是会尝试“隐藏”它,并且无法对废弃的数据执行必要的数据库操作。

如果遇到此错误,则发送的数据不是 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,那么问题就解决了;)

一般情况下,如果向编码/排序不兼容的列插入字符串,就会发生这种情况。

当我使用 TRIGGER 时,我得到了这个错误,由于某种原因,它继承了服务器的排序规则。 Mysql 的默认值是(至少在 Ubuntu 上是)带有瑞典排序的拉丁 -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-* (没有拉丁文 -1或其他编码) :

show variables like 'char%';

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

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

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

我已经尝试了以上所有的解决方案(它们都带来了有效的点) ,但没有一个对我有效。

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

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

有趣的是,我一直在使用 MySqlDbType。Blob 使用 UTF8字符输入了好几个月,没有遇到任何麻烦,直到有一天我尝试编写一个包含一些特定字符的字符串。

希望这能帮助那些正在努力寻找错误原因的人。

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

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

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

如果需要存储来自较高 Unicode 平面的值,则需要使用 Utf8mb4编码

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

插入到 tableA 值中(二进制 stringcolname1) ;

对我来说,首先我遇到了一个在我的网站,然后我检查了 Mysql 的字符集,现在是拉丁文,所以我把它改成了 utf-8,然后我重新启动我的项目,然后我得到了同样的错误,然后我发现我忘了改变数据库的字符集,并且改成了 utf-8,嘣,它工作了。

首先检查 default _ role _ 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 文件到我的数据库。

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

ALTER TABLE tabale_name MODIFY COLUMN column_name VARCHAR(255)
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
我得到了一个类似的错误(Incorrect string value: '\xD0\xBE\xDO\xB2. ...' for 'content' at row 1)。我尝试将列的字符集改为 utf8mb4,然后错误改为 'Data too long for column 'content' at row 1'。< br > 结果 mysql 给我显示了错误的错误。将列的字符集返回到 utf8,并将列的类型改为 MEDIUMTEXT。之后,错误消失了。< br > 我希望它能帮到别人 顺便说一下,MariaDB 在同样的情况下(我在那里测试了相同的 INSERT)只是剪切了一个文本而没有错误。

表和字段有错误的编码; 但是,您可以将它们转换为 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;
嗨,当我使用 Godaddy 服务器上的在线数据库时,也出现了这个错误 我认为它有 mysql 版本的5.1或更多。但是,当我从我的本地主机服务器(版本5.7) ,这是罚款后,我从本地服务器创建的表格和复制到在线服务器使用 mysql yog 我认为问题是字符集

截图: http://i.stack.imgur.com/5JC3u.jpg

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

< p > 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

为了修复这个错误,我将 MySQL 数据库升级到 utf8mb4,它支持按照 这个详细的教程设置的完整 Unicode字符。我建议仔细检查它,因为有相当多的陷阱(例如,索引键可能变得太大,由于新的编码之后,你必须修改字段类型)。

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

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

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

我几乎尝试了这里提到的每一个步骤。都没用。下载 Mariadb。成功了。我知道这不是一个解决方案,但这可能有助于人们迅速发现问题或给出一个临时的解决方案。

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

在我的例子中,通过将 Mysql 列编码更改为“二进制”(数据类型将自动更改为 VARBINARY)解决了这个问题。也许我不能使用该列进行过滤或搜索,但我不需要它。

在我的案例 Incorrect string value: '\xCC\x88'...中,问题是元音变音处于分解状态。这个问答帮助我理解了 ö之间的区别。在 PHP 中,我的解决方案是使用 PHP 的 Normalizer 库。例如 Normalizer::normalize('o¨', Normalizer::FORM_C)

如果在保存之前碰巧用某个字符串函数处理该值,请确保该函数能够正确处理多字节字符。不能这样做的字符串函数,例如,尝试截断的字符串函数可能会将中间的一个多字节字符分割开来,从而导致出现这种字符串错误的情况。

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

我有一个带有 varbinary列的表,我想将其转换为 utf8mb4varchar。遗憾的是,现有的一些数据是无效的 UTF-8,并且 ALTER查询为不同的行返回 Incorrect string value

我尝试了所有我能找到的关于 cast/convert/char_length = length等的建议,但是没有在 SQL 中检测到错误的值,除了 ALTER查询一个接一个返回错误的行。我希望有一个纯粹的 SQL 解决方案来消除错误的值。遗憾的是,这个解决方案并不美观

最后,我将整个表转换成了 PHP,在这里错误的行可以通过以下方式被全部检测到:

if (empty(htmlspecialchars($row['whatever'])))

如果字符集没有设置为 utf8mb4,也可能是客户端引起的问题。因此,即使每个 Database、 Table 和 Column 都设置为 utf8mb4,仍然会得到一个错误,例如 PyCharm 中的错误。

对于 Python,在 MySQL Connector connect 方法中设置连接的字符集:

mydb = mysql.connector.connect(
host="IP or Host",
user="<user>",
passwd="<password>",
database="<yourDB>",
# set charset to utf8mb4 to support emojis
charset='utf8mb4'
)