前のプログラマーがテーブル(Mysql)に間違った照合を設定しました。彼はUTF8であるはずのラテン照合でそれを設定しました、そして今私は問題を抱えています。中国語と日本文字のすべてのレコードは??? キャラクター。
照合順序を変更して、キャラクターの詳細を取得することはできますか?
前のプログラマーがテーブル(Mysql)に間違った照合を設定しました。彼はUTF8であるはずのラテン照合でそれを設定しました、そして今私は問題を抱えています。中国語と日本文字のすべてのレコードは??? キャラクター。
照合順序を変更して、キャラクターの詳細を取得することはできますか?
回答:
データベースの照合順序を変更します。
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
より詳しい情報:
CHARACTER SET utf8
デフォルトに設定されutf8_general_ci
ますがALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8_unicode_ci;
、必要に応じてこのような照合を定義することもできます
create table testit(a varchar(1)); show create table testit \G drop table testit;
utf8_general_ci
ます。に変更するutf8_unicode_ci
場合は、照合を定義できます ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
。これは、@ KCDが指摘したように、データベースで機能するのとまったく同じようにテーブルで機能します。
ALTER DATABASE <database_name> CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
ます。他の2つのステートメントについても同じことを行う必要があります。
すべてのデータベース/テーブル/列を変更する方法を示します。これらのクエリを実行すると、スキーマ全体を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';
Mysqlでは、utf8
文字セットは実際のUTF8文字セットのサブセットにすぎないことに注意してください。1バイトのストレージを節約するために、Mysqlチームは、4バイト全体ではなく、3バイトのUTF8文字のみを保存することを決定しました。つまり、一部の東アジア言語と絵文字は完全にはサポートされていません。すべてのUTF8文字を確実に保存できるようにするには、utf8mb4
データ型を使用するutf8mb4_bin
かutf8mb4_general_ci
、Mysql で使用します。
utf8mb4_unicode_ci
ではなくを使用することをお勧めしますutf8mb4_general_ci
。stackoverflow.com/questions/766809/…およびdrupal.stackexchange.com/questions/166405/…を
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文字が変換で誤って取得されるようです。変更前と変更後のメモリで問題になることがわかっていた列のデータを保持し、それらを比較してデータを修正するための更新ステートメントを生成しました。