「不正な文字列値」エラーを修正する方法は?


162

不正な文字列値エラーのためにアプリケーションがランダムなメールを破棄する傾向があることに気付いた後、私は行って、多くのテキスト列を切り替えて、utf8列の文字セットとデフォルトの列照合(utf8_general_ci)を使用するようにしました。これにより、ほとんどのエラーが修正され、アプリケーションがラテン語以外の電子メールにヒットしたときにSQLエラーが発生しなくなりました。

それにもかかわらず、一部の電子メールは依然としてプログラムに不正な文字列値エラーを引き起こしています。 (Incorrect string value: '\xE4\xC5\xCC\xC9\xD3\xD8...' for column 'contents' at row 1)

コンテンツ列はMEDIUMTEXTutf8列の文字セットとutf8_general_ci列の照合を使用するデータ型です。この列で切り替えることができるフラグはありません。

どうしても必要な場合を除いて、アプリケーションのソースコードに触れたり、見たりしたくありません。

  • そのエラーの原因は何ですか?(はい、私はメールがランダムなゴミでいっぱいであることを知っていますが、utf8はかなり許容できると思いました)
  • どうすれば修正できますか?
  • そのような修正の可能性のある影響は何ですか?

私が検討したことの1つは、バイナリフラグをオンにしてutf8 varchar([some large number])に切り替えることでしたが、MySQLにはあまり慣れていないので、そのような修正が意味があるかどうかはわかりません。


3
事後分析RichieHindleのソリューションは問題を解決し、実行中に他の問題を引き起こさなかった。それは少しハックのようだったかもしれませんが、それはうまくいき、私が完全に理解していないサードパーティのソフトウェアで手を汚さないようにすることができました。この時点で、これらのエンコーディングの問題をすべて適切に処理する(そして実際にサポートされているほど新しい)ソフトウェア/スキーマの新しいバージョンに更新し、ハッキングを不要にしました。
ブライアン

回答:


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西ヨーロッパ")が最も許容できるエンコーディングです。すべてのバイト値が有効なコードポイントです。

もちろん、本物のUTF-8や、その他のcp1252以外のエンコーディングを理解することはもうありませんが、あまり気にしていないように思えますか?


4
「もちろん、もはや本物のUTF-8を理解するつもりはない」とはどういう意味ですか?
ブライアン

5
@ブライアン:cp1252を指定していると伝えて、実際にUTF-8を指定している場合、たとえばcaféと誤解してしまいcaféます。クラッシュしませんが、ハイビット文字を誤解します。
RichieHindle 2009

3
@Richie:データベースはデータを好きなように喜んで呼び出すことができますが、それを取得するphpコードが文字列に詰め込んでいる場合、それは大きな違いをもたらさないでしょう... UTF-8の理解の欠如が影響を及ぼしている場所は正確にはわかりません。
ブライアン

7
@ブライアン:いいえ、その通りです。たとえば、SQLでORDER BY句を使用した場合など、違いが生じる時間はデータベース内にあります。ASCII以外の文字がある場合、並べ替えは不安定になります。
RichieHindle 2009

11
この答えを解決策としてマークを外してください。エラーを非表示にすることは何の解決策にもなりません。車から過熱ランプを外すと、表示されます。
David Vartanian 2017

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
2番目のコマンドはSET CHARACTER SET utf8(CHARACTER_SETではなく)
Coder

6
この回答は問題の調査に役立ちますが、それを修正するために何をすべきかには答えません。「utf-8」の代わりに「latin1」が表示されます。
バヌアン2014年

2
この回答は問題の説明には優れていますが、ソリューションの詳細(OPが求めていたもの)は非常に貧弱です。@nicogawenda:問題を完全に修正するために実行するすべてのSQLクエリは何ですか?既存のデータをすべて修正する方法は?
クリントイーストウッド、

1
「ソース、トランスポート、宛先がUTF-8であれば、問題は解決しました;)」それが私にとってはトリックでした
suarsenegger

80

MySQLのutf-8タイプは、実際には適切なutf-8ではありません。1文字あたり最大3バイトを使用し、基本的な多言語プレーン(つまり、絵文字、アストラルプレーンなど)のみをサポートします。

上位のUnicodeプレーンからの値を保存する必要がある場合は、utf8mb4エンコーディングが必要です。


9
これはおそらく最良の修正だと思います。上記の回答では、5.5にアップグレードしてutf8をutf8mb4に置き換えます。絵文字や4バイトを必要とするその他の文字が含まれるTwitterからutf8データを挿入していました。
rmarscher 14

5.5にアップグレードしないとしましょう。エラーを抑制するにはどうすればよいですか?
2015

私はこの最も有用な答えのためにあまりにも遠くにスクロールしました
handheldblender

