データベース全体で文字セット(およびコレクション)を変更するにはどうすればよいですか?


172

前のプログラマーがテーブル(Mysql)に間違った照合を設定しました。彼はUTF8であるはずのラテン照合でそれを設定しました、そして今私は問題を抱えています。中国語と日本文字のすべてのレコードは??? キャラクター。

照合順序を変更して、キャラクターの詳細を取得することはできますか?



照合順序は '???'とどのような関係がありますか?キャラクターセット?それはキャラクターセットと関係があると思いましたか?
peterchaula

タイトルを変更して、意図を反映させます。データベースのデフォルトの照合を変更することは、望まれていたよりもはるかに少ないです。
リックジェームズ

回答:


365

データベースの照合順序を変更します。

ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8mb4_0900_ai_ci;

テーブルの照合順序を変更します。

ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE utf8mb4_0900_ai_ci;

列の照合順序を変更します。

ALTER TABLE <table_name> MODIFY <column_name> VARCHAR(255) CHARACTER SET utf8 COLLATE utf8mb4_0900_ai_ci;

の部分はutf8mb4_0900_ai_ciどういう意味ですか?

3 bytes -- utf8
4 bytes -- utf8mb4 (new)
v4.0 --   _unicode_
v5.20 --  _unicode_520_
v9.0 --   _0900_ (new)
_bin      -- just compare the bits; don't consider case folding, accents, etc
_ci       -- explicitly case insensitive (A=a) and implicitly accent insensitive (a=á)
_ai_ci    -- explicitly case insensitive and accent insensitive
_as (etc) -- accent-sensitive (etc)
_bin         -- simple, fast
_general_ci  -- fails to compare multiple letters; eg ss=ß, somewhat fast
...          -- slower
_0900_       -- (8.0) much faster because of a rewrite

より詳しい情報:


4
注意してくださいCHARACTER SET utf8デフォルトに設定されutf8_general_ciますがALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8_unicode_ci;、必要に応じてこのような照合を定義することもできます
KCD

1
...そして、テストすることをお勧めしますcreate table testit(a varchar(1)); show create table testit \G drop table testit;
KCD '17

2
2番目は照合順序をに変更することを述べておきutf8_general_ciます。に変更するutf8_unicode_ci場合は、照合を定義できます ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;。これは、@ KCDが指摘したように、データベースで機能するのとまったく同じようにテーブルで機能します。
より賢明な2015

9
utf8を完全にサポートするには、以下を実行することをお勧めしALTER DATABASE <database_name> CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ciます。他の2つのステートメントについても同じことを行う必要があります。
Greeso 2015年

「ALTER TABLE <table_name> MODIFY <column_name> ...」を本当に使用する必要がありますか?dev.mysql.com/doc/refman/5.5/en/alter-table.htmlによると、「ALTER TABLE <table_name> CONVERT TO CHARACTER SET ...」も列を変更しているようです。または、マニュアルを正しく読んで理解していないのかもしれません。
hansfn 2017

49

すべてのデータベース/テーブル/列を変更する方法を示します。これらのクエリを実行すると、スキーマ全体をutf8に変換するために必要な後続のクエリがすべて出力されます。お役に立てれば!

-データベースのデフォルトの照合順序を変更する

SELECT DISTINCT concat('ALTER DATABASE `', TABLE_SCHEMA, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.tables
where TABLE_SCHEMA like  'database_name';

-TABLE照合/文字セットの変更

SELECT concat('ALTER TABLE `', TABLE_SCHEMA, '`.`', table_name, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.tables
where TABLE_SCHEMA like 'database_name';

-列の照合順序/文字セットを変更

SELECT concat('ALTER TABLE `', t1.TABLE_SCHEMA, '`.`', t1.table_name, '` MODIFY `', t1.column_name, '` ', t1.data_type , '(' , t1.CHARACTER_MAXIMUM_LENGTH , ')' , ' CHARACTER SET utf8 COLLATE utf8_unicode_ci;')
from information_schema.columns t1
where t1.TABLE_SCHEMA like 'database_name' and t1.COLLATION_NAME = 'old_charset_name';

良い。!私が同じ問題を解決しようとしているのは約1時間です。私はこれら3つのコマンドを使用しましたが、文字セットに変更があったことを確認しました。しかし、主な問題は私に残っています。私がデータベースに直接書き込んだ場合、すべてが私のブラウザーでうまく表示されます。しかし、Webサイトフォームからコンテンツを追加した場合、データベースの結果は??????になります。考慮すべきことはありますか?私のWebアプリは.NET MVCアプリです。
Tchaps 2015

将来のプロジェクトに役立つクエリに保存します。
Manatax 2016年

これらの自動化されたクエリはまだ安全に使用できなかったため、いくつかの編集を提案しました。CHARACTER_MAXIMUM_LENGTHにはまだ問題があります。たとえば、latin1_swedish_ciからutf8_unicode_ciに変更すると、元の値が高すぎる可能性があります。
ルーベン

1
これは素晴らしい答えです。3つのコメント/質問があります。1)COLUMNコードで「t1」を使用する理由を教えてください。必要はないと思います。2)なぜ「t1.column_type」だけでなく、「t1.data_type、 '('、t1.CHARACTER_MAXIMUM_LENGTH、 ')」」なのですか?3)大文字と小文字が混在する理由-TABLE_SCHEMA vs table_nameなど
hansfn 2017

