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

时间:2009-07-22 20:26:02

标签: mysql

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

23 个答案:

答案 0 :(得分:122)

我不建议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 :(得分:69)

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

如果您需要存储较高Unicode平面的值,则需要utf8mb4 encodings

答案 2 :(得分:33)

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

答案 3 :(得分:32)

"\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 :(得分:21)

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

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

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

答案 5 :(得分: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

这必须用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 :(得分:7)

首先检查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 :(得分:5)

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

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

答案 8 :(得分:4)

该错误意味着您要么使用不正确编码的字符串(例如,您尝试将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?

答案 9 :(得分:4)

我收到了类似的错误(utf8mb4)。我尝试将列的字符集更改为'Data too long for column 'content' at row 1',之后错误已更改为utf8
原来,mysql显示错误的错误。我将列的字符集转回MEDIUMTEXT,并将列的类型更改为{{1}}。之后错误消失了 我希望它有助于某人 顺便说一句,MariaDB在同样的情况下(我在那里测试了相同的INSERT)只是剪切了一个没有错误的文本。

答案 10 :(得分:2)

遇到这个错误的字符串值时的解决方案:'\ xF8'用于使用scriptcase的列错误是为了确保我的数据库设置为utf8 general ci,因此我的字段排序规则。然后,当我执行csv文件的数据导入时,我将csv加载到UE Studio中,然后将其格式化为utf8和Voila!它就像一个魅力,29000记录没有错误。以前我试图导入一个excel创建的csv。

答案 11 :(得分:2)

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

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

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

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

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

答案 12 :(得分:1)

我在列名前添加了二进制文件并解决了charset错误。

插入tableA值(二进制stringcolname1);

答案 13 :(得分:1)

当我使用来自godaddy服务器的在线数据库时,我也遇到了这个错误 我认为它有5.1或更高版本的mysql版本。但是当我从我的localhost服务器(版本5.7)做到这一点之后,我从本地服务器创建表并使用mysql yog复制到在线服务器,我认为问题是字符集

Screenshot Here

答案 14 :(得分:1)

要修复此错误,我将MySQL数据库升级到utf8mb4,后者this detailed tutorial支持完整的Unicode字符集。我建议仔细检查一下,因为有很多问题(例如索引键可能因为新编码而变得太大,之后你必须修改字段类型)。

答案 15 :(得分: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而言,似乎它有一堆provided type mappers,包括java.net.URL,但不适用于java.net.URI(这是我们需要的)。

答案 16 :(得分:0)

在我的情况下,首先我遇到了一个&#39; ????在我的网站上,然后我检查了现在拉丁语的Mysql的字符集,所以我把它改成utf-8,然后我重启我的项目,然后我得到了同样的错误,然后我发现我忘了改变数据库的字符集并改为utf-8,繁荣,它有效。

答案 17 :(得分:0)

我做了什么,首先将列类型更改为LONG BLOB,插入数据然后将列类型更改为VARCHAR(255),因为数据不是那么敏感,我冒了风险而且它也很大(大约40k)条款)。我建议你可以尝试这个,只要你没有任何你不想扭曲的数据。

答案 18 :(得分:0)

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

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

答案 19 :(得分:0)

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

答案 20 :(得分:0)

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

答案 21 :(得分:0)

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

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

答案 22 :(得分:-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