1
元の質問から10年。MySQLのutf8エンコーディングが適切なutf8ではないことを知らせてください。utf8mb4を使用してください!MariaDBについても同様です。そうしないと、😂喜びの涙はできません
リアム・

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
これが正解だと思います。2つのテーブルにそれぞれutf8 varchar形式があります。1つはエラーが発生し、もう1つは問題ありません。「update select」を使用しても、「good」utf8列から別のテーブルにコピーを作成しても、同じエラーが発生します。これは、2つのテーブルが異なるバージョンのMySQLで作成されているためです。
AiShiguang 2017年

はい!それも私のデータベーステーブルからの設定ミスでした。この答えは正解だと思います。私の問題は、選択された照合順序がutf8_general_ciではなくutf8_unicode_ciであったことでした。ありがとう:)
jprivillaso

2
この答えはここで何をしているのでしょうか、一番上にあるはずです
Shrestha

1
これは役に立ちます。何が悪いのかではなく、何を試すべきかを教えてくれます。
Victor Di

ありがとうございました!それは私がテーブル照合を変更したことを私に大いに助けましたantそれはそれであるはずだと思いましたが、フィールドはまだASCII照合でした...
Radu

25

列を「LONGBLOB」タイプに変更して、UTF-8文字ではなく生のバイトを格納することで、この問題を解決しました。

これを行うことの唯一の欠点は、自分でエンコードを処理する必要があることです。アプリケーションの1つのクライアントがUTF-8エンコーディングを使用し、別のクライアントがCP1252を使用している場合、誤った文字でメールが送信される可能性があります。これを回避するには、すべてのアプリケーション常に同じエンコーディング(UTF-8など)を使用します

TEXT / LONGTEXTとBLOB / LONGBLOBの違いの詳細については、このページhttp://dev.mysql.com/doc/refman/5.0/en/blob.htmlを参照してください。これら2つについて議論しているWeb上の他の多くの議論もあります。


1
このソリューションは、最も簡単な方法のようです。他のエンコーディングをいくつか試しましたが、成功しませんでした。
Simeon Abolarinwa 2016

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文字をデータベースに書き込むために再試行できます。このソリューションは、csvファイルの200000行をデータベースにアップロードしようとするときに役立ちます。


8

一般的に、これは、互換性のないエンコーディング/照合を使用して列に文字列を挿入した場合に発生します。

何らかの理由でサーバーの照合順序を継承するトリガーがあったときに、このエラーが発生しました。また、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アンコーディングをサポートしておらず、原因を理解しようとしていませんでした。タイプを変更することは明らかに答えであり、即時の解決策でした。
Liza

4

このエラーは、エンコードが正しくない文字列がある(たとえば、ISO-8859-1エンコードされた文字列をUTF-8エンコードされた列に入力しようとしている)か、入力しようとしているデータを列がサポートしていないことを意味します。

実際には、後者の問題は、UTF-8で表したときに1〜3バイトを必要とするUNICODE文字のみをサポートするMySQL UTF-8実装が原因で発生します。JDBCを介してMySQLにUTF-8を挿入しようとする場合、「不正な文字列値」を参照してください詳細については。


2

スクリプトケースを使用した列エラーのこの不正な文字列値「\ xF8」に遭遇したときの私に対する解決策は、私のデータベースがutf8一般的なCIに設定されていることを確認し、フィールド照合も確認することでした。次に、csvファイルのデータインポートを実行するときに、csvをUE Studioにロードし、utf8およびVoilaとしてフォーマットして保存します!それは魅力のように動作し、エラーなしで29000レコードです。以前は、Excelで作成したcsvをインポートしようとしていました。


2

私は上記の解決策(すべて有効なポイントをもたらす)をすべて試しましたが、何もうまくいきませんでした。

C#でのMySQLテーブルフィールドマッピングが誤ったタイプMySqlDbType.Blobを使用していることがわかるまでMySqlDbType.Textに変更しました。これで、必要なすべてのUTF8シンボルを書き込むことができます。

ps My MySQLテーブルフィールドは「LongText」タイプです。ただし、MyGenerationソフトウェアを使用してフィールドマッピングを自動生成すると、C#でフィールドタイプがMySqlDbType.Blobとして自動的に設定されます。

興味深いことに、MySqlDbType.Blob型をUTF8文字で何ヶ月も問題なく使用してきました。ある日、特定の文字を含む文字列を書いてみました。

これがエラーの理由を見つけるのに苦労している人に役立つことを願っています。


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を含む、提供されている型マッパーがたくさんあるようですが、for java.net.URLはありませんjava.net.URI(ここで必要なものです)。


1

保存する前に文字列関数で値を処理する場合は、関数がマルチバイト文字を適切に処理できることを確認してください。これを実行できない、たとえば切り捨てようとしている文字列関数は、単一のマルチバイト文字の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列のエンコードを「バイナリ」に変更することで解決されました(データ型は自動的にVARBINARYに変更されます)。おそらく、その列でフィルターをかけたり検索したりすることはできませんが、その必要はありません。



-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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.