25

Mysqlでは、utf8文字セットは実際のUTF8文字セットのサブセットにすぎないことに注意してください。1バイトのストレージを節約するために、Mysqlチームは、4バイト全体ではなく、3バイトのUTF8文字のみを保存することを決定しました。つまり、一部の東アジア言語と絵文字は完全にはサポートされていません。すべてのUTF8文字を確実に保存できるようにするには、utf8mb4データ型を使用するutf8mb4_binutf8mb4_general_ci、Mysql で使用します。


1
現在、utf8mb4_unicode_ciではなくを使用することをお勧めしますutf8mb4_general_cistackoverflow.com/questions/766809/…およびdrupal.stackexchange.com/questions/166405/…を
Robin van Baalen

6

David Whittakerが投稿したものに加えて、完全なテーブルと各テーブルを変換する列の変更ステートメントを生成するクエリを作成しました。実行することをお勧めします

SET SESSION group_concat_max_len = 100000;

最初に、ここで見られるように、グループ連結が非常に小さな制限を超えないようにします

     SELECT a.table_name, concat('ALTER TABLE ', a.table_schema, '.', a.table_name, ' DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci, ',
        group_concat(distinct(concat(' MODIFY ',  column_name, ' ', column_type, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ', if (is_nullable = 'NO', ' NOT', ''), ' NULL ',
        if (COLUMN_DEFAULT is not null, CONCAT(' DEFAULT \'', COLUMN_DEFAULT, '\''), ''), if (EXTRA != '', CONCAT(' ', EXTRA), '')))), ';') as alter_statement
    FROM information_schema.columns a
    INNER JOIN INFORMATION_SCHEMA.TABLES b ON a.TABLE_CATALOG = b.TABLE_CATALOG
        AND a.TABLE_SCHEMA = b.TABLE_SCHEMA
        AND a.TABLE_NAME = b.TABLE_NAME
        AND b.table_type != 'view'
    WHERE a.table_schema = ? and (collation_name = 'latin1_swedish_ci' or collation_name = 'utf8mb4_general_ci')
    GROUP BY table_name;

前の回答との違いは、ut8mb4の代わりにutf8を使用しており、t1.CHARACTER_MAXIMUM_LENGTHでt1.data_typeを使用しても列挙型では機能しなかったことです。また、ビューは個別に変更する必要があるため、ビューではクエリを除外しています。

私は単にPerlスクリプトを使用してこれらすべての変更を配列として返し、それらを繰り返し、長すぎる列を修正しました(通常、データに20文字しか含まれていない場合、一般的にはvarchar(256)でした)簡単に修正できました)。

latin1-> utf8mb4から変更すると、一部のデータが破損していることがわかりました。列のutf8エンコードされたlatin1文字が変換で誤って取得されるようです。変更前と変更後のメモリで問題になることがわかっていた列のデータを保持し、それらを比較してデータを修正するための更新ステートメントを生成しました。


4

ここでプロセスをよく説明します。ただし、ラテン空間に収まらなかった一部の文字は永久に消えてしまいます。UTF-8は、latin1のスーパーセットです。逆ではありません。ほとんどは1バイトスペースに収まりますが、未定義のものは収まりません(mysqlのlatin1の定義に応じて、latin1のリストを確認してください-256文字すべてが定義されているわけではありません)。

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