第 10 章 グローバリゼーション

目次

10.1 文字セットのサポート
10.1.1 一般の文字セットおよび照合順序
10.1.2 MySQL での文字セットと照合順序
10.1.3 文字セットと照合順序の指定
10.1.4 接続文字セットおよび照合順序
10.1.5 アプリケーションの文字セットおよび照合順序の構成
10.1.6 エラーメッセージの文字セット
10.1.7 照合順序の問題
10.1.8 文字列のレパートリー
10.1.9 文字セットのサポートによる影響を受ける演算
10.1.10 Unicode のサポート
10.1.11 以前の Unicode サポートから現在の Unicode サポートへのアップグレード
10.1.12 メタデータ用の UTF-8
10.1.13 カラム文字セットの変換
10.1.14 MySQL でサポートされる文字セットと照合順序
10.2 エラーメッセージ言語の設定
10.3 文字セットの追加
10.3.1 文字定義配列
10.3.2 複雑な文字セットの文字列照合のサポート
10.3.3 複雑な文字セットのマルチバイト文字のサポート
10.4 文字セットへの照合順序の追加
10.4.1 照合順序の実装タイプ
10.4.2 照合順序 ID の選択
10.4.3 8 ビットの文字セットへの単純な照合順序の追加
10.4.4 Unicode 文字セットへの UCA 照合順序の追加
10.5 文字セットの構成
10.6 MySQL Server でのタイムゾーンのサポート
10.6.1 タイムゾーンの変更による現在の時間の維持
10.6.2 タイムゾーンのうるう秒のサポート
10.7 MySQL Server のロケールサポート

この章では、国際化 (各地域での使用に対応するための MySQL の機能) とローカライズ (特定の地域的な規則の選択) を含む、次のようなグローバリゼーションの問題を取り上げます。

10.1 文字セットのサポート

MySQL では、さまざまな文字セットを使用してデータを格納し、さまざまな照合順序に従って比較を実行できます。サーバー、データベース、テーブル、およびカラムレベルで文字セットを指定できます。MySQL では、MyISAMMEMORY、および InnoDB のストレージエンジンの文字セットの使用をサポートします。

この章では次のトピックについて説明します。

  • 文字セットと照合順序とは。

  • 文字セットの割り当てに対する複数レベルのデフォルトシステム。

  • 文字セットと照合順序を指定するための構文。

  • 影響を受ける関数と演算。

  • Unicode のサポート。

  • 使用可能な文字セットと照合順序 (ノート付き)。

文字セットの問題は、データストレージだけではなく、クライアントプログラムと MySQL Server との通信にも影響を与えます。デフォルトと異なる文字セットを使用してクライアントプログラムとサーバー間の通信を行う場合、どの文字セットを使用するのかを示す必要があります。たとえば、utf8 Unicode 文字セットを使用するには、サーバー接続後に次のステートメントを発行してください。

SET NAMES 'utf8';

アプリケーションで使用する文字セットの構成と、クライアント/サーバー間の通信に関する文字セット関連の問題の詳細は、セクション10.1.5「アプリケーションの文字セットおよび照合順序の構成」およびセクション10.1.4「接続文字セットおよび照合順序」を参照してください。

10.1.1 一般の文字セットおよび照合順序

文字セットとは、記号とエンコーディングのセットです。照合順序とは、文字セット内の文字を比較するためのルールを集めたものです。架空の文字セットを例にして、文字セットと照合順序の違いを見てみましょう。

ABabの 4 つのアルファベットがあるとします。それぞれの文字に A = 0、B = 1、a = 2、b = 3 の数字を割り当てます。文字Aは記号で、数字 0 はAに対するエンコーディングであり、4 つの文字とそのエンコーディングの組み合わせが文字セットになります。

ABの 2 つの文字列値を比較するとします。これを行うには、Aの 0、Bの 1 というエンコーディングを調べる方法がもっとも簡単です。0 は 1 より小さいので、ABより小さいと見なします。今ここで行なったのは、文字セットに対する照合順序の適用です。照合順序はルールの集まりであり、この場合、ルールはエンコーディングの比較の 1 つだけになります。これは可能な照合順序のうちでもっとも単純なものであり、バイナリ照合順序と呼ばれています。

しかし、小文字と大文字が同等であることを表すにはどうなるのでしょうか。この場合、少なくとも次の 2 つのルールが必要です。(1) 小文字aおよびbAおよびBと同等のものとして扱います。(2) 続いてそのエンコーディングを比較します。これは大文字と小文字を区別しない照合順序と呼ばれます。バイナリ照合順序よりも少し複雑になります。

実際には、ほとんどの文字セットには多数の文字があり、ABだけではなくアルファベット全体が含まれます。複数のアルファベットが含まれる場合も、数千種類の文字や多くの特殊記号および句読点から構成される東洋書記体系の場合もあります。また実際には、ほとんどの照合順序は、大文字と小文字の区別だけでなく、アクセント符号 (アクセント符号とはドイツ語のÖに見られるような文字に付けられた符号です) を区別するかどうかに関するルールや、複数文字のマッピングのルール (2 つのドイツ語の照合順序の一方におけるÖ = OEというルールなど) など多くのルールを含んでいます。

MySQL では以下が可能です。

  • さまざまな文字セットを使用して文字列を格納します。

  • さまざまな照合順序を使用して文字列を比較します。

  • 文字セットまたは照合順序が異なる文字列を、同じサーバー、同じデータベース、または同じテーブル内にも混在させます。

  • どのレベルでも文字セットと照合順序を指定できるようにします。

MySQL はこれらの点において、ほかのほとんどのデータベース管理システムに大きく差をつけています。ただし、これらの機能を効果的に使用するには、利用可能な文字セットと照合順序、各デフォルトの変更方法、および文字列演算子および関数の動作にこれらの機能が与える影響を知っておく必要があります。

10.1.2 MySQL での文字セットと照合順序

MySQL Server では複数の文字セットがサポートされています。利用可能な文字セットを一覧表示するには、SHOW CHARACTER SET ステートメントを使用します。リストの一部は次のとおりです。完全な情報については、セクション10.1.14「MySQL でサポートされる文字セットと照合順序」を参照してください。

mysql> SHOW CHARACTER SET;+----------+-----------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| swe7 | 7bit Swedish | swe7_swedish_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 |
| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci | 1 |
| tis620 | TIS620 Thai | tis620_thai_ci | 1 |
| euckr | EUC-KR Korean | euckr_korean_ci | 2 |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci | 1 |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| greek | ISO 8859-7 Greek | greek_general_ci | 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
...

どの文字セットにも常に少なくとも 1 つの照合順序が対応しています。複数の照合順序が対応することもあります。文字セットの照合順序を一覧表示するには、SHOW COLLATION ステートメントを使用します。たとえば、latin1 (cp1252 西ヨーロッパ言語) 文字セットの照合順序を表示するには、このステートメントを使用して、名前が latin1 で始まる照合順序を探します。

mysql> SHOW COLLATION LIKE 'latin1%';+---------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+---------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 1 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+---------------------+---------+----+---------+----------+---------+

latin1 の照合順序の意味は次のとおりです。

照合順序意味
latin1_german1_ciドイツ語 DIN-1
latin1_swedish_ciスウェーデン語/フィンランド語
latin1_danish_ciデンマーク語/ノルウェー語
latin1_german2_ciドイツ語 DIN-2
latin1_binlatin1 エンコーディングに基づくバイナリ
latin1_general_ciマルチリンガル (西ヨーロッパ言語)
latin1_general_csマルチリンガル (ISO 西ヨーロッパ言語)、大文字と小文字を区別
latin1_spanish_ci現代スペイン語

照合順序には次のような一般的な特徴があります。

  • 2 つの異なる文字セットで、同じ照合順序を共有できません。

  • 各文字セットには、デフォルト照合順序が 1 つ存在します。たとえば、latin1 のデフォルト照合順序は latin1_swedish_ci です。SHOW CHARACTER SET の出力には、表示されている各文字セットのデフォルト照合順序が示されます。

  • 照合順序名には、関連する文字セットの名前で始まる、通常は言語名を含む、_ci (大文字と小文字を区別しない)、_cs (大文字と小文字を区別する)、_bin (バイナリ) のいずれかで終わる、という規則が適用されます。

文字セットに複数の照合順序が存在する場合、どの照合順序が所定のアプリケーションにもっとも適しているかが明確でないことがあります。正しくない照合順序を選択しないようにするには、代表的なデータ値で比較を行い、特定の照合順序で期待どおりに値がソートされることを確認すると役立ちます。

10.1.3 文字セットと照合順序の指定

サーバー、データベース、テーブル、カラムの 4 つのレベルで、文字セットと照合順序のデフォルト設定が用意されています。以降のセクションの説明は複雑に思われますが、実際、複数レベルのデフォルト設定によって自然で明白な結果が得られることがわかっています。

CHARACTER SET は文字セットを指定する句で使用します。CHARSET は、CHARACTER SET のシノニムとして使用できます。

文字セットの問題は、データストレージだけではなく、クライアントプログラムと MySQL Server との通信にも影響を与えます。デフォルトと異なる文字セットを使用してクライアントプログラムとサーバー間の通信を行う場合、どの文字セットを使用するのかを示す必要があります。たとえば、utf8 Unicode 文字セットを使用するには、サーバー接続後に次のステートメントを発行してください。

SET NAMES 'utf8';

クライアント/サーバー間の通信に関する文字セット関連の問題の詳細は、セクション10.1.4「接続文字セットおよび照合順序」を参照してください。

10.1.3.1 サーバー文字セットおよび照合順序

MySQL Server にはサーバー文字セットとサーバー照合順序があります。これらは、コマンド行またはオプションファイルで、サーバーの起動時に設定し、実行時に変更できます。

サーバー文字セットおよび照合順序は最初、mysqld の起動時に使用するオプションに依存します。文字セットに --character-set-server を使用できます。これに加え、照合順序に --collation-server を追加できます。文字セットを指定しない場合は、--character-set-server=latin1 を指定した場合と同じになります。文字セット (たとえば latin1) だけを指定して照合順序を指定しない場合は、--character-set-server=latin1--collation-server=latin1_swedish_ci を指定した場合と同じになります。これは latin1_swedish_cilatin1 のデフォルト照合順序であるためです。したがって、次の 3 つのコマンドを実行した結果はいずれも同じになります。

shell> mysqldshell> mysqld --character-set-server=latin1shell> mysqld --character-set-server=latin1 \--collation-server=latin1_swedish_ci

設定を変更する手段の 1 つは再コンパイルです。ソースから構築するときに、デフォルトのサーバー文字セットおよび照合順序を変更するには、CMakeDEFAULT_CHARSET および DEFAULT_COLLATION オプションを使用します。例:

shell> cmake . -DDEFAULT_CHARSET=latin1

または:

shell> cmake . -DDEFAULT_CHARSET=latin1 \-DDEFAULT_COLLATION=latin1_german1_ci

mysqldCMake の両方は、文字セットと照合順序の組み合わせが有効であることを検証します。組み合わせが有効でない場合、各プログラムによってエラーメッセージが表示され、強制終了されます。

サーバー文字セットおよび照合順序は、データベース文字セットおよび照合順序が CREATE DATABASE ステートメントで指定されていない場合にデフォルト値として使用されます。これらにほかの用途はありません。

現在のサーバー文字セットおよび照合順序は、character_set_server および collation_server システム変数の値で判別できます。これらの変数は実行時に変更できます。

10.1.3.2 データベース文字セットおよび照合順序

各データベースにはデータベース文字セットとデータベース照合順序があります。CREATE DATABASE および ALTER DATABASE ステートメントには、データベース文字セットおよび照合順序を指定するためのオプション句があります。

CREATE DATABASE db_name [[DEFAULT] CHARACTER SET charset_name] [[DEFAULT] COLLATE collation_name]
ALTER DATABASE db_name [[DEFAULT] CHARACTER SET charset_name] [[DEFAULT] COLLATE collation_name]

SCHEMA というキーワードは DATABASE の代わりに使用できます。

すべてのデータベースオプションは、データベースディレクトリ内の db.opt というテキストファイルに格納されます。

CHARACTER SET および COLLATE 句を使用すると、文字セットと照合順序が異なる複数のデータベースを同一の MySQL Server に作成できます。

例:

CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_swedish_ci;

MySQL では、データベース文字セットとデータベース照合順序が次のように選択されます。

  • CHARACTER SET XCOLLATE Y の両方が指定されている場合、文字セット X と照合順序 Y が使用されます。

  • CHARACTER SET X は指定されているが COLLATE は指定されていない場合、文字セット X とそのデフォルト照合順序が使用されます。各文字セットのデフォルトの照合順序を確認するには、SHOW COLLATION ステートメントを使用します。

  • COLLATE Y は指定されているが CHARACTER SET は指定されていない場合、Y に関連付けられた文字セットと照合順序 Y が使用されます。

  • これ以外の場合は、サーバー文字セットとサーバー照合順序が使用されます。

デフォルトのデータベースに対する文字セットと照合順序は、character_set_database および collation_database システム変数の値から判別できます。デフォルトのデータベースが変わるたびに、サーバーはこれらの変数を設定します。デフォルトのデータベースがない場合、変数は、character_set_server および collation_server という対応するサーバーレベルのシステム変数と同値になります。

特定のデータベースのデフォルト文字セットおよび照合順序を確認するには、次のステートメントを使用します。

USE db_name;
SELECT @@character_set_database, @@collation_database;

また、デフォルトのデータベースを変更しないで値を表示するには、次のステートメントを使用します。

SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'db_name';

データベース文字セットおよび照合順序は、サーバー操作の次の側面に影響します。

  • CREATE TABLE ステートメントでは、テーブル文字セットおよび照合順序が指定されていない場合、データベース文字セットおよび照合順序がテーブル定義のデフォルト値として使用されます。これをオーバーライドするには、CHARACTER SET および COLLATE テーブルオプションを明示的に指定します。

  • CHARACTER SET 句を含まない LOAD DATA ステートメントでは、サーバーは、character_set_database システム変数によって示された文字セットを使用して、ファイル内の情報を解釈します。これをオーバーライドするには、CHARACTER SET 句を明示的に指定します。

  • ストアドルーチン (ストアドプロシージャーおよびストアドファンクション) では、CHARACTER SET 属性も COLLATE 属性も宣言に含まれていない文字データパラメータの文字セットおよび照合順序として、ルーチンの作成時に有効なデータベース文字セットおよび照合順序が使用されます。これをオーバーライドするには、CHARACTER SET および COLLATE 属性を明示的に指定します。

10.1.3.3 テーブル文字セットおよび照合順序

各テーブルにはテーブル文字セットとテーブル照合順序があります。CREATE TABLE および ALTER TABLE ステートメントには、テーブル文字セットおよび照合順序を指定するためのオプション句があります。

CREATE TABLE tbl_name (column_list) [[DEFAULT] CHARACTER SET charset_name] [COLLATE collation_name]]
ALTER TABLE tbl_name [[DEFAULT] CHARACTER SET charset_name] [COLLATE collation_name]

例:

CREATE TABLE t1 ( ... )
CHARACTER SET latin1 COLLATE latin1_danish_ci;

MySQL では、テーブル文字セットとテーブル照合順序が次のように選択されます。

  • CHARACTER SET XCOLLATE Y の両方が指定されている場合、文字セット X と照合順序 Y が使用されます。

  • CHARACTER SET X は指定されているが COLLATE は指定されていない場合、文字セット X とそのデフォルト照合順序が使用されます。各文字セットのデフォルトの照合順序を確認するには、SHOW COLLATION ステートメントを使用します。

  • COLLATE Y は指定されているが CHARACTER SET は指定されていない場合、Y に関連付けられた文字セットと照合順序 Y が使用されます。

  • これ以外の場合は、データベース文字セットとデータベース照合順序が使用されます。

個々のカラム定義でカラム文字セットおよび照合順序が指定されていない場合は、テーブル文字セットおよび照合順序がカラム定義のデフォルト値として使用されます。テーブル文字セットおよび照合順序は MySQL の拡張機能です。このような機能は標準 SQL には存在しません。

10.1.3.4 カラム文字セットおよび照合順序

文字カラム (CHARVARCHAR、または TEXT 型のカラム) にはカラム文字セットとカラム照合順序があります。CREATE TABLE および ALTER TABLE のカラム定義構文には、カラム文字セットおよび照合順序を指定するためのオプション句があります。

col_name {CHAR | VARCHAR | TEXT} (col_length) [CHARACTER SET charset_name] [COLLATE collation_name]

これらの句は、ENUM および SET カラムにも使用できます。

col_name {ENUM | SET} (val_list) [CHARACTER SET charset_name] [COLLATE collation_name]

例:

CREATE TABLE t1
( col1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci
);
ALTER TABLE t1 MODIFY col1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_swedish_ci;

MySQL では、カラム文字セットとカラム照合順序が次のように選択されます。

  • CHARACTER SET XCOLLATE Y の両方が指定されている場合、文字セット X と照合順序 Y が使用されます。

    CREATE TABLE t1
    ( col1 CHAR(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci
    ) CHARACTER SET latin1 COLLATE latin1_bin;

    カラムに対して文字セットと照合順序が指定されているので、これらが使用されます。このカラムには、文字セット utf8 と照合順序 utf8_unicode_ci があります。

  • CHARACTER SET X は指定されているが COLLATE は指定されていない場合、文字セット X とそのデフォルト照合順序が使用されます。

    CREATE TABLE t1
    ( col1 CHAR(10) CHARACTER SET utf8
    ) CHARACTER SET latin1 COLLATE latin1_bin;

    カラムに対して文字セットは指定されていますが、照合順序は指定されていません。このカラムには、文字セット utf8 と、utf8 のデフォルトの照合順序である utf8_general_ci があります。各文字セットのデフォルトの照合順序を確認するには、SHOW COLLATION ステートメントを使用します。

  • COLLATE Y は指定されているが CHARACTER SET は指定されていない場合、Y に関連付けられた文字セットと照合順序 Y が使用されます。

    CREATE TABLE t1
    ( col1 CHAR(10) COLLATE utf8_polish_ci
    ) CHARACTER SET latin1 COLLATE latin1_bin;

    カラムに対して照合順序は指定されていますが、文字セットは指定されていません。このカラムには照合順序 utf8_polish_ci があり、この照合順序に関連付けられた文字セットである utf8 があります。

  • これ以外の場合は、テーブル文字セットとテーブル照合順序が使用されます。

    CREATE TABLE t1
    ( col1 CHAR(10)
    ) CHARACTER SET latin1 COLLATE latin1_bin;

    カラムに対して文字セットも照合順序も指定されていないので、テーブルのデフォルトが使用されます。このカラムには、文字セット latin1 と照合順序 latin1_bin があります。

CHARACTER SET および COLLATE 句は標準 SQL です。

ALTER TABLE を使用して、ある文字セットから別の文字セットにカラムを変換する場合、MySQL はデータ値をマップしようとしますが、文字セットに互換性がない場合、データの損失が生じる可能性があります。

10.1.3.5 文字列リテラルの文字セットおよび照合順序

各文字列リテラルには文字セットと照合順序があります。

文字列リテラルでは、オプションとして文字セットイントロデューサと COLLATE 句を指定できます。

[_charset_name]'string' [COLLATE collation_name]

例:

SELECT 'string';
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;

単純なステートメント SELECT 'string' に対して、文字列には character_set_connection および collation_connection システム変数で定義された文字セットと照合順序が適用されます。

_charset_name 式は正式にはイントロデューサと呼ばれます。これは、後続する文字列が文字セット X を使用することをパーサーに通知します。わかりにくいので強調しておきますが、イントロデューサは、CONVERT() が行うようなイントロデューサ文字セットへの文字列の変換は行いません。パディングが行われる可能性がありますが、文字列の値は変更しません。イントロデューサは単なる信号です。イントロデューサは、標準の 16 進リテラルおよび数値の 16 進リテラル表記 (x'literal' および 0xnnnn) の前でも、ビットフィールドリテラル表記 (b'literal' および 0bnnnn) の前でも有効です。

例:

SELECT _latin1 x'AABBCC';
SELECT _latin1 0xAABBCC;
SELECT _latin1 b'1100011';
SELECT _latin1 0b1100011;

MySQL では、リテラルの文字セットおよび照合順序が次のように決定されます。

  • _XCOLLATE Y の両方が指定されている場合、文字セット X と照合順序 Y が使用されます。

  • _X は指定されているが、COLLATE が指定されていない場合、文字セット X とそのデフォルト照合順序が使用されます。各文字セットのデフォルトの照合順序を確認するには、SHOW COLLATION ステートメントを使用します。

  • これ以外の場合は、character_set_connection および collation_connection システム変数で指定される文字セットと照合順序が使用されます。

例:

  • 文字列に latin1 文字セットと latin1_german1_ci 照合順序が指定されている場合

    SELECT _latin1'Müller' COLLATE latin1_german1_ci;
  • 文字列に latin1 文字セットとそのデフォルト照合順序 (つまり、latin1_swedish_ci) が指定されている場合

    SELECT _latin1'Müller';
  • 文字列に接続デフォルト文字セットおよび照合順序が指定されている場合

    SELECT 'Müller';

文字セットイントロデューサと COLLATE 句は、標準 SQL 仕様に基づいて実装されています。

イントロデューサは後続の文字列の文字セットを指定しますが、現在のところ、その文字列内でパーサーがエスケープ処理を実行する方法までは変更しません。エスケープは常に、character_set_connection で指定された文字セットに従ってパーサーが解釈します。

次の例は、イントロデューサが存在する場合でも、character_set_connection を使用して、エスケープ処理が行われることを示します。例では、SET NAMES (セクション10.1.4「接続文字セットおよび照合順序」で説明しているように、character_set_connection を変更します) を使用し、正確な文字列の内容を確認できるように HEX() 関数を使用して結果の文字列を表示します。

例 1:

mysql> SET NAMES latin1;Query OK, 0 rows affected (0.01 sec)
mysql> SELECT HEX('à\n'), HEX(_sjis'à\n');+------------+-----------------+
| HEX('à\n') | HEX(_sjis'à\n') |
+------------+-----------------+
| E00A | E00A |
+------------+-----------------+
1 row in set (0.00 sec)

ここでは、à (16 進値 E0) のあとに、改行のエスケープシーケンスである\nが続いています。このエスケープシーケンスは、latin1character_set_connection 値を使用して解釈され、リテラルの改行 (16 進値 0A) を生成します。これは 2 番目の文字列にも行われます。つまり、_sjis のイントロデューサはパーサーのエスケープ処理に影響を及ぼしません。

例 2:

mysql> SET NAMES sjis;Query OK, 0 rows affected (0.00 sec)
mysql> SELECT HEX('à\n'), HEX(_latin1'à\n');+------------+-------------------+
| HEX('à\n') | HEX(_latin1'à\n') |
+------------+-------------------+
| E05C6E | E05C6E |
+------------+-------------------+
1 row in set (0.04 sec)

ここでは、character_set_connectionsjis です。この文字セットでは、àのあとに\ (16 進値 05 および 5C) が続いたシーケンスは、有効なマルチバイト文字になります。したがって、文字列の最初の 2 バイトは、単一の sjis 文字として解釈され、\はエスケープ文字として解釈されません。後続のn (16 進値 6E) はエスケープシーケンスの一部としては解釈されません。これは 2 番目の文字列にも当てはまります。_latin1 のイントロデューサはエスケープ処理に影響を及ぼしません。

10.1.3.6 各国文字セット

標準 SQL では、NCHAR または NATIONAL CHAR は、CHAR カラムで事前定義された文字セットを使用するように指定する方法として定義されています。MySQL 5.6 では、utf8 を事前定義された文字セットとして使用します。たとえば、次のデータ型宣言は同等です。

CHAR(10) CHARACTER SET utf8
NATIONAL CHARACTER(10)
NCHAR(10)

次も同様です。

VARCHAR(10) CHARACTER SET utf8
NATIONAL VARCHAR(10)
NCHAR VARCHAR(10)
NATIONAL CHARACTER VARYING(10)
NATIONAL CHAR VARYING(10)

N'literal' (または n'literal') を使用すると、各国文字セットの文字列を作成できます。次のステートメントは同等です。

SELECT N'some text';
SELECT n'some text';
SELECT _utf8'some text';

4.1 以前のバージョンから MySQL 5.6 への文字セットのアップグレードに関する情報については、MySQL 3.23、4.0、4.1 リファレンスマニュアルを参照してください。

10.1.3.7 文字セットと照合順序の割り当ての例

MySQL でどのようにしてデフォルトの文字セットおよび照合順序の値が決定されるかを、次の例で示します。

例 1: テーブルおよびカラムの定義

CREATE TABLE t1
( c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci
) DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;

ここでは latin1 文字セットと latin1_german1_ci 照合順序がカラムに指定されています。この定義は明確であり、簡単明瞭です。なお、latin1 カラムを latin2 テーブルに格納することに問題はありません。

例 2: テーブルおよびカラムの定義

CREATE TABLE t1
( c1 CHAR(10) CHARACTER SET latin1
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

ここでは、latin1 文字セットとデフォルト照合順序がカラムに指定されています。当然のようですが、デフォルトの照合順序はテーブルレベルからは取得されません。latin1 のデフォルト照合順序は常に latin1_swedish_ci なので、カラム c1 には latin1_danish_ci ではなく latin1_swedish_ci の照合順序が設定されます。

例 3: テーブルおよびカラムの定義

CREATE TABLE t1
( c1 CHAR(10)
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

ここでは、デフォルト文字セットとデフォルト照合順序がカラムに指定されています。この状況では、MySQL はテーブルレベルをチェックして、カラムの文字セットおよび照合順序を特定します。したがって、カラム c1 の文字セットは latin1、照合順序は latin1_danish_ci となります。

例 4: データベース、テーブル、およびカラムの定義

CREATE DATABASE d1 DEFAULT CHARACTER SET latin2 COLLATE latin2_czech_ci;
USE d1;
CREATE TABLE t1
( c1 CHAR(10)
);

文字セットと照合順序を指定せずにカラムを作成します。テーブルレベルの文字セットと照合順序も指定しません。この状況では、MySQL は、データベースレベルをチェックして、テーブル設定を特定します。その後、この設定がカラム設定になります。したがって、カラム c1 の文字セットは latin2、照合順序は latin2_czech_ci となります。

10.1.3.8 ほかの DBMS との互換性

MaxDB との互換性について、次の 2 つのステートメントは同じです。

CREATE TABLE t1 (f1 CHAR(N) UNICODE);
CREATE TABLE t1 (f1 CHAR(N) CHARACTER SET ucs2);

10.1.4 接続文字セットおよび照合順序

複数の文字セットおよび照合順序のシステム変数は、サーバーとのクライアントの通信に関係しています。これらのいくつかは、これまでのセクションですでに説明されています。

  • サーバー文字セットおよび照合順序は、character_set_server および collation_server システム変数の値です。

  • デフォルトのデータベースの文字セットおよび照合順序は、character_set_database および collation_database システム変数の値です。

その他の文字セットおよび照合順序システム変数は、クライアントとサーバー間の接続のトラフィックの処理に関わっています。どのクライアントも接続関連の文字セットおよび照合順序システム変数を持っています。

接続は、サーバーに接続するときに作成するものです。クライアントは接続を介して、SQL ステートメント (クエリーなど) をサーバーに送信します。サーバーは接続を介して、結果セットやエラーメッセージなどの応答をクライアントに送信します。これによって、次のようなクライアント接続を扱う文字セットおよび照合順序に関する疑問が生じますが、これらはシステム変数の点から回答できます。

  • クライアントから送信されるときに、ステートメントはどの文字セットで送信されますか。

    サーバーは、character_set_client システム変数値を、クライアントが送信するステートメントの文字セットにします。

  • ステートメントを受信したあとで、サーバーはこれをどの文字セットに変換しますか。

    これには、サーバーは character_set_connection および collation_connection システム変数値を使用します。クライアントから送信されたステートメントは、character_set_client から character_set_connection に変換されます (_latin1_utf8 などのイントロデューサがある文字列リテラルを除きます)。collation_connection はリテラル文字列の比較で重要です。カラム値のある文字列の比較には、collation_connection は重要視されません。なぜなら、カラムには独自の照合順序があり、この照合順序が優先されるからです。

  • 結果セットまたはエラーメッセージをクライアントに返送する前に、サーバーはこれらをどの文字セットに変換しますか。

    character_set_results システム変数値は、サーバーがクライアントにクエリー結果を返信するときに使用する文字セットを示します。これには、カラム値などの結果データと、カラム名やエラーメッセージなどの結果メタデータが含まれます。

クライアントは、これらの変数の設定を微調整することも、デフォルトに従うこともできます (この場合は、このセクションの残りをスキップできます)。デフォルトを使用しない場合、サーバーへの接続ごとに文字設定を変更する必要があります。

2 つのステートメントは、接続関連の文字セット変数にグループとして影響します。

  • SET NAMES 'charset_name' [COLLATE 'collation_name']

    SET NAMES は、クライアントからサーバーへの SQL ステートメントの送信に使用される文字セットを示します。したがって、SET NAMES 'cp1251' は、このクライアントから今後受信するメッセージが文字セット cp1251 で送信されることを、サーバーに知らせます。また、クライアントに結果を返信するときにサーバーが使用する文字セットも指定します。(たとえば、SELECT ステートメントを使用する場合に、カラム値に使用する文字セットを指定します。)

    SET NAMES 'charset_name' ステートメントは次の 3 つのステートメントと同等です。

    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET character_set_connection = charset_name;

    character_set_connectioncharset_name に設定すると、collation_connection も暗黙的に charset_name のデフォルト照合順序に設定されます。この照合順序を明示的に設定する必要はありません。特定の照合順序を指定するには、オプションの COLLATE 句を使用します。

    SET NAMES 'charset_name' COLLATE 'collation_name'
  • SET CHARACTER SET charset_name

    SET CHARACTER SETSET NAMES に似ていますが、character_set_connectioncollation_connectioncharacter_set_databasecollation_database に設定します。SET CHARACTER SET charset_name ステートメントは次の 3 つのステートメントと同等です。

    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET collation_connection = @@collation_database;

    collation_connection を設定すると、character_set_connection も、関連付けられた文字セットに暗黙的に設定されます (SET character_set_connection = @@character_set_database の実行と同等です)。character_set_connection を明示的に設定する必要はありません。

注記

ucs2utf16utf16le、および utf32 をクライアント文字セットとして使用することはできません。つまり、これらは SET NAMES または SET CHARACTER SET には機能しません。

MySQL クライアントプログラム mysqlmysqladminmysqlcheckmysqlimport、および mysqlshow は、次のように、使用するデフォルトの文字セットを特定します。

  • ほかの情報が欠如している場合、プログラムは、コンパイル時のデフォルトの文字セット (通常は latin1) を使用します。

  • プログラムは、オペレーティングシステム設定 (たとえば、Unix システムでは LANGLC_ALL ローカル環境変数の値、Windows システムではコードページ設定) に基づいて、使用する文字セットを自動検出できます。ロケールが OS から利用できるシステムの場合、クライアントはコンパイル時のデフォルトを使用するのではなく、このロケールを使用してデフォルトの文字セットを設定します。たとえば、LANGru_RU.KOI8-R に設定すると、koi8r 文字セットが使用されます。したがってユーザーは、MySQL クライアントが使用できるように、自身の環境内でロケールを構成できます。

    OS 文字セットは、正確に一致するものがない場合は、もっとも近い MySQL 文字セットにマップされます。一致した文字セットをサポートしていない場合、クライアントはコンパイルイ時のデフォルトを使用します。たとえば、ucs2 は接続文字セットとしてはサポートされていません。

    C アプリケーションは、サーバーに接続する前に次のように mysql_options() を呼び出すことによって、OS 設定に基づいて文字セットの自動検出を使用できます。

    mysql_options(mysql, MYSQL_SET_CHARSET_NAME, MYSQL_AUTODETECT_CHARSET_NAME);
  • プログラムは --default-character-set オプションをサポートしており、ユーザーはこのオプションを使用すると文字セットを明示的に指定でき、クライアントがそれ以外のどのデフォルトを指定していても、それをオーバーライドできます。

クライアントはサーバーに接続するときに、使用する文字セットの名前を送信します。サーバーはこの名前を使用して、character_set_clientcharacter_set_results、および character_set_connection システム変数を設定します。実際には、サーバーは文字セット名を使用して SET NAMES 操作を実行します。

mysql クライアントの場合、デフォルトとは別の文字セットを使用するには、起動するたびに、SET NAMES を明示的に実行できます。より簡単に同じ結果を得るには、--default-character-set オプション設定を mysql コマンド行またはオプションファイルに追加します。たとえば、次のオプションファイル設定は、mysql を呼び出すたびに、koi8r に設定された 3 つの接続関連の文字セット変数を変更します。

[mysql]
default-character-set=koi8r

自動再接続を有効にして mysql クライアントを使用している場合は (推奨しません)、SET NAMES ではなく charset コマンドを使用することをお勧めします。例:

mysql> charset utf8Charset changed

charset コマンドは、SET NAMES ステートメントを発行し、接続の切断後に再接続するときに mysql が使用するデフォルトの文字セットも変更します。

例: column1CHAR(5) CHARACTER SET latin2 として定義されているとします。SET NAMES または SET CHARACTER SET を指定しない場合、SELECT column1 FROM t に対して、サーバーは、接続時にクライアントが指定した文字セットを使用して、column1 のすべての値を送り返します。反対に、SET NAMES 'latin1' または SET CHARACTER SET latin1SELECT ステートメントを発行する前に指定した場合、サーバーは結果を返信する直前に、latin2 の値を latin1 に変換します。両方の文字セットに存在しない文字がある場合、変換の損失が大きくなる可能性があります。

サーバーに結果セットまたはエラーメッセージの変換を実行させない場合は、character_set_resultsNULL または binary に設定してください。

SET character_set_results = NULL;

接続に適用する文字セットおよび照合順序システム変数の値を確認するには、次のステートメントを使用してください。

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

MySQL アプリケーションを実行する環境も考慮する必要があります。セクション10.1.5「アプリケーションの文字セットおよび照合順序の構成」を参照してください。

文字セットおよびエラーメッセージの詳細は、セクション10.1.6「エラーメッセージの文字セット」を参照してください。

10.1.5 アプリケーションの文字セットおよび照合順序の構成

デフォルトの MySQL 文字セットおよび照合順序 (latin1latin1_swedish_ci) を使用してデータを格納するアプリケーションの場合、特別な構成は必要ありません。別の文字セットまたは照合順序を使用したデータストレージが必要なアプリケーションの場合は、次の複数の方法で、文字セット情報を構成できます。

  • データベースごとに文字設定を指定します。たとえば、あるデータベースを使用するアプリケーションでは utf8 が必要で、別のデータベースを使用するアプリケーションでは sjis が必要な場合があります。

  • サーバーの起動時に文字設定を指定します。これにより、サーバーは、ほかの調整を行わないすべてのアプリケーションに、所定の設定を使用します。

  • ソースから MySQL を構築する場合は、構成時に文字設定を指定します。これにより、サーバーはすべてのアプリケーションに対して所定の設定を使用し、サーバーの起動時に指定する必要がなくなります。

異なるアプリケーションで別々の文字設定が必要な場合は、データベースごとの手法で十分対応できます。ほとんどまたはすべてのアプリケーションで同じ文字セットを使用する場合は、サーバーの起動時または構成時に文字設定を指定する方法がもっとも便利です。

データベースごとの手法またはサーバー起動の手法では、設定によって、データストレージの文字セットが制御されます。アプリケーションはまた、次の手順で説明するように、クライアントとサーバー間の通信に使用する文字セットをサーバーに知らせる必要もあります。

ここで示す例では、utf8 文字セットと utf8_general_ci 照合順序を使用することを想定しています。

データベースごとに文字設定を指定します。テーブルで所定のデフォルトの文字セットおよび照合順序をデータストレージに使用するようなデータベースを作成するには、次のような CREATE DATABASE ステートメントを使用します。

CREATE DATABASE mydb DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

データベース内に作成されたテーブルは、すべての文字カラムに対してデフォルトで utf8utf8_general_ci を使用します。

データベースを使用するアプリケーションは、接続するたびに、サーバーへの接続を構成する必要もあります。これは、接続後に SET NAMES 'utf8' ステートメントを実行することによって行えます。このステートメントは、接続方法 (mysql クライアント、PHP スクリプトなど) とは無関係に使用できます。

場合によっては、必要な文字セットを別の方法で使用するように接続を構成できます。たとえば、mysql を使用して行われた接続の場合、--default-character-set=utf8 コマンド行オプションを指定すると、SET NAMES 'utf8' と同じ効果を得ることができます。

クライアント接続の構成の詳細は、セクション10.1.4「接続文字セットおよび照合順序」を参照してください。

データベースのデフォルトの文字セットまたは照合順序を変更する場合、データベースのデフォルトを使用するストアドルーチンを削除して、新しいデフォルトを使用するように再作成する必要があります。(ストアドルーチンでは、文字セットまたは照合順序が明示的に指定されていない場合、文字データ型を伴う変数は、データベースのデフォルトを使用します。セクション13.1.15「CREATE PROCEDURE および CREATE FUNCTION 構文」を参照してください。)

サーバーの起動時に文字設定を指定します。サーバーの起動時に文字セットおよび照合順序を選択するには、--character-set-server および --collation-server オプションを使用します。たとえば、オプションファイルでオプションを指定するには、次の行を含めます。

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

これらの設定は、サーバー全体に適用され、任意のアプリケーションによって作成されたデータベースのデフォルトおよびこれらのデータベース内に作成されたテーブルのデフォルトとして適用されます。

前述のように、アプリケーションは引き続き、接続したあとで SET NAMES または同等のステートメントを使用して、その接続を構成する必要があります。--init_connect="SET NAMES 'utf8'" オプションでサーバーを起動して、接続するクライアントごとに SET NAMES を自動的に実行させることができます。ただし、SUPER 権限を持つユーザーには init_connect 値は実行されないので、これによって一貫しない結果が生じます。

MySQL の構成時に文字設定を指定します。ソースから MySQL を構成および構築するときに、文字セットおよび照合順序を選択するには、CMakeDEFAULT_CHARSET および DEFAULT_COLLATION オプションを使用します。

shell> cmake . -DDEFAULT_CHARSET=utf8 \-DDEFAULT_COLLATION=utf8_general_ci

この結果構成されたサーバーは、データベースおよびテーブルのデフォルトと、クライアント接続のデフォルトとして、utf8 および utf8_general_ci を使用します。--character-set-server--collation-server を使用して、サーバー起動時にこれらのデフォルトを指定する必要はありません。また、アプリケーションがサーバーに接続したあとで SET NAMES または同等のステートメントを使用して、その接続を構成する必要もありません。

アプリケーション用に MySQL 文字セットを構成する方法とは無関係に、これらのアプリケーションが実行する環境も考慮する必要があります。エディタで作成したファイルから取得された UTF-8 テキストを使用してステートメントを送信する場合、ファイルのエンコーディングが正しく、オペレーティングシステムで正しく処理されるように、環境のロケールを UTF-8 に設定してファイルを編集する必要があります。端末ウィンドウ内から mysql クライアントを使用する場合、UTF-8 を使用するようにこのウィンドウを構成する必要があります。そのようにしないと、文字が正しく表示されない可能性があります。Web 環境で実行するスクリプトの場合、このスクリプトは、MySQL Server とやり取りできるように文字のエンコーディングを正しく処理する必要があり、ページ内容の表示方法をブラウザが認識できるようにエンコーディングを正しく指定したページを生成する必要があります。たとえば、次の <meta> タグを <head> 要素内に含められます。

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

10.1.6 エラーメッセージの文字セット

このセクションでは、サーバーがエラーメッセージを構築しクライアントに返信する場合にどのように文字セットを使用するかについて説明します。エラーメッセージの (文字セットではなく) 言語の詳細は、セクション10.2「エラーメッセージ言語の設定」を参照してください。

MySQL 5.6 では、サーバーは、UTF-8 を使用してエラーメッセージを構築し、character_set_results システム変数で指定された文字セットでクライアントに返信します。

サーバーは次のようにエラーメッセージを構築します。

  • メッセージテンプレートで UTF-8 が使用されます。

  • メッセージテンプレートのパラメータが、特定のエラーの発生に適用される値に置き換えられます。

    • テーブル名やカラム名などの識別子は、UTF-8 を内部で使用するので、そのままコピーされます。

    • 文字 (非バイナリ) 文字列値は、その文字セットから UTF-8 に変換されます。

    • バイナリ文字列値は、0x20 から 0x7E の範囲のバイトについてはそのままコピーされ、この範囲外のバイトについては \x 16 進エンコーディングを使用してコピーされます。たとえば、0x41CF9FVARBINARY 一意カラムに挿入しようとしたときに重複キーエラーが発生した場合、この結果生成されるエラーメッセージでは UTF-8 が使用され、一部のバイトは 16 進数でエンコードされます。

      Duplicate entry 'A\xC3\x9F' for key 1

メッセージの構築後、これをクライアントに返すために、サーバーはこのメッセージを UTF-8 から、character_set_results システム変数によって指定された文字セットに変換します。character_set_resultsNULL または binary の値がある場合、変換は行われません。変数値が utf8 である場合にも、これが元のエラーメッセージの文字セットに一致するので、変換は行われません。

character_set_results で表すことができない文字の場合、変換中に一部のエンコーディングが行われることがあります。エンコーディングは、Unicode コードポイント値を使用します。

  • Basic Multilingual Plane (BMP) 範囲 (0x0000 から 0xFFFF) 内の文字は、\nnnn 表記を使用して書き込まれます。

  • BMP 範囲外 (0x01000 から 0x10FFFF) の文字は、\+nnnnnn 表記を使用して書き込まれます。

クライアントは、character_set_results を設定して、エラーメッセージを受信するときの文字セットを制御できます。この変数は直接設定することも、SET NAMES などの手段で間接的に設定することもできます。character_set_results の詳細は、セクション10.1.4「接続文字セットおよび照合順序」を参照してください。

クライアントにエラーメッセージを返信する前に character_set_results に変換する間に行われるエンコーディングの結果、以前のバージョン (MySQL 5.5 より前のバージョン) とは異なるメッセージ内容になることがあります。たとえば、 (カタカナのペ) という名前のテーブルを削除しようとしたときにエラーが発生し、character_set_results が、この文字を含まない latin1 などの文字セットである場合、クライアントに送信される結果のメッセージには、次のようにエンコードされたテーブル名が表示されます。

ERROR 1051 (42S02): Unknown table '\30DA'

MySQL 5.5 より前では、次のように名前はエンコードされません。

ERROR 1051 (42S02): Unknown table 'ペ'

10.1.7 照合順序の問題

以降のセクションでは、文字セットの照合順序のさまざまな側面について説明します。

10.1.7.1 照合順序名

MySQL 照合順序名は次のルールに従います。

  • _ci で終わる名前は大文字と小文字を区別しない照合順序を示します。

  • _cs で終わる名前は、大文字と小文字を区別する照合順序を示します。

  • _bin で終わる名前はバイナリ照合順序を示します。文字の比較は、文字バイナリコード値に従って行われます。

  • Unicode 照合順序名には、照合順序が従う Unicode 照合アルゴリズム (UCA) のバージョンを示すバージョン番号が含まれることがあります。名前にバージョン番号が含まれない UCA ベースの照合順序は、バージョン 4.0.0 UCA 重みキー (http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt) を使用します。utf8_unicode_520_ci などの照合順序名は、UCA 5.2.0 重みキー (http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt) に基づきます。

10.1.7.2 SQL ステートメントでの COLLATE の使用

COLLATE 句では、比較に対するデフォルト照合順序が何であれ、オーバーライドできます。SQL ステートメントのさまざまな個所で COLLATE を使用できます。次にいくつかの例を示します。

  • ORDER BY を指定した場合

    SELECT k
    FROM t1
    ORDER BY k COLLATE latin1_german2_ci;
  • AS を指定した場合

    SELECT k COLLATE latin1_german2_ci AS k1
    FROM t1
    ORDER BY k1;
  • GROUP BY を指定した場合

    SELECT k
    FROM t1
    GROUP BY k COLLATE latin1_german2_ci;
  • 集計関数を指定した場合

    SELECT MAX(k COLLATE latin1_german2_ci)
    FROM t1;
  • DISTINCT を指定した場合

    SELECT DISTINCT k COLLATE latin1_german2_ci
    FROM t1;
  • WHERE を指定した場合

     SELECT * FROM t1 WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k;
     SELECT * FROM t1 WHERE k LIKE _latin1 'Müller' COLLATE latin1_german2_ci;
  • HAVING を指定した場合

    SELECT k
    FROM t1
    GROUP BY k
    HAVING k = _latin1 'Müller' COLLATE latin1_german2_ci;

10.1.7.3 COLLATE 句の優先順位

COLLATE 句は優先順位が高いため (|| より上位)、次の 2 つの式は同等です。

x || y COLLATE z
x || (y COLLATE z)

10.1.7.4 照合順序と文字セットとの適切な対応

各文字セットには 1 つ以上の照合順序があり、各照合順序は 1 つの文字セットにのみ関連付けられています。したがって、次のステートメントではエラーメッセージが表示されます。latin2_bin 照合順序は latin1 文字セットに対して有効ではないからです。

mysql> SELECT _latin1 'x' COLLATE latin2_bin;ERROR 1253 (42000): COLLATION 'latin2_bin' is not valid
for CHARACTER SET 'latin1'

10.1.7.5 式の照合順序

大多数のステートメントでは、MySQL がどの照合順序を使用して比較演算を行うかは明確になっています。たとえば、次の場合、照合順序がカラム charset_name の照合順序であることは明らかです。

SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;

ただし、複数のオペランドがあると、あいまいさが生じることがあります。例:

SELECT x FROM T WHERE x = 'Y';

カラム x の照合順序を使用して比較したほうがよいでしょうか、それとも文字列リテラル 'Y' の照合順を使用して比較したほうがよいででしょうか。x'Y' の両方に照合順序がありますが、どちらの照合順序が優先されるでしょうか。

標準 SQL では、強制性ルールと呼ばれていた方法で上記の問題を解決しています。MySQL は次のように強制性値を割り当てます。

  • 明示的な COLLATE 句の強制性は 0 です。(強制性がまったくありません。)

  • 照合順序の異なる 2 つの文字列を連結すると強制性は 1 になります。

  • カラムまたはストアドルーチンのパラメータまたはローカル変数の照合順序の強制性は 2 です。

  • システム定数 (USER() または VERSION() などの関数で返される文字列) の強制性は 3 です。

  • リテラルの照合順序の強制性は 4 です。

  • NULL または NULL から派生した式の強制性 5 です。

MySQL は、次のルールとともに強制性値を使用して、あいまいさを解決します。

  • 強制性値がもっとも低い照合順序を使用します。

  • 両方の側で強制性が同じ場合は、次のようになります。

    • 両方の側が Unicode であるか、両方の側が Unicode ではない場合は、エラーになります。

    • どちらかの側に Unicode 文字セットがあり、もう一方の側に Unicode 以外の文字セットがある場合、Unicode 文字セットの側が優先され、Unicode 以外の側に自動文字セット変換が適用されます。たとえば、次のステートメントはエラーを返しません。

      SELECT CONCAT(utf8_column, latin1_column) FROM t1;

      これは、utf8 の文字セットと、utf8_column と同じ照合順序を含む結果を返します。連結する前に、latin1_column の値は自動的に、utf8 に変換されます。

    • 同じ文字セットのオペランドだが、_bin 照合順序と _ci または _cs 照合順序が混在したオペランドを使用した演算の場合、_bin 照合順序が使用されます。これは、対象がデータ型でなく照合順序である点を除けば、非バイナリ文字列とバイナリ文字列が混在した演算でオペランドがバイナリ文字列に評価される方法に似ています。

自動変換機能は SQL 標準には含まれていません。ただし、どの文字セットも (サポートされている文字に関して) Unicode のサブセットであることが SQL 標準のドキュメントに記載されています。スーパーセットに適用されるものはサブセットにも適用されるというよく知られた原則があるので、Unicode の照合順序は Unicode 以外の文字列との比較にも適用できると考えられます。

例:

比較使用される照合順序
column1 = 'A'column1 の照合順序を使用します
column1 = 'A' COLLATE x'A' COLLATE x の照合順序を使用します
column1 COLLATE x = 'A' COLLATE yエラー

COERCIBILITY() 関数を使用すると、文字列式の強制性を特定できます。

mysql> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci); -> 0
mysql> SELECT COERCIBILITY(VERSION()); -> 3
mysql> SELECT COERCIBILITY('A'); -> 4

セクション12.14「情報関数」を参照してください。

CONCAT(1, 'abc') での引数 1 に対して行われる変換など、数値または時間値の文字列への暗黙の変換の場合、その結果は、character_set_connection および collation_connection システム変数で指定された文字セットおよび照合順序を持つ文字 (非バイナリ) 列になります。セクション12.2「式評価での型変換」を参照してください。

10.1.7.6 _bin および binary 照合順序

このセクションでは、非バイナリ文字列の _bin 照合順序が、バイナリ文字列の binary照合順序とどのように異なるかについて説明します。

非バイナリ文字列 (CHARVARCHAR、および TEXT データ型に格納) には、文字セットと照合順序があります。特定の文字セットには複数の照合順序が対応していることがあり、そのそれぞれが、セット内の文字の具体的なソートおよび比較順序を定義しています。これらの中の 1 つが文字セットのバイナリ照合順序であり、その照合順序名の中には _bin サフィクスがあります。たとえば、latin1utf8 には、latin1_bin および utf8_bin という名前のバイナリ照合順序があります。

バイナリ文字列 (BINARYVARBINARY、および BLOB データ型に格納) には、非バイナリ文字列にあるような文字セットや照合順序はありません。(CHARSET()COLLATION() 関数はどちらも、バイナリ文字列に適用されると binary の値を返します。)バイナリ文字列はバイトのシーケンスであり、これらのバイトの数値がソート順序を決定します。

_bin 照合順序は、いくつかの点で binary 照合順序と異なります。

ソートおよび比較の単位。バイナリ文字列は、バイトのシーケンスです。ソートおよび比較は、常に数値のバイト値に基づきます。非バイナリ文字列は文字のシーケンスであり、これはマルチバイトであることもあります。非バイナリ文字列の照合順序は、文字値のソートおよび比較の順序を定義します。_bin 照合順序の場合、この順序は文字のバイナリコード値にのみ基づきます (これは、_bin 照合順序では複数バイトの文字の可能性を考慮に入れる必要がある点を除き、バイナリ文字列の順序に似ています)。ほかの照合順序の場合、文字の順序は、大文字と小文字の区別などのその他の要素を考慮に入れることがあります。

文字セットの変換。非バイナリ文字列には文字セットがあり、多くの場合、文字列に _bin 照合順序があるときでも、別の文字セットに変換されます。

  • 別の文字セットを持つほかのカラムから、カラム値を割り当てる場合:

    UPDATE t1 SET utf8_bin_column=latin1_column;
    INSERT INTO t1 (latin1_column) SELECT utf8_bin_column FROM t2;
  • 文字列リテラルを使用して、INSERT または UPDATE のカラム値を割り当てる場合:

    SET NAMES latin1;
    INSERT INTO t1 (utf8_bin_column) VALUES ('string-in-latin1');
  • サーバーからクライアントに結果を送信する場合:

    SET NAMES latin1;
    SELECT utf8_bin_column FROM t2;

バイナリ文字列カラムの場合、変換は行われません。前述の場合、文字列値はバイトのようにコピーされます。

大文字と小文字の変換。照合順序は文字の大文字と小文字に関する情報をもたらすので、非バイナリ文字列内の文字は大文字と小文字を変換できます。これは、順序で大文字と小文字の区別を無視する _bin 照合順序の場合でも該当します。

mysql> SET NAMES latin1 COLLATE latin1_bin;Query OK, 0 rows affected (0.02 sec)
mysql> SELECT LOWER('aA'), UPPER('zZ');+-------------+-------------+
| LOWER('aA') | UPPER('zZ') |
+-------------+-------------+
| aa | ZZ |
+-------------+-------------+
1 row in set (0.13 sec)

大文字と小文字という概念は、バイナリ文字列内のバイトには適用されません。大文字と小文字の変換を行うには、文字列を非バイナリ文字列に変換する必要があります。

mysql> SET NAMES binary;Query OK, 0 rows affected (0.00 sec)
mysql> SELECT LOWER('aA'), LOWER(CONVERT('aA' USING latin1));+-------------+-----------------------------------+
| LOWER('aA') | LOWER(CONVERT('aA' USING latin1)) |
+-------------+-----------------------------------+
| aA | aa |
+-------------+-----------------------------------+
1 row in set (0.00 sec)

比較での後続スペースの処理。非バイナリ文字列には、_bin 照合順序を含むすべての照合順序に対する PADSPACE 動作があります。後続スペースは比較で意味がありません。

mysql> SET NAMES utf8 COLLATE utf8_bin;Query OK, 0 rows affected (0.00 sec)
mysql> SELECT 'a ' = 'a';+------------+
| 'a ' = 'a' |
+------------+
| 1 |
+------------+
1 row in set (0.00 sec)

バイナリ文字列では、後続スペースを含むすべての文字が比較で重要になります。

mysql> SET NAMES binary;Query OK, 0 rows affected (0.00 sec)
mysql> SELECT 'a ' = 'a';+------------+
| 'a ' = 'a' |
+------------+
| 0 |
+------------+
1 row in set (0.00 sec)

挿入および取り出しでの後続スペースの処理。CHAR(N) 列には非バイナリ文字列が格納されます。N 文字より短い値は、挿入時にスペースで拡張されます。取り出しの場合、後続スペースは削除されます。

BINARY(N) 列にはバイナリ文字列が格納されます。N バイトより短い値は、挿入時に 0x00 バイトで拡張されます。取り出しの場合、何も削除されず、宣言された長さの値が常に返されます。

mysql> CREATE TABLE t1 ( ->  a CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin, ->  b BINARY(10) -> );Query OK, 0 rows affected (0.09 sec)
mysql> INSERT INTO t1 VALUES ('a','a');Query OK, 1 row affected (0.01 sec)
mysql> SELECT HEX(a), HEX(b) FROM t1;+--------+----------------------+
| HEX(a) | HEX(b) |
+--------+----------------------+
| 61 | 61000000000000000000 |
+--------+----------------------+
1 row in set (0.04 sec)

10.1.7.7 BINARY 演算子

BINARY 演算子は、それに続く文字列をバイナリ文字列にキャストします。これは、比較を文字ごとでなくバイトごとに強制的に実行させる簡単な方法です。また、BINARY では末尾の空白文字が重要になります。

mysql> SELECT 'a' = 'A'; -> 1
mysql> SELECT BINARY 'a' = 'A'; -> 0
mysql> SELECT 'a' = 'a '; -> 1
mysql> SELECT BINARY 'a' = 'a '; -> 0

BINARY strCAST(str AS BINARY) の略でもあります。

文字カラム定義内の BINARY 属性には別の効果があります。BINARY 属性で定義された文字カラムには、カラム文字セットのバイナリ照合順序が割り当てられます。すべての文字セットにバイナリ照合順序があります。たとえば、latin1 文字セットのバイナリ照合順序は latin1_bin です。このためテーブルのデフォルト文字セットが latin1 の場合、次の 2 つのカラム定義は同等になります。

CHAR(10) BINARY
CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin

BINARY のカラム属性としての効果は、MySQL 4.1 より前の効果とは異なります。以前は、BINARY は、バイナリ文字列として扱われたカラムになっていました。バイナリ文字列は、文字セットや照合順序がないバイトの文字列であり、バイナリ照合順序を持つ非バイナリ文字列とは異なります。どちらのタイプの文字列についても、比較は文字列単位の数値に基づいて行われますが、非バイナリ文字列については、単位は文字であり、文字セットによってはマルチバイト文字をサポートします。セクション11.4.2「BINARY および VARBINARY 型」を参照してください。

CHARVARCHAR、または TEXT カラムの定義で CHARACTER SET binary を使用すると、このカラムはバイナリデータ型として扱われます。たとえば、次のペアになった定義は同等です。

CHAR(10) CHARACTER SET binary
BINARY(10)
VARCHAR(10) CHARACTER SET binary
VARBINARY(10)
TEXT CHARACTER SET binary
BLOB

10.1.7.8 照合順序の効果の例

例 1: ドイツ語のウムラウトのソート

テーブル T のカラム X に次の latin1 カラムの値が設定されているとします。

Muffler
Müller
MX Systems
MySQL

さらに、次のステートメントを使用してカラムの値を取得するとします。

SELECT X FROM T ORDER BY X COLLATE collation_name;

次の表に、別の照合順序で ORDER BY を使用した場合に得られる値の順序を示します。

latin1_swedish_cilatin1_german1_cilatin1_german2_ci
MufflerMufflerMüller
MX SystemsMüllerMuffler
MüllerMX SystemsMX Systems
MySQLMySQLMySQL

この例でソート順の違いを生じさせている文字は、頭に 2 つの点が付いた U (ü) であり、これはドイツ語でU ウムラウトと呼ばれているものです。

  • 最初のカラムには、スウェーデン語/フィンランド語の照合ルールを使用した SELECT の結果が示されています。この照合ルールによると、U ウムラウトは Y とソート順が一致します。

  • 2 番目のカラムには、German DIN-1 ルールを使用した SELECT の結果が示されています。この照合ルールによると、U ウムラウトは U とソート順が一致します。

  • 3 番目のカラムには、German DIN-2 ルールを使用した SELECT の結果が示されています。この照合ルールによると、U ウムラウトは UE とソート順が一致します。

例 2: ドイツ語のウムラウトの検索

使用される文字セットと照合順序だけが異なる次の 3 つのテーブルがあるとします。

mysql> SET NAMES utf8;mysql> CREATE TABLE german1 ( ->  c CHAR(10) -> ) CHARACTER SET latin1 COLLATE latin1_german1_ci;mysql> CREATE TABLE german2 ( ->  c CHAR(10) -> ) CHARACTER SET latin1 COLLATE latin1_german2_ci;mysql> CREATE TABLE germanutf8 ( ->  c CHAR(10) -> ) CHARACTER SET utf8 COLLATE utf8_unicode_ci;

各テーブルには次の 2 つのレコードが含まれます。

mysql> INSERT INTO german1 VALUES ('Bar'), ('Bär');mysql> INSERT INTO german2 VALUES ('Bar'), ('Bär');mysql> INSERT INTO germanutf8 VALUES ('Bar'), ('Bär');

上記の照合順序の 2 つには A = Ä の等式が含まれ、1 つにはこのような等式はありません (latin1_german2_ci)。そのため、比較では次の結果が得られます。

mysql> SELECT * FROM german1 WHERE c = 'Bär';+------+
| c |
+------+
| Bar |
| Bär |
+------+
mysql> SELECT * FROM german2 WHERE c = 'Bär';+------+
| c |
+------+
| Bär |
+------+
mysql> SELECT * FROM germanutf8 WHERE c = 'Bär';+------+
| c |
+------+
| Bar |
| Bär |
+------+

これはバグではなく、latin1_german1_ciutf8_unicode_ci のソートプロパティーの結果です (示されたソートは、German DIN 5007 標準に従って行われています)。

10.1.7.9 照合順序と INFORMATION_SCHEMA 検索

INFORMATION_SCHEMA テーブルでの文字列カラムには utf8_general_ci の照合順序があり、これは大文字と小文字を区別しません。ただし、INFORMATION_SCHEMA 文字列カラムでの検索には、ファイルシステムでの大文字と小文字の区別も影響します。データベースやテーブルの名前など、ファイルシステムで表されるオブジェクトに対応する値については、ファイルシステムで大文字と小文字を区別する場合は、検索で大文字と小文字が区別されることがあります。このセクションでは、必要に応じて、この問題を解決する方法を説明します。Bug #34921 も参照してください。

クエリーで、test データベースに対し SCHEMATA.SCHEMA_NAME カラムを検索するとします。Linux では、ファイルシステムで大文字と小文字を区別するので、SCHEMATA.SCHEMA_NAME'test' との比較は一致しますが、'TEST' との比較は一致しません。

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME = 'test';+-------------+
| SCHEMA_NAME |
+-------------+
| test |
+-------------+
1 row in set (0.01 sec)
mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME = 'TEST';Empty set (0.00 sec)

Windows または OS X では、ファイルシステムで大文字と小文字を区別しないので、比較は 'test''TEST' の両方と一致します。

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME = 'test';+-------------+
| SCHEMA_NAME |
+-------------+
| test |
+-------------+
1 row in set (0.00 sec)
mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME = 'TEST';+-------------+
| SCHEMA_NAME |
+-------------+
| TEST |
+-------------+
1 row in set (0.00 sec)

lower_case_table_names システム変数の値はこのコンテキストでは違いをもたらしません。

ファイルシステム内でデータベースオブジェクトを検索するときに、INFORMATION_SCHEMA クエリーで utf8_general_ci 照合順序が使用されていないために、このような処理が行われます。これは、MySQL での INFORMATION_SCHEMA 検索に対して実装された最適化の結果です。これらの最適化の詳細は、セクション8.2.4「INFORMATION_SCHEMA クエリーの最適化」を参照してください。

INFORMATION_SCHEMA仮想データベースであり、ファイルシステムには表されないので、INFORMATION_SCHEMA 文字列カラム内で INFORMATION_SCHEMA 自体を参照する値を検索する場合、utf8_general_ci 照合順序を使用します。たとえば、SCHEMATA.SCHEMA_NAME との比較は、プラットフォームに関係なく、'information_schema' または 'INFORMATION_SCHEMA' に一致します。

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME = 'information_schema';+--------------------+
| SCHEMA_NAME |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)
mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME = 'INFORMATION_SCHEMA';+--------------------+
| SCHEMA_NAME |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)

INFORMATION_SCHEMA カラムでの文字列演算の結果が予想と異なる場合、回避策は、明示的な COLLATE 句を使用して、適切な照合順序を強制的に使用することです (セクション10.1.7.2「SQL ステートメントでの COLLATE の使用」)。たとえば、大文字と小文字を区別しない検索を実行するには、INFORMATION_SCHEMA カラム名とともに COLLATE を使用します。

mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME COLLATE utf8_general_ci = 'test';+-------------+
| SCHEMA_NAME |
+-------------+
| test |
+-------------+
1 row in set (0.00 sec)
mysql> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA -> WHERE SCHEMA_NAME COLLATE utf8_general_ci = 'TEST';| SCHEMA_NAME |
+-------------+
| test |
+-------------+
1 row in set (0.00 sec)

UPPER() または LOWER() 関数を使用することもできます。

WHERE UPPER(SCHEMA_NAME) = 'TEST'
WHERE LOWER(SCHEMA_NAME) = 'test'

大文字と小文字を区別するファイルシステムのプラットフォームでも、大文字と小文字を区別しない比較を実行できますが、前述のように、必ずしも常に正しい処理になるとはかぎりません。このようなプラットフォームでは、大文字と小文字だけが異なる名前の複数のオブジェクトが存在する可能性があります。たとえば、cityCITY、および City という名前のテーブルがすべて同時に存在することが可能です。検索でこれらのすべての名前に一致するか、1 つだけに一致するかを検討し、それに応じてクエリーを作成します。

WHERE TABLE_NAME COLLATE utf8_bin = 'City'
WHERE TABLE_NAME COLLATE utf8_general_ci = 'city'
WHERE UPPER(TABLE_NAME) = 'CITY'
WHERE LOWER(TABLE_NAME) = 'city'

これらのうち最初の比較 (utf8_bin 使用) では大文字と小文字を区別します。ほかの比較では区別しません。

10.1.8 文字列のレパートリー

文字セットのレパートリーとは、そのセット内の文字の集合です。

文字列式にはレパートリー属性があり、その値は次の 2 つです。

  • ASCII: U+0000 から U+007F の Unicode 範囲内の文字だけを式に含めることができます。

  • UNICODE: U+0000 から U+FFFF の Unicode 範囲内の文字を式に含めることができます。

ASCII 範囲は UNICODE 範囲のサブセットであるので、ASCII レパートリーの文字列は、UNICODE レパートリーの文字列の文字セットに、または ASCII のスーパーセットである文字セットに、情報を失うことなく安全に変換できます。(すべての MySQL 文字セットは、スウェーデン語のアクセント符号付き文字に一部の句読点文字を再使用する swe7 を除き、ASCII のスーパーセットです。)MySQL から照合順序の不正な混在エラーが返されるような多くの場合でも、レパートリーを使用すると、式内の文字セットを変換できます。

次の説明では、式とそのレパートリーの例を挙げ、レパートリーの使用によって、文字列式の評価がどのように変わるかを示します。

  • 文字列定数のレパートリーは、文字列の内容に応じて異なります。

    SET NAMES utf8; SELECT 'abc';
    SELECT _utf8'def';
    SELECT N'MySQL';

    前述のそれぞれの場合では文字セットは utf8 ですが、実際には ASCII 範囲外の文字は 1 つも文字列に含まれていないので、そのレパートリーは UNICODE ではなく ASCII です。

  • ascii 文字セットを含むカラムには、その文字セットのために、ASCII レパートリーがあります。次のテーブルでは、c1 には ASCII レパートリーがあります。

    CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET ascii);

    次の例では、レパートリーがないときにエラーが発生する場合に、レパートリーによってどのように結果が求められるようになるかを示しています。

    CREATE TABLE t1 ( c1 CHAR(1) CHARACTER SET latin1, c2 CHAR(1) CHARACTER SET ascii
    );
    INSERT INTO t1 VALUES ('a','b');
    SELECT CONCAT(c1,c2) FROM t1;

    レパートリーがない場合、次のエラーが発生します。

    ERROR 1267 (HY000): Illegal mix of collations (latin1_swedish_ci,IMPLICIT)
    and (ascii_general_ci,IMPLICIT) for operation 'concat'

    レパートリーを使用すると、サブセットからスーパーセットへ (ascii から latin1 へ) の変換を行うことができ、結果が返されます。

    +---------------+
    | CONCAT(c1,c2) |
    +---------------+
    | ab |
    +---------------+
  • 1 つの文字列引数を持つ関数は、その引数のレパートリーを継承します。UPPER(_utf8'abc') の場合、引数に ASCII レパートリーがあるので、その結果には ASCII レパートリーが存在します。

  • 文字列を返すが、文字列引数を持たず、結果文字セットとして character_set_connection を使用する関数の場合、結果のレパートリーは、character_set_connectionascii である場合は ASCII に、それ以外の場合は UNICODE になります。

    FORMAT(numeric_column, 4);

    レパートリーを使用するかどうかによって、MySQL が次の例をどのように評価するかが変わります。

    SET NAMES ascii;
    CREATE TABLE t1 (a INT, b VARCHAR(10) CHARACTER SET latin1);
    INSERT INTO t1 VALUES (1,'b');
    SELECT CONCAT(FORMAT(a, 4), b) FROM t1;

    レパートリーがない場合、次のエラーが発生します。

    ERROR 1267 (HY000): Illegal mix of collations (ascii_general_ci,COERCIBLE)
    and (latin1_swedish_ci,IMPLICIT) for operation 'concat'

    レパートリーを使用すると、次のように結果が返されます。

    +-------------------------+
    | CONCAT(FORMAT(a, 4), b) |
    +-------------------------+
    | 1.0000b |
    +-------------------------+
  • 2 つ以上の文字列引数を持つ関数は、結果のレパートリーとして、もっとも範囲の広い引数レパートリーを使用します (UNICODEASCII よりも範囲が広くなります)。次の CONCAT() 呼び出しを考えてみます。

    CONCAT(_ucs2 0x0041, _ucs2 0x0042)
    CONCAT(_ucs2 0x0041, _ucs2 0x00C2)

    最初の呼び出しでは、両方の引数が ascii 文字セットの範囲内にあるので、レパートリーは ASCII です。2 番目の呼び出しでは、2 番目の引数が ascii 文字セット範囲外にあるので、レパートリーは UNICODE です。

  • 関数の戻り値のレパートリーは、結果の文字セットおよび照合順序に影響する引数のレパートリーにのみ基づいて定められます。

    IF(column1 < column2, 'smaller', 'greater')

    結果のレパートリーは、2 つの文字列引数 (2 番目の引数と 3 番目の引数) がどちらも ASCII レパートリーなので、ASCII です。最初の引数は、式で文字列値を使用する場合でも、結果のレパートリーにとっては重要ではありません。

10.1.9 文字セットのサポートによる影響を受ける演算

このセクションでは、文字セット情報を考慮した演算について説明します。

10.1.9.1 結果文字列

MySQL には、文字列を返す多数の演算子と関数があります。このセクションでは、そのような文字列の文字セットと照合順序について説明します。

文字列の入力を取得して文字列の結果を出力として返す単純な関数では、出力の文字セットおよび照合順序は、主要な入力値の文字セットおよび照合順序と同じです。たとえば、UPPER(X) は、文字セットおよび照合順序が X と同じ文字列を返します。同じことは、INSTR()LCASE()LOWER()LTRIM()MID()REPEAT()REPLACE()REVERSE()RIGHT()RPAD()RTRIM()SOUNDEX()SUBSTRING()TRIM()UCASE()、および UPPER() についても当てはまります。

注: REPLACE() 関数はほかのどの関数とも異なり、文字列入力の照合順序を無視し、大文字と小文字が区別される比較を毎回実行します。

入力文字列または関数の結果がバイナリ文字列の場合、その文字列には文字セットも照合順序もありません。これは CHARSET()COLLATION() 関数を使ってチェックできます。両関数とも、引数がバイナリ文字列であることを示す binary を返します。

mysql> SELECT CHARSET(BINARY 'a'), COLLATION(BINARY 'a');+---------------------+-----------------------+
| CHARSET(BINARY 'a') | COLLATION(BINARY 'a') |
+---------------------+-----------------------+
| binary | binary |
+---------------------+-----------------------+

複数の文字列入力を組み合わせて単一の文字列出力を返す演算では、結果の照合順序の特定に次の標準 SQL のアグリゲーションルールが適用されます。

  • 明示的な COLLATE X が行われた場合、X を使用します。

  • 明示的な COLLATE XCOLLATE Y が行われた場合、エラーが発生します。

  • 上記以外の場合ですべての照合順序が X であるときは、X を使用します。

  • その他の場合、結果に照合順序はありません。

たとえば、CASE ... WHEN a THEN b WHEN b THEN c COLLATE X END と指定されている場合、結果の照合順序は X になります。同じことは、UNION||CONCAT()ELT()GREATEST()IF()、および LEAST() にも当てはまります。

文字データに変換する演算の場合、この演算の結果得られる文字列の文字セットと照合順序は、character_set_connectioncollation_connection システム変数値によって定義されています。このことは、CAST()CONV()FORMAT()HEX()、および SPACE() にのみ当てはまります。

文字列関数で返される結果の文字セットまたは照合順序について不確かな場合は、CHARSET() または COLLATION() 関数を使用して調べることができます。

mysql> SELECT USER(), CHARSET(USER()), COLLATION(USER());+----------------+-----------------+-------------------+
| USER() | CHARSET(USER()) | COLLATION(USER()) |
+----------------+-----------------+-------------------+
| test@localhost | utf8 | utf8_general_ci |
+----------------+-----------------+-------------------+

10.1.9.2 CONVERT() と CAST()

CONVERT() を使用すると、異なる文字セット間でデータを変換できます。構文は次のとおりです。

CONVERT(expr USING transcoding_name)

MySQL では、トランスコーディング名は対応する文字セット名と同じです。

例:

SELECT CONVERT(_latin1'Müller' USING utf8);
INSERT INTO utf8table (utf8column) SELECT CONVERT(latin1field USING utf8) FROM latin1table;

CONVERT(... USING ...) は、標準 SQL の仕様に基づき実装されています。

CAST() を使用し、文字列を別の文字セットに変換することもできます。構文は次のとおりです。

CAST(character_string AS character_data_type CHARACTER SET charset_name)

例:

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8);

CHARACTER SET を指定せずに CAST() を使用した場合、文字セットと照合順序は character_set_connection および collation_connection システム変数で定義されます。CHARACTER SET X を指定して CAST() を使用した場合、文字セットはX、照合順序は X のデフォルト照合順序になります。

CONVERT() または CAST() 呼び出し内では COLLATE 句を使用できませんが、呼び出し外では使用できます。たとえば、CAST(... COLLATE ...) は無効ですが、CAST(...) COLLATE ... は有効です。

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;

10.1.9.3 SHOW ステートメントと INFORMATION_SCHEMA

複数の SHOW ステートメントから文字セットの追加情報が得られます。これらには SHOW CHARACTER SETSHOW COLLATIONSHOW CREATE DATABASESHOW CREATE TABLE、および SHOW COLUMNS が含まれます。ここでは、これらのステートメントについて簡単に説明します。詳細は、セクション13.7.5「SHOW 構文」を参照してください。

INFORMATION_SCHEMA には、SHOW ステートメントで表示されるものに類似した情報を含む複数のテーブルが含まれます。たとえば、CHARACTER_SETS および COLLATIONS テーブルには、SHOW CHARACTER SET および SHOW COLLATION で表示される情報が含まれます。第21章「INFORMATION_SCHEMA テーブルを参照してください。

SHOW CHARACTER SET ステートメントは使用可能な文字セットをすべて表示します。一致する文字セット名を指定するには、オプションの LIKE 句を使用します。例:

mysql> SHOW CHARACTER SET LIKE 'latin%';+---------+-----------------------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
+---------+-----------------------------+-------------------+--------+

SHOW COLLATION からの出力には、使用可能なすべての文字セットが含まれます。一致する照合順序名を指定するには、オプションの LIKE 句を使用します。例:

mysql> SHOW COLLATION LIKE 'latin1%';+-------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 0 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+-------------------+---------+----+---------+----------+---------+

SHOW CREATE DATABASE は、所定のデータベースを作成する CREATE DATABASE ステートメントを表示します。

mysql> SHOW CREATE DATABASE test;+----------+-----------------------------------------------------------------+
| Database | Create Database |
+----------+-----------------------------------------------------------------+
| test | CREATE DATABASE `test` |
+----------+-----------------------------------------------------------------+

COLLATE 句が表示されていなければ、文字セットのデフォルト照合順序が適用されます。

SHOW CREATE TABLE は類似していますが、所定のテーブルを作成する CREATE TABLE ステートメントを表示します。カラム定義は文字セット仕様を指定し、テーブルオプションは文字セット情報を含んでいます。

SHOW COLUMNS ステートメントは SHOW FULL COLUMNS として呼び出された場合、テーブルのカラムの照合順序を表示します。CHARVARCHAR、または TEXT データ型を含むカラムには照合順序があります。数値型およびほかの非文字型には照合順序はありません (Collation 値として NULL で示されます)。例:

mysql> SHOW FULL COLUMNS FROM person\G*************************** 1. row *************************** Field: id Type: smallint(5) unsigned Collation: NULL Null: NO Key: PRI Default: NULL Extra: auto_increment
Privileges: select,insert,update,references Comment:
*************************** 2. row *************************** Field: name Type: char(60) Collation: latin1_swedish_ci Null: NO Key: Default: Extra:
Privileges: select,insert,update,references Comment:

文字セットは表示の中にはなく、照合順序名で示されます。

10.1.10 Unicode のサポート

Unicode サポートの (MySQL 4.1 での) 初期実装には、Unicode データを格納するための次の 2 つの文字セットが含まれていました。

  • ucs2。文字ごとに 16 ビットを使用する Unicode 文字セットの UCS-2 エンコーディング。

  • utf8。文字ごとに 1 から 3 バイトを使用する Unicode 文字セットの UTF-8 エンコーディング。

これらの 2 つの文字セットは、Unicode バージョン 3.0 の Basic Multilingual Plane (BMP) の文字をサポートします。BMP 文字には次の 3 つの特性があります。

  • これらのコード値は 0 から 65535 (または U+0000 ..U+FFFF) です。

  • これらは、ucs2 と同様に、16 ビット固定の単語でエンコードできます。

  • これらは、utf8 と同様に、8、16、または 24 ビットでエンコードできます。

  • 主要言語のほとんどすべての文字には、これらで十分です。

前述の文字セットではサポートされていない文字には、BMP の範囲外にある補助文字が含まれます。BMP の範囲外の文字は、REPLACEMENT CHARACTER と見なされ、Unicode 文字セットへの変換時に、'?' に変換されます。

MySQL 5.6 での Unicode のサポートには補助文字が含まれるので、範囲がより広いため、より多くのスペースを占める新しい文字セットが必要になります。次の表では、以前の Unicode サポートと現在の Unicode サポートの機能を簡単に比較しています。

MySQL 5.5 より前MySQL 5.5 以降
すべての Unicode 3.0 文字すべての Unicode 5.0 および 6.0 文字
補助文字なし補助文字あり
ucs2 文字セット、BMP のみ変更なし
3 バイトまでの utf8 文字セット、BMP のみ変更なし
 4 バイトまでの新しい utf8mb4 文字セット、BMP または補助
 新しい utf16 文字セット、BMP または補助
 新しい utf16le 文字セット、BMP または補助 (5.6.1 以降)
 新しい utf32 文字セット、BMP または補助

これらの変更には上位互換性があります。新しい文字セットを使用する場合、アプリケーションの非互換性の問題が生じる可能性があります。セクション10.1.11「以前の Unicode サポートから現在の Unicode サポートへのアップグレード」を参照してください。さらにこのセクションでは、utf8 から (4 バイトの) utf8mb4 文字セットに変換する方法と、そのときに適用される可能性がある制約について説明します。

MySQL 5.6 は、次の Unicode 文字セットをサポートします。

  • ucs2。文字ごとに 16 ビットを使用する Unicode 文字セットの UCS-2 エンコーディング。

  • utf16。Unicode 文字セットの UTF-16 エンコーディング。ucs2 に似ていますが、補助文字用の拡張機能があります。

  • utf16le。Unicode 文字セットの UTF-16LE エンコーディング。utf16 と似ていますが、ビッグエンディアンではなくリトルエンディアンです。

  • utf32。文字ごとに 32 ビットを使用した Unicode 文字セットの UTF-32 エンコーディング。

  • utf8。文字ごとに 1 から 3 バイトを使用する Unicode 文字セットの UTF-8 エンコーディング。

  • utf8mb4。文字ごとに 1 から 4 バイトを使用した Unicode 文字セットの UTF-8 エンコーディング。

ucs2 および utf8 は BMP 文字をサポートします。utf8mb4utf16utf16le、および utf32 は、BMP および補助文字をサポートします。

類似した一連の照合順序を、ほとんどの Unicode 文字セットで使用できます。たとえば、それぞれにはデンマーク語の照合順序があり、その名前は ucs2_danish_ciutf16_danish_ciutf32_danish_ciutf8_danish_ci、および utf8mb4_danish_ci です。例外は utf16le であり、2 つの照合順序しかありません。セクション10.1.14.1「Unicode 文字セット」にはすべての Unicode 照合順序が一覧表示されており、補助文字の照合順序プロパティーについても説明しています。

多くの補助文字は東アジアの言語のものですが、MySQL 5.6 で追加するサポートは、Unicode 文字セットでのより多くの日本語と中国語の文字に対するサポートであり、新しい日本語および中国語の文字セットのサポートではありません。

UCS-2、UTF-16、および UTF-32 の MySQL での実装は、ビッグエンディアンのバイト順で文字を格納し、値の先頭にバイト順マーク (BOM) を使用しません。ほかのデータベースシステムでは、リトルエンディアンのバイト順または BOM を使用していることもあります。このような場合、これらのシステムと MySQL の間でデータを転送するときに、値の変換を実行する必要があります。UTF-16LE の実装はリトルエンディアンです。

MySQL は UTF-8 値に BOM を使用しません。

Unicode を使用したサーバーと通信する必要があるクライアントアプリケーションは、たとえば SET NAMES 'utf8' ステートメントを発行することによって、クライアント文字セットをそれに従って設定する必要があります。ucs2utf16utf16le、および utf32 は、クライアント文字セットとして使用できません。つまり、これらは SET NAMES または SET CHARACTER SET で機能しません。(セクション10.1.4「接続文字セットおよび照合順序」を参照してください。)

以降のセクションでは、MySQL における Unicode 文字セットについてさらに詳しく説明します。

10.1.10.1 ucs2 文字セット (UCS-2 Unicode エンコーディング)

UCS-2 では、すべての文字が 2 バイトの Unicode コードで表され、もっとも重要なバイトは 1 番目のバイトです。例: LATIN CAPITAL LETTER A にはコード 0x0041 があり、これは 2 バイトのシーケンス (0x00 0x41) として格納されます。CYRILLIC SMALL LETTER YERU (Unicode 0x044B) は、2 バイトシーケンス (0x04 0x4B) として格納されます。Unicode 文字とそのコードについては、Unicode ホームページを参照してください。

MySQL では、ucs2 文字セットは、Unicode BMP 文字の 16 ビット固定長のエンコーディングです。

10.1.10.2 utf16 文字セット (UTF-16 Unicode エンコーディング)

utf16 文字セットは、補助文字のエンコーディングを可能にする拡張機能を備えた ucs2 文字セットです。

  • BMP 文字の場合、utf16ucs2 には、同じコード値、同じエンコーディング、同じ長さという同一のストレージ特性があります。

  • 補助文字の場合、utf16 には、32 ビットを使用する文字を表すための特殊シーケンスがあります。これは、サロゲートメカニズムと呼ばれます。0xffff より大きな数値の場合、10 ビットを確保して、これらを 0xd800 に追加し、最初の 16 ビット語に配置します。さらに 10 ビットを確保して、これらを 0xdc00 に追加し、次の 16 ビット語に配置します。この結果、すべての補助文字に 32 ビットが必要になります。このうち最初の 16 ビットは 0xd8000xdbff の間の数値であり、残りの 16 ビットは 0xdc000xdfff の間の数値になります。Unicode 4.0 ドキュメントの「15.5 Surrogates Area」に例が記載されています。

utf16 はサロゲートをサポートし、ucs2 をサポートしていないので、utf16 でのみ適用される妥当性チェックがあります。下位サロゲートがなければ上位サロゲートを挿入できず、逆も同様です。例:

INSERT INTO t (ucs2_column) VALUES (0xd800);
INSERT INTO t (utf16_column)VALUES (0xd800); 

技術的に有効であるが真の Unicode ではない文字 (つまり、Unicode が未割り当てコードポイントまたは個人使用文字、さらには 0xffff のように不正と見なす文字) に対する妥当性チェックはありません。たとえば、U+F8FF は Apple のロゴなので、これは有効です。

INSERT INTO t (utf16_column)VALUES (0xf8ff); 

このような文字は、すべてのユーザーに対し同じ意味を持たせることは期待できません。

MySQL は、最悪の場合 (文字が 4 バイトを必要とする場合) に対応する必要があるので、utf16 カラムまたはインデックスの最大長は、ucs2 カラムまたはインデックスの最大長の半分しかありません。たとえば、MySQL 5.6 では、MEMORY テーブルインデックスキーの最大長は、3072 バイトなので、これらのステートメントは、ucs2 および utf16 カラムに対し、最大許容長のインデックスを持つテーブルを作成します。

CREATE TABLE tf (s1 VARCHAR(1536) CHARACTER SET ucs2) ENGINE=MEMORY;
CREATE INDEX i ON tf (s1);
CREATE TABLE tg (s1 VARCHAR(768) CHARACTER SET utf16) ENGINE=MEMORY;
CREATE INDEX i ON tg (s1);

10.1.10.3 utf16le 文字セット (UTF-16LE Unicode エンコーディング)

これは、utf16 と同じですが、ビッグエンディアンではなくリトルエンディアンです。

10.1.10.4 utf32 文字セット (UTF-32 Unicode エンコーディング)

utf32 文字セットは固定長です (ucs2 と同様で、utf16 とは異なります)。utf32 はすべての文字に 32 ビットを使用し、ucs2 (すべての文字に 16 ビットを使用します) とも、utf16 (一部の文字に 16 ビットを、ほかの文字に 32 ビットを使用します) とも異なります。

utf32 は、ucs2 の 2 倍のスペース、utf16 よりも多くのスペースを必要としますが、utf32 には、ストレージについて予測可能であるという ucs2 と同じ利点があります。utf32 に必要なバイト数は文字数の 4 倍になります。また、utf16 とは異なり、utf32 でのエンコーディングにはトリックはないので、格納された値はコード値と等しくなります。

後者の利点がどのように役立つかを説明するために、utf32 コード値のときに utf8mb4 値を求める方法を示した例を挙げます。

CREATE TABLE tmp (utf32_col CHAR(1) CHARACTER SET utf32, utf8mb4_col CHAR(1) CHARACTER SET utf8mb4);
INSERT INTO tmp VALUES (0x000100cc,NULL);
UPDATE tmp SET utf8mb4_col = utf32_col;
SELECT HEX(utf32_col),HEX(utf8mb4_col) FROM tmp;

MySQL では、未割り当ての Unicode 文字または個人使用領域の文字の追加について広く許容しています。実際、utf32 の妥当性チェックは 1 つしかありません。0x10ffff よりも大きなコード値はありません。たとえば次の場合は不正です。

INSERT INTO t (utf32_column) VALUES (0x110000); 

10.1.10.5 utf8 文字セット (3 バイト UTF-8 Unicode エンコーディング)

UTF-8 (8 ビット単位の Unicode Transformation Format) は Unicode データを格納する別の方法です。これは、1 から 4 バイトを使用するエンコーディングシーケンスについて記述した RFC 3629 に従って実装されています。(UTF-8 エンコーディングの以前の標準である RFC 2279 では、1 から 6 バイトを使用する UTF-8 シーケンスについて記述しています。RFC 3629 は RFC 2279 を無効にするため、5 と 6 バイトのシーケンスはすでに使用されていません。)

UTF-8 の概念は、長さの異なるバイトシーケンスを使用してさまざまな Unicode 文字をエンコードするというものです。

  • 基本的なラテン文字、数字、句読点は 1 バイトを使用します。

  • 拡張ラテン文字 (チルダ、長音符号、アキュート、グラーヴェ、およびほかのアクセント符号)、キリル文字、ギリシャ語、アルメニア語、ヘブライ語、アラビア語、シリア語などのほとんどのヨーロッパおよび中東のスクリプト文字は、2 バイトシーケンスに収まります。

  • 韓国語、中国語、および日本語の表意文字は、3 バイトまたは 4 バイトのシーケンスを使用します。

MySQL 5.6 の utf8 文字セットは 5.6 以前と同じであり、特性もまったく同じです。

  • 補助文字のサポートなし (BMP 文字のみ)。

  • マルチバイト文字ごとに最大 3 バイト。

utf8 では ucs2 とちょうど同じ文字セットを使用できます。つまり、レパートリーも同じです。

ヒント: スペースを UTF-8 で保存する場合は、CHAR ではなく VARCHAR を使用してください。そのようにしないと、MySQL では CHAR CHARACTER SET utf8 カラムに対して 3 バイトを確保する必要があります。これは、可能性のある最大長が 3 バイトであるためです。たとえば、MySQL は CHAR(10) CHARACTER SET utf8 カラムに対して 30 バイトを確保する必要があります。

データ型のストレージの詳細は、セクション11.7「データ型のストレージ要件」を参照してください。COMPACT 行フォーマットを使用する InnoDB テーブルが UTF-8 CHAR(N) カラムを内部で処理する方法を含め、InnoDB 物理行ストレージの詳細は、セクション14.2.13.7「物理的な行構造」を参照してください。

10.1.10.6 utf8mb3 文字セット (utf8 のエイリアス)

MySQL の今後のバージョンでは、utf8 が 4 バイトの utf8 になり、3 バイトの utf8 を指定するときに utf8mb3 を示す必要が生じる可能性があります。マスターサーバーとスレーブサーバーの MySQL のバージョンが異なるときにレプリケーションで生じる将来の問題を回避するために、ユーザーは、CHARACTER SET 句で utf8mb3 を、COLLATE 句で utf8mb3_collation_substring を指定できます。ここで、collation_substringbinczech_cidanish_ciesperanto_ciestonian_ci などです。例:

CREATE TABLE t (s1 CHAR(1) CHARACTER SET utf8mb3;
SELECT * FROM t WHERE s1 COLLATE utf8mb3_general_ci = 'x';
DECLARE x VARCHAR(5) CHARACTER SET utf8mb3 COLLATE utf8mb3_danish_ci;
SELECT CAST('a' AS CHAR CHARACTER SET utf8) COLLATE utf8_czech_ci;

MySQL は即座に、エイリアス内の utf8mb3 のインスタンスを、utf8 に変換するので、SHOW CREATE TABLESELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLUMNSSELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS などのステートメントでは、真の名前、utf8、または utf8_collation_substring がユーザーに表示されます。

utf8mb3 エイリアスは、CHARACTER SET 句と、ほかの特定の場所でのみ有効です。たとえば、次の場合は有効です。

mysqld --character-set-server=utf8mb3
SET NAMES 'utf8mb3';
SELECT _utf8mb3 'a';

照合順序が基づいている Unicode 照合アルゴリズムのバージョンを示すバージョン番号を含む照合順序名 (utf8_unicode_520_ci など) を表す、対応する utf8 照合順序の utf8mb3 エイリアスはありません。

10.1.10.7 utf8mb4 文字セット (4 バイトの UTF-8 Unicode エンコーディング)

utf8 という名前の文字セットは、文字あたり最大 3 バイトを使用し、BMP 文字だけを含みます。utf8mb4 文字セットは、文字ごとに最大 4 バイトを使用し、補助文字をサポートします。

  • BMP 文字の場合、utf8utf8mb4 のストレージ特性は同一で、コード値、エンコーディング、長さが同じです。

  • 補助文字については、utf8 はこの文字をまったく格納できませんが、utf8mb4 は文字の格納に 4 バイトを必要とします。utf8 はこの文字をまったく格納しないので、utf8 カラムには補助文字がなく、utf8 データを古いバージョンの MySQL からアップグレードするときに、文字の変換やデータの損失について心配する必要はありません。

utf8mb4utf8 のスーパーセットであるので、次の連結のような演算の場合、その結果には utf8mb4 の文字セットと utf8mb4_col の照合順序が含まれます。

SELECT CONCAT(utf8_col, utf8mb4_col);

同様に、次の WHERE 句内の比較は、utf8mb4_col の照合順序に従って行われます。

SELECT * FROM utf8_tbl, utf8mb4_tbl
WHERE utf8_tbl.utf8_col = utf8mb4_tbl.utf8mb4_col;

ヒント: スペースを UTF-8 で保存する場合は、CHAR ではなく VARCHAR を使用してください。そのようにしないと、MySQL では CHAR CHARACTER SET utf8 (または utf8mb4) カラムに対して 3 (または 4) バイトを確保する必要があります。これは、可能性のある最大長が 3 (または 4) バイトであるためです。たとえば、MySQL は CHAR(10) CHARACTER SET utf8mb4 カラムに対して 40 バイトを確保する必要があります。

10.1.11 以前の Unicode サポートから現在の Unicode サポートへのアップグレード

このセクションでは、古い MySQL リリースから MySQL 5.6 にアップグレードするときに起きる可能性のある、Unicode サポートに関する問題について説明します。また、MySQL 5.6 から古いリリースにダウングレードするためのガイドラインも示します。

ほとんどの点で MySQL 5.6 にアップグレードしても、Unicode の使用法について問題が生じることはほとんどありませんが、非互換性の可能性のあるいくつかの領域があります。主な対象領域は次のとおりです。

  • 可変長文字データ型 (VARCHAR 型と TEXT 型) の場合、文字の最大長は、utf8mb4 カラムのほうが utf8 カラムよりも短くなります。

  • すべての文字データ型 (CHAR 型、VARCHAR 型、および TEXT 型) で、インデックスを付けることができる文字の最大数は、utf8mb4 カラムのほうが utf8 カラムよりも少なくなります。

このため、utf8 から utf8mb4 にテーブルをアップグレードして補助文字サポートを利用する場合、一部のカラムまたはインデックス定義を変更する必要が生じることがあります。

テーブルは、ALTER TABLE を使用することにより、utf8 から utf8mb4 に変換できます。テーブルがもともと次のように定義されていたとします。

CREATE TABLE t1 ( col1 CHAR(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, col2 CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL
) CHARACTER SET utf8;

次のステートメントは、utf8mb4 を使用するように t1 を変換します。

ALTER TABLE t1 DEFAULT CHARACTER SET utf8mb4, MODIFY col1 CHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, MODIFY col2 CHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;

テーブルの内容については、utf8 から utf8mb4 への変換で問題は起こりません。

  • BMP 文字の場合、utf8utf8mb4 のストレージ特性は同一で、コード値、エンコーディング、長さが同じです。

  • 補助文字については、utf8 はこの文字をまったく格納できませんが、utf8mb4 は文字の格納に 4 バイトを必要とします。utf8 はこの文字をまったく格納しないので、utf8 カラムには補助文字がなく、utf8 データを古いバージョンの MySQL からアップグレードするときに、文字の変換やデータの損失について心配する必要はありません。

テーブル構造については、utf8 から utf8mb4 への変換時に、カラムまたはインデックスキーの最大長がバイトの点では変更されないという問題が生じます。そのため、文字の最大長が 3 ではなく 4 なので、文字の点ではこれはより小さくなります。CHARVARCHAR、および TEXT データ型の場合、MySQL テーブルを変換するときに、次の点に注意してください。

  • utf8 カラムのすべての定義を調べて、それらがストレージエンジンの最大長を超えていないことを確認します。

  • utf8 カラムのすべてのインデックスを調べて、それらがストレージエンジンの最大長を超えていないことを確認します。最大値は、ストレージエンジンの機能強化によって変更されることがあります。

前述の条件が当てはまる場合は、カラムまたはインデックスの定義された長さを減らすか、utf8mb4 ではなく utf8 を使用し続ける必要があります。

次に、構造的な変更が必要な例をいくつか示します。

  • TINYTEXT カラムは、最大 255 バイトを保持できるので、3 バイトの文字は 85 個まで、4 バイトの文字は 63 個まで保持できます。utf8 を使用する TINYTEXT カラムがあるが、63 個以上の文字を含められることが必要だとします。データ型も TEXT などのより長い型に変更しないかぎり、これを utf8mb4 に変換できません。

    同様に非常に長い VARCHAR カラムは、utf8 から utf8mb4 に変換する場合は、より長い TEXT 型のいずれかに変更する必要があります。

  • InnoDB には、COMPACT または REDUNDANT 行フォーマットを使用するテーブル用に 767 バイトの最大インデックス長があり、utf8 または utf8mb4 カラムの場合、それぞれ最大 255 または 191 個の文字にインデックスを付けることができます。現在、インデックスが 191 個の文字より長い utf8 カラムがある場合、インデックスを付ける文字数を減らす必要があります。

    COMPACT または REDUNDANT 行フォーマットを使用する InnoDB テーブルでは、次のカラムおよびインデックス定義が有効です。

    col1 VARCHAR(500) CHARACTER SET utf8, INDEX (col1(255))

    代わりに utf8mb4 を使用するには、インデックスをより小さくする必要があります。

    col1 VARCHAR(500) CHARACTER SET utf8mb4, INDEX (col1(191))
    注記

    COMPRESSED または DYNAMIC 行フォーマットを使用する InnoDB テーブルの場合、innodb_large_prefix オプションを有効にすると、767 バイトより長いインデックスキープリフィクス (最大 3072 バイト) を許容できます。このようなテーブルの作成には、innodb_file_format=barracuda および innodb_file_per_table=true のオプション値も必要になります。)この場合、innodb_large_prefix オプションを有効にすると、utf8 または utf8mb4 カラムに対しそれぞれ最大 1024 または 768 個の文字にインデックスを付けることができます。関連情報については、セクション14.6.7「InnoDB テーブル上の制限」を参照してください。

前述の変更のタイプは、非常に長いカラムまたはインデックスを持つ場合にのみ必要になる可能性が高くなります。それ以外の場合は、utf8 から utf8mb4 に問題なくテーブルを変換できます。これを行うには、5.6 に適切にアップグレードしたあとで、このセクションですでに述べたように ALTER TABLE を使用します。

次の項目は、非互換性の可能性のあるほかの領域についてまとめたものです。

  • 4 バイトの UTF-8 (utf8mb4) のパフォーマンスは、3 バイトの UTF-8 (utf8) のパフォーマンスより低下します。このペナルティーを望まない場合は、utf8 を引き続き使用してください。

  • SET NAMES 'utf8mb4' では、接続文字セットに対して 4 バイトの文字セットを使用する必要があります。4 バイト文字がサーバーから送信されていないかぎり、問題は起こりません。それ以外の場合は、文字ごとに最大 3 バイトの受信を要求するアプリケーションで問題が発生する可能性があります。反対に、4 バイトの文字の送信を要求するアプリケーションは、その文字がサーバーで認識されることを確認する必要があります。

  • アプリケーションは、utf16utf16le、または utf32 文字データを認識しない古いサーバーにこれらのデータを送信できません。

  • レプリケーションでは、補助文字をサポートする文字セットがマスターで使用される場合、すべてのスレーブでもこれらの文字を認識する必要があります。MySQL 5.6 マスターから古いスレーブに複製しようとしたときに、utf8 データはスレーブで utf8 と認識され、正しく複製されます。ただし、utf8mb4utf16utf16le、または utf32 データは送信できません。

    また、テーブルにマスターとスレーブについて異なる定義がある場合、予想外の結果を招くことがあるという一般的な原則に留意してください。たとえば、インデックスキー長の制限が異なると、マスターで utf8 を使用し、スレーブで utf8mb4 を使用することは危険です。

MySQL 5.6 にアップグレードしてあり、古いリリースにダウングレードすることにした場合、次の考慮事項が該当します。

  • ucs2 および utf8 データで問題が生じていない必要があります。

  • utf8mb4utf16utf16le、または utf32 文字セットを参照するすべての定義は、古いサーバーで認識されません。

  • utf8mb4 文字セットを参照するオブジェクト定義の場合、データ内に 4 バイト文字が存在しないかぎり、MySQL 5.6 で mysqldump を使用してこれらをダンプし、utf8mb4 のインスタンスを utf8 に変更するようにダンプファイルを編集し、このファイルを古いサーバーにリロードできます。古いサーバーは、ダンプファイルオブジェクト定義内の utf8 を認識し、(3 バイトの) utf8 文字セットを使用する新しいオブジェクトを作成します。

10.1.12 メタデータ用の UTF-8

メタデータデータに関するデータです。データベースについて記述しているすべてのものがメタデータであり、データベースの内容ではありません。したがって、カラム名、データベース名、ユーザー名、バージョン名、および SHOW の文字列結果のほとんどがメタデータです。INFORMATION_SCHEMA 内のテーブルは定義上、データベースオブジェクトに関する情報を含んでいるので、これは、このテーブルの内容にも当てはまります。

メタデータの表現は次の要件を満たしている必要があります。

  • すべてのメタデータで文字セットが一致している必要があります。それ以外の場合、INFORMATION_SCHEMA 内のテーブルに対する SHOW ステートメントも SELECT ステートメントも正しく機能しません。これらの演算結果の同一カラム内の各行で文字セットが異なるからです。

  • メタデータはすべての言語のすべての文字が含まれている必要があります。そうでない場合、ユーザーはそれぞれの言語を使用してカラムとテーブルに名前を付けることはできません。

両方の要件を満たすために、MySQL では、Unicode 文字セット、つまり UTF-8 でメタデータを格納します。アクセント符号付きの文字またはラテン語以外の文字を使用しなければ、混乱が生じることはありません。ただし、使用した場合は、メタデータの文字セットが UTF-8 であることを認識する必要があります。

このメタデータ要件は、USER()CURRENT_USER()SESSION_USER()SYSTEM_USER()DATABASE()、および VERSION() の関数の戻り値で、UTF-8 文字セットがデフォルトで使用されることを意味します。

サーバーは、character_set_system システム変数をメタデータ文字セットの名前に設定します。

mysql> SHOW VARIABLES LIKE 'character_set_system';+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| character_set_system | utf8 |
+----------------------+-------+

Unicode を使用してメタデータを格納しても、サーバーが、カラムのヘッダーや DESCRIBE 関数の結果を、デフォルトで character_set_system 文字セットで返すことにはなりませんSELECT column1 FROM t を使用すると、character_set_results システム変数の値 (デフォルト値は latin1) で特定される文字セットで、名前 column1 自体がサーバーからクライアントに返されます。別の文字セットでメタデータの結果をサーバーに返させる場合は、SET NAMES ステートメントを使用してサーバーに文字セット変換を強制的に実行させてください。SET NAMEScharacter_set_results および関連するほかのシステム変数を設定します。(セクション10.1.4「接続文字セットおよび照合順序」を参照してください。)また、サーバーから結果を受け取ったあとで、クライアントプログラムが変換を実行できます。クライアントが変換を実行するとより効率的ですが、このオプションは、すべてのクライアントが常に使用できるとはかぎりません。

character_set_resultsNULL に設定されている場合、変換は実行されず、サーバーはオリジナルの文字セット (character_set_system によって指定されたセット) を使用してメタデータを返します。

サーバーからクライアントに返されるエラーメッセージは、メタデータと同様に自動的にクライアントの文字セットに変換されます。

たとえば、USER() 関数を比較または割り当てのために単一のステートメント内で使用している場合、問題はありません。MySQL が自動的に変換を実行します。

SELECT * FROM t1 WHERE USER() = latin1_column;

これが機能するのは、latin1_column の内容が UTF-8 に自動的に変換されてから比較が行われるからです。

INSERT INTO t1 (latin1_column) SELECT USER();

これが機能するのは、USER() の内容が latin1 に自動的に変換されてから割り当てが行われるからです。

自動変換機能は SQL 標準には含まれていません。ただし、どの文字セットも (サポートされている文字に関して) Unicode のサブセットであることが SQL 標準のドキュメントに記載されています。スーパーセットに適用されるものはサブセットにも適用されるというよく知られた原則があるので、Unicode の照合順序は Unicode 以外の文字列との比較にも適用できると考えられます。文字列の強制力の詳細は、セクション10.1.7.5「式の照合順序」を参照してください。

10.1.13 カラム文字セットの変換

特定の文字セットを使用するようにバイナリ文字列または非バイナリ文字列カラムを変換するには、ALTER TABLE を使用します。正しく変換が行われるには、次の条件のいずれかを適用する必要があります。

  • カラムにバイナリデータ型 (BINARYVARBINARYBLOB) がある場合、含まれるすべての値は、単一の文字セット (カラムの変換後の文字セット) を使用してエンコードされる必要があります。バイナリカラムを使用して複数の文字セットで情報を格納する場合、MySQL はどの値がどの文字セットを使用するかを認識できず、データを正確に変換できません。

  • カラムに非バイナリデータ型 (CHARVARCHARTEXT) がある場合、その内容は、カラムの文字セットでエンコードする必要があり、ほかの文字セットは使用できません。内容が別の文字セットでエンコードされている場合、最初にバイナリデータ型を使用するようにカラムを変換してから、使用する文字セットで非バイナリカラムに変換できます。

VARBINARY(50) として定義された col1 という名前のテーブル t にバイナリカラムがあるとします。カラム内の情報が、単一の文字セットを使用してエンコードされているとすると、このカラムを、その文字セットを含む非バイナリカラムに変換できます。たとえば、col1greek 文字セットの文字を表すバイナリデータが含まれる場合、次のように変換できます。

ALTER TABLE t MODIFY col1 VARCHAR(50) CHARACTER SET greek;

元のカラムに BINARY(50) の型がある場合、これを CHAR(50) に変換できますが、その結果得られる値は、末尾が 0x00 バイトでパディングされ、これが望ましくない場合があります。これらのバイトを削除するには、TRIM() 関数を使用します。

UPDATE t SET col1 = TRIM(TRAILING 0x00 FROM col1);

テーブル tCHAR(50) CHARACTER SET latin1 として定義された col1 という名前の非バイナリ列があるが、utf8 を使用するようにこれを変換し、多くの言語の値を格納できるようにするとします。次のステートメントでこれを実行できます。

ALTER TABLE t MODIFY col1 CHAR(50) CHARACTER SET utf8;

両方の文字セットにない文字がカラムに含まれている場合、変換の損失が大きくなることがあります。

MySQL 4.1 より前の古いテーブルがある場合、実際にはサーバーのデフォルトの文字セットと異なる文字セットでエンコードされた値が、非バイナリカラムに含まれるという特殊な状況が起こります。たとえば、MySQL のデフォルト文字セットが latin1 であっても、アプリケーションは sjis 値をカラムに格納します。適切な文字セットを使用するために、カラムを変換することは可能ですが、追加ステップが必要になります。たとえば、サーバーのデフォルト文字セットが latin1 で、col1CHAR(50) と定義されているにもかかわらず、内容は sjis 値であるとします。最初のステップでは、バイナリデータ型にカラムを変換することで、文字変換を実行しないで既存の文字セット情報を取り除きます。

ALTER TABLE t MODIFY col1 BLOB;

次のステップでは、適切な文字セットを使用して、非バイナリデータ型にカラムを変換します。

ALTER TABLE t MODIFY col1 CHAR(50) CHARACTER SET sjis;

この手順では、MySQL 4.1 以降にアップグレードしたあと、テーブルが INSERTUPDATE などのステートメントで変更されていない必要があります。その場合、MySQL は latin1 を使用してカラムに新しい値を格納し、そのカラムは sjis 値と latin1 値を同時に含んでおり、正確に変換できません。

最初にカラムを作成するときに属性を指定した場合、ALTER TABLE を使用してテーブルを変更しているときにも属性を指定する必要があります。たとえば、NOT NULL と明示的な DEFAULT 値を指定した場合、ALTER TABLE ステートメントでも指定する必要があります。指定しない場合、結果のカラム定義にはこれらの属性が含まれません。

テーブル内のすべての文字カラムを変換するには、ALTER TABLE ... CONVERT TO CHARACTER SET charset ステートメントが役立つことがあります。セクション13.1.7「ALTER TABLE 構文」を参照してください。

10.1.14 MySQL でサポートされる文字セットと照合順序

MySQL では、30 を超える文字セットに対して 70 を超える照合順序がサポートされています。このセクションでは MySQL がどの文字セットをサポートするかを示します。関連する文字セットのグループごとに、1 つのサブセクションがあります。文字セットごとに、許容される照合順序が一覧表示されます。

SHOW CHARACTER SET ステートメント使用すると、使用可能な文字セットとそのデフォルト照合順序を常に表示できます。

mysql> SHOW CHARACTER SET;+----------+-----------------------------+---------------------+
| Charset | Description | Default collation |
+----------+-----------------------------+---------------------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci |
| dec8 | DEC West European | dec8_swedish_ci |
| cp850 | DOS West European | cp850_general_ci |
| hp8 | HP West European | hp8_english_ci |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci |
| latin1 | cp1252 West European | latin1_swedish_ci |
| latin2 | ISO 8859-2 Central European | latin2_general_ci |
| swe7 | 7bit Swedish | swe7_swedish_ci |
| ascii | US ASCII | ascii_general_ci |
| ujis | EUC-JP Japanese | ujis_japanese_ci |
| sjis | Shift-JIS Japanese | sjis_japanese_ci |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci |
| tis620 | TIS620 Thai | tis620_thai_ci |
| euckr | EUC-KR Korean | euckr_korean_ci |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci |
| greek | ISO 8859-7 Greek | greek_general_ci |
| cp1250 | Windows Central European | cp1250_general_ci |
| gbk | GBK Simplified Chinese | gbk_chinese_ci |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci |
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci |
| utf8 | UTF-8 Unicode | utf8_general_ci |
| ucs2 | UCS-2 Unicode | ucs2_general_ci |
| cp866 | DOS Russian | cp866_general_ci |
| keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci |
| macce | Mac Central European | macce_general_ci |
| macroman | Mac West European | macroman_general_ci |
| cp852 | DOS Central European | cp852_general_ci |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci |
| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci |
| cp1251 | Windows Cyrillic | cp1251_general_ci |
| utf16 | UTF-16 Unicode | utf16_general_ci |
| utf16le | UTF-16LE Unicode | utf16le_general_ci |
| cp1256 | Windows Arabic | cp1256_general_ci |
| cp1257 | Windows Baltic | cp1257_general_ci |
| utf32 | UTF-32 Unicode | utf32_general_ci |
| binary | Binary pseudo charset | binary |
| geostd8 | GEOSTD8 Georgian | geostd8_general_ci |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci |
+----------+-----------------------------+---------------------+

文字セットに複数の照合順序が存在する場合、どの照合順序が所定のアプリケーションにもっとも適しているかが明確でないことがあります。正しくない照合順序を選択しないようにするには、代表的なデータ値で比較を行い、特定の照合順序で期待どおりに値がソートされることを確認すると役立ちます。

10.1.14.1 Unicode 文字セット

MySQL 5.6 は、次の Unicode 文字セットをサポートします。

  • ucs2。文字ごとに 16 ビットを使用する Unicode 文字セットの UCS-2 エンコーディング。

  • utf16。Unicode 文字セットの UTF-16 エンコーディング。ucs2 に似ていますが、補助文字用の拡張機能があります。

  • utf16le。Unicode 文字セットの UTF-16LE エンコーディング。utf16 と似ていますが、ビッグエンディアンではなくリトルエンディアンです。

  • utf32。文字ごとに 32 ビットを使用した Unicode 文字セットの UTF-32 エンコーディング。

  • utf8。文字ごとに 1 から 3 バイトを使用する Unicode 文字セットの UTF-8 エンコーディング。

  • utf8mb4。文字ごとに 1 から 4 バイトを使用した Unicode 文字セットの UTF-8 エンコーディング。

ucs2 および utf8 は、Basic Multilingual Plane (BMP) 文字をサポートします。utf8mb4utf16utf16le、および utf32 は BMP と補助文字をサポートします。utf16le は MySQL 5.6.1 で追加されました。

これらの文字セットを使用すると、約 650 の言語でテキストを格納できます。このセクションでは、Unicode 文字セットごとに利用可能な照合順序を示し、それらを区別するプロパティーについて説明します。文字セットの一般的な情報については、セクション10.1.10「Unicode のサポート」を参照してください。

類似した一連の照合順序を、ほとんどの Unicode 文字セットで使用できます。これらは次のリストに表示されます。ここで xxx は文字セット名を表します。たとえば、xxx_danish_ci はデンマーク語の照合順序を表し、具体的には ucs2_danish_ciutf16_danish_ciutf32_danish_ciutf8_danish_ci、および utf8mb4_danish_ci の名前を構成します。

utf16le に対する照合順序のサポートはさらに限定されます。使用可能な唯一の照合順序は、utf16le_general_ciutf16le_bin です。これらは、utf16_general_ciutf16_bin に似ています。

このセクションで後述するように、Unicode 照合順序名には、照合順序が基づいている Unicode 照合順序アルゴリズムのバージョンを示すバージョン番号も含まれる場合があります (たとえば xxx_unicode_520_ci)。このような照合順序の場合、対応する utf8 照合順序の utf8mb3 エイリアスはありません。セクション10.1.10.6「utf8mb3 文字セット (utf8 のエイリアス)」を参照してください。

  • xxx_bin

  • xxx_croatian_ci

  • xxx_czech_ci

  • xxx_danish_ci

  • xxx_esperanto_ci

  • xxx_estonian_ci

  • xxx_general_ci (デフォルト)

  • xxx_german2_ci

  • xxx_general_mysql500_ci

  • xxx_hungarian_ci

  • xxx_icelandic_ci

  • xxx_latvian_ci

  • xxx_lithuanian_ci

  • xxx_persian_ci

  • xxx_polish_ci

  • xxx_roman_ci

  • xxx_romanian_ci

  • xxx_sinhala_ci

  • xxx_slovak_ci

  • xxx_slovenian_ci

  • xxx_spanish_ci

  • xxx_spanish2_ci

  • xxx_swedish_ci

  • xxx_turkish_ci

  • xxx_unicode_ci

  • xxx_vietnamese_ci

MySQL は、http://www.unicode.org/reports/tr10/ で説明している Unicode 照合順序アルゴリズム (UCA) に従って xxx_unicode_ci 照合順序を実装します。照合順序は、バージョン 4.0.0 UCA 重みキー (http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt) を使用します。現在、xxx_unicode_ci 照合順序は、Unicode 照合順序アルゴリズムを一部だけサポートします。中にはまだサポートされていない文字もあります。また、結合マークは完全にはサポートされていません。これは主に、ベトナム語、ヨルバ語、ナバホ語などの一部のより小さな言語に影響します。組み合わされた文字は、文字列比較では、単一の Unicode 文字で書き込まれた同じ文字とは異なると見なされ、2 つの文字は長さが異なると考えられます (たとえば、CHAR_LENGTH() 関数で返されたものや、結果セットのメタデータにおけるもの)。

xxx_unicode_ci での順序付けが各言語で適切に機能しない場合にのみ、MySQL は言語固有の Unicode 照合順序を実装します。言語固有の照合順序は UCA ベースです。これらは、追加の言語の調整ルールを使用して、xxx_unicode_ci から派生されます。

4.0.0 以降の UCA バージョンに基づく照合順序では、照合順序名の中にバージョンが含まれます。したがって、xxx_unicode_520_ci 照合順序は、UCA 5.2.0 重みキー (http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt) に基づきます。

LOWER() および UPPER() は、その引数の照合順序に従って、大文字と小文字の変換を実行します。4.0.0 より新しい Unicode バージョンでのみ大文字バージョンと小文字バージョンがある文字は、新しい UCA バージョンを使用する照合順序が引数にある場合にのみ、これらの機能によって変換されます。

Unicode 文字セットの場合、xxx_general_ci 照合順序を使用して実行する演算は、xxx_unicode_ci 照合順序のものよりも高速です。たとえば、utf8_general_ci 照合順序の比較は、utf8_unicode_ci の比較よりも高速ですが、精度は少し低くなります。この理由は、utf8_unicode_ci では、ある文字がほかの文字の組み合わせに等しいものと見なされる拡張形式などのマッピングをサポートしているためです。たとえば、ドイツ語とほかのいくつかの言語では、ßssと同じです。utf8_unicode_ci は、短縮形式と無視可能な文字もサポートします。utf8_general_ci は、拡張形式、短縮形式、無視可能な文字をサポートしない従来の照合順序です。文字間で 1 対 1 の比較しかできません。

さらに説明するために、次の等式は utf8_general_ciutf8_unicode_ci の両方で構成されています (比較または検索を行うときのこの効果については、セクション10.1.7.8「照合順序の効果の例」を参照してください)。

Ä = A
Ö = O
Ü = U

照合順序間の違いは、次の式が utf8_general_ci に当てはまるという点です。

ß = s

一方、次の式は、ドイツ語 DIN-1 順序 (辞書順序とも呼ばれます) をサポートする utf8_unicode_ci に当てはまります。

ß = ss

MySQL が utf8 文字セットに対する言語固有の照合順序を実行するのは、utf8_unicode_ci による順序付けが言語に対してうまく機能しないときだけです。たとえば、utf8_unicode_ci は、ドイツ語辞書順序とフランス語には適切に機能するので、特殊な utf8 照合順序を作成する必要はありません。

utf8_general_ci も、ドイツ語とフランス語の両方にとって十分ですが、ßsに等しく、ssに等しくない点が異なります。これがアプリケーションで許容可能な場合は、utf8_general_ci のほうが高速なので、こちらを使用する必要があります。これが許容できない場合 (たとえば、ドイツ語辞書順序が必要な場合) は、utf8_unicode_ci のほうがより正確なので、こちらを使用してください。

ドイツ語 DIN-2 (電話帳) 順序が必要な場合は、utf8_german2_ci 照合順序を使用してください。これは次の文字セットを等しいものと見なします。

Ä = Æ = AE
Ö = Œ = OE
Ü = UE
ß = ss

utf8_german2_ci は、latin1_german2_ci に似ていますが、後者は、ÆAEに、またはŒOEに等しいものとは見なしません。utf8_general_ci で十分であるので、ドイツ語辞書順序のための latin1_german_ci に対応する utf8_german_ci はありません。

xxx_swedish_ci には、スウェーデン語のルールが含まれます。たとえば、スウェーデン語には、ドイツ語やフランス語を使用するユーザーでは予期しないような次の関係があります。

Ü = Y < Ö

xxx_spanish_ci および xxx_spanish2_ci 照合順序は、それぞれ現代のスペイン語と伝統的なスペイン語に対応しています。どちらの照合順序でも、ñ (n チルダ) は、noの間の独立した文字です。さらに、伝統的なスペイン語の場合、chは、cdの間の独立した文字であり、llは、lmの間の独立した文字です。

xxx_spanish2_ci 照合順序は、アストゥリアス語およびガリーシア語にも使用できます。

xxx_danich_ci 照合順序は、ノルウェー語にも使用できます。

xxx_roman_ci 照合順序では、IJ は等しいと見なされ、UV は等しいと見なされます。

xxx_croatian_ci 照合順序は、ČĆĐLjNjŠŽ のクロアチア語の文字を調整します。

バイナリ (xxx_bin) 照合順序を除くすべての Unicode 照合順序に対し、MySQL は文字の照合重みを探すようにテーブルルックアップを実行します。この重みは、WEIGHT_STRING() 関数を使用して表示できます。(セクション12.5「文字列関数」を参照してください。)文字がテーブル内にない場合 (たとえば、新しい文字であるため)、照合重み判定がより複雑になります。

  • 一般的な照合順序 (xxx_general_ci) での BMP 文字の場合、重み = コードポイント。

  • UCA 照合順序 (たとえば、xxx_unicode_ci と言語固有の照合順序) での BMP 文字の場合、次のアルゴリズムが適用されます。

    if (code >= 0x3400 && code <= 0x4DB5) base= 0xFB80;
    else if (code >= 0x4E00 && code <= 0x9FA5) base= 0xFB40;
    else base= 0xFBC0;
    aaaa= base + (code >> 15);
    bbbb= (code & 0x7FFF) | 0x8000;

    結果は、aaaabbbb が続いた 2 つの照合要素のシーケンスになります。例:

    mysql> SELECT HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci));+----------------------------------------------------------+
    | HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci)) |
    +----------------------------------------------------------+
    | FBC084CF |
    +----------------------------------------------------------+

    したがって、U+04cf CYRILLIC SMALL LETTER PALOCHKA は、すべての UCA 4.0.0 照合順序で、U+04c0 CYRILLIC LETTER PALOCHKA より大きくなります。UCA 5.2.0 照合順序では、すべての palochka は一緒にソートされます。

  • 一般的な照合順序の補助文字の場合、重みは 0xfffd REPLACEMENT CHARACTER の重みです。UCA 4.0.0 照合順序の補助文字の場合、照合重みは 0xfffd です。つまり、MySQL では、すべての補助文字は互いに等しく、ほとんどすべての BMP 文字より大きくなります。

    デザレット文字と COUNT(DISTINCT) を使用した例:

    CREATE TABLE t (s1 VARCHAR(5) CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    INSERT INTO t VALUES (0xfffd);
    INSERT INTO t VALUES (0x010412);
    INSERT INTO t VALUES (0x010413);
    SELECT COUNT(DISTINCT s1) FROM t;

    結果は 2 です。これは、MySQL xxx_unicode_ci 照合順序で、置換文字は 0x0dc6 の重みを持ちますが、デザレット B とデザレット T はどちらも、0xfffd の重みを持つからです。(utf32_general_ci 照合順序が代わりに使用された場合、この照合順序ではすべての 3 文字が 0xfffd の重みを持つので、結果は 1 になります。)

    くさび形文字と WEIGHT_STRING() を使用した例:

    CREATE TABLE t (s1 CHAR(4) CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    INSERT INTO t VALUES (0x000000410001218f000121a700000042);
    SELECT HEX(WEIGHT_STRING(s1)) FROM t;

    結果は次のようになります。

    0E33 FFFD FFFD 0E4A

    0E330E4A は、UCA 4.0.0 の主要な重みです。FFFD は KAB の重みであり、KISH の重みでもあります。

    すべての補助文字が互いに同じであるというルールは、最適ではありませんが、問題を引き起こすとは考えられません。これらの文字は非常に珍しく、マルチ文字文字列全体が補助文字から構成されることは非常にまれです。日本では、補助文字はあいまいな漢字表意文字であるので、一般的なユーザーは、いずれにしてもそれらの順序を気にしません。実際には、MySQL のルールに従って行をソートし、二次的にコードポイント値でソートする場合、次のようにすることが簡単です。

    ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin
  • 4.0.0 以降の UCA バージョンに基づいた補助文字の場合 (たとえば、xxx_unicode_520_ci)、必ずしもすべての補助文字が同じ照合順序重みを持つとはかぎりません。一部には、UCA allkeys.txt ファイルからの明示的な重みがあります。それ以外には、このアルゴリズムから計算された重みがあります。

    aaaa= base + (code >> 15);
    bbbb= (code & 0x7FFF) | 0x8000;

utf16_bin 照合順序

文字のコード値による順序付け文字のバイナリ表現による順序付けと間には違いがあります。これは、サロゲートのために、utf16_bin でのみ表示される違いです。

utf16_bin (utf16 のバイナリ照合順序) が、文字ごとではなくバイトごとのバイナリ比較であったとします。その場合は、utf16_bin での文字の順序は utf8_bin での順序とは異なります。たとえば、次の表には 2 つの珍しい文字が示されています。最初の文字は E000-FFFF の範囲にあるので、サロゲートより大きくなりますが、補助文字より小さくなります。2 番目の文字は補助文字です。

Code point Character utf8 utf16
---------- --------- ---- -----
0FF9D HALFWIDTH KATAKANA LETTER N EF BE 9D FF 9D
10384 UGARITIC LETTER DELTA F0 90 8E 84 D8 00 DF 84

表の 2 つの文字は、0xff9d < 0x10384 であるので、コードポイント値による順序になります。また、0xef < 0xf0 なので、utf8 値による順序になります。ただし、0xff > 0xd8 なので、バイトごとの比較を使用する場合は、utf16 値による順序にはなりません。

したがって、MySQL の utf16_bin 照合順序はバイトごとにはなりません。コードポイントによる順序になります。MySQL は、utf16 での補助文字エンコーディングを認識すると、文字のコードポイント値に変換してから比較します。したがって、utf8_binutf16_bin の順序付けは同じになります。これは、UCS_BASIC 照合順序の SQL:2008 標準の要件に一致します。UCS_BASIC は、ソートされている文字列の文字の Unicode スカラー値によって、順序付け全体が決定される照合順序です。これは UCS 文字レパートリーに適用できます。すべての文字レパートリーは、UCS レパートリーのサブセットなので、UCS_BASIC 照合順序は、すべての文字セットに適用できる可能性があります。ノート 11: 文字の Unicode スカラー値は、符号なしの整数として扱われるそのコードポイントです。

文字セットが ucs2 である場合、比較はバイトごとになりますが、いずれにしても、ucs2 文字列にはサロゲートを含めないでください。

MySQL 5.6.5 で xxx_general_mysql500_ci 照合順序が追加されました。これらは、元の xxx_general_ci 照合順序の 5.1.24 以前の順序付けを維持し、MySQL 5.1.24 より前に作成されたテーブルのアップグレードを許可します。詳細は、セクション2.11.3「テーブルまたはインデックスの再構築が必要かどうかのチェック」およびセクション2.11.4「テーブルまたはインデックスの再作成または修復」を参照してください。

10.1.14.2 西ヨーロッパの文字セット

西ヨーロッパの文字セットには、大部分の西ヨーロッパ言語 (フランス語、スペイン語、カタロニア語、バスク語、ポルトガル語、イタリア語、アルバニア語、オランダ語、ドイツ語、デンマーク語、スウェーデン語、ノルウェー語、フィンランド語、フェロー語、アイスランド語、アイルランド語、スコットランド語、英語など) が含まれます。

  • ascii (US ASCII) 照合順序:

    • ascii_bin

    • ascii_general_ci (デフォルト)

  • cp850 (DOS 西ヨーロッパ言語) 照合順序:

    • cp850_bin

    • cp850_general_ci (デフォルト)

  • dec8 (DEC 西ヨーロッパ言語) 照合順序:

    • dec8_bin

    • dec8_swedish_ci (デフォルト)

  • hp8 (HP 西ヨーロッパ言語) 照合順序:

    • hp8_bin

    • hp8_english_ci (デフォルト)

  • latin1 (cp1252 西ヨーロッパ言語) 照合順序:

    • latin1_bin

    • latin1_danish_ci

    • latin1_general_ci

    • latin1_general_cs

    • latin1_german1_ci

    • latin1_german2_ci

    • latin1_spanish_ci

    • latin1_swedish_ci (デフォルト)

    latin1 はデフォルト文字セットです。MySQL の latin1 は Windows cp1252 文字セットと同じです。つまり、これは公式の ISO 8859-1 または IANA (Internet Assigned Numbers Authority) latin1 と同じですが、IANA latin1 が、0x800x9f の間のコードポイントを未定義として扱うのに対し、cp1252、および MySQL の latin1 はこれらの位置の文字を割り当てる点が異なることを示します。たとえば 0x80 はユーロの記号です。cp1252定義されていないエントリでは、MySQL は 0x81 を Unicode 0x0081 に、0x8d0x008d に、0x8f0x008f に、0x900x0090 に、0x9d0x009d に変換します。

    latin1_swedish_ci 照合順序は、大部分の MySQL カスタマが使用しているデフォルトです。スウェーデン語/フィンランド語の照合順序ルールに基づいているとされていますが、スウェーデン人やフィンランド人の中にはこの意見に賛同しないユーザーもいます。

    latin1_german1_cilatin1_german2_ci 照合順序は DIN-1 および DIN-2 標準に基づきます。ここで、DIN は Deutsches Institut für Normung (ANSI のドイツ版) を表しています。DIN-1 は辞書の照合順序と呼ばれ、DIN-2 は電話帳の照合順序と呼ばれています。比較、または検索を行うときのこの効果の例については、セクション10.1.7.8「照合順序の効果の例」を参照してください。

    • latin1_german1_ci (辞書) ルール:

      Ä = A
      Ö = O
      Ü = U
      ß = s
    • latin1_german2_ci (電話帳) ルール:

      Ä = AE
      Ö = OE
      Ü = UE
      ß = ss

    latin1_spanish_ci 照合順序では、ñ (n チルダ) は、noの間の独立した文字です。

  • macroman (Mac 西ヨーロッパ言語) 照合順序:

    • macroman_bin

    • macroman_general_ci (デフォルト)

  • swe7 (7 ビットスウェーデン語) 照合順序:

    • swe7_bin

    • swe7_swedish_ci (デフォルト)

10.1.14.3 中央ヨーロッパの文字セット

MySQL ではチェコ、スロバキア、ハンガリー、ルーマニア、スロベニア、クロアチア、ポーランド、セルビア (ラテン) で使用される文字セットも一部サポートされています。

  • cp1250 (Windows 中央ヨーロッパ言語) 照合順序:

    • cp1250_bin

    • cp1250_croatian_ci

    • cp1250_czech_cs

    • cp1250_general_ci (デフォルト)

    • cp1250_polish_ci

  • cp852 (DOS 中央ヨーロッパ言語) 照合順序:

    • cp852_bin

    • cp852_general_ci (デフォルト)

  • keybcs2 (DOS Kamenicky Czech-Slovak) 照合順序:

    • keybcs2_bin

    • keybcs2_general_ci (デフォルト)

  • latin2 (ISO 8859-2 中央ヨーロッパ言語) 照合順序:

    • latin2_bin

    • latin2_croatian_ci

    • latin2_czech_cs

    • latin2_general_ci (デフォルト)

    • latin2_hungarian_ci

  • macce (Mac 中央ヨーロッパ言語) 照合順序:

    • macce_bin

    • macce_general_ci (デフォルト)

10.1.14.4 南ヨーロッパおよび中東の文字セット

MySQL では南ヨーロッパや中東、アルメニア語、アラビア語、グルジア語、ギリシャ語、ヘブライ語、トルコ語の文字セットがサポートされています。

  • armscii8 (ARMSCII-8 アルメニア語) 照合順序:

    • armscii8_bin

    • armscii8_general_ci (デフォルト)

  • cp1256 (Windows アラビア語) 照合順序:

    • cp1256_bin

    • cp1256_general_ci (デフォルト)

  • geostd8 (GEOSTD8 グルジア語) 照合順序:

    • geostd8_bin

    • geostd8_general_ci (デフォルト)

  • greek (ISO 8859-7 ギリシャ語) 照合順序:

    • greek_bin

    • greek_general_ci (デフォルト)

  • hebrew (ISO 8859-8 ヘブライ語) 照合順序:

    • hebrew_bin

    • hebrew_general_ci (デフォルト)

  • latin5 (ISO 8859-9 トルコ語) 照合順序:

    • latin5_bin

    • latin5_turkish_ci (デフォルト)

10.1.14.5 バルト語の文字セット

バルト語に含まれる文字セットにはエストニア語、ラトビア語、リトアニア言語が含まれます。

  • cp1257 (Windows バルト語) 照合順序:

    • cp1257_bin

    • cp1257_general_ci (デフォルト)

    • cp1257_lithuanian_ci

  • latin7 (ISO 8859-13 バルト語) 照合順序:

    • latin7_bin

    • latin7_estonian_cs

    • latin7_general_ci (デフォルト)

    • latin7_general_cs

10.1.14.6 キリル文字の文字セット

ベラルーシ語、ブルガリア語、ロシア語、ウクライナ語、セルビア語 (キリル) とともに使用するキリル文字の文字セットおよび照合順序を以下に示します。

  • cp1251 (Windows キリル文字) 照合順序:

    • cp1251_bin

    • cp1251_bulgarian_ci

    • cp1251_general_ci (デフォルト)

    • cp1251_general_cs

    • cp1251_ukrainian_ci

  • cp866 (DOS ロシア語) 照合順序:

    • cp866_bin

    • cp866_general_ci (デフォルト)

  • koi8r (KOI8-R Relcom Russian) 照合順序:

    • koi8r_bin

    • koi8r_general_ci (デフォルト)

  • koi8u (KOI8-U ウクライナ語) 照合順序:

    • koi8u_bin

    • koi8u_general_ci (デフォルト)

10.1.14.7 アジアの文字セット

サポートされているアジアの文字セットには、中国語、日本語、韓国語、タイ語が含まれています。これらは複雑な場合があります。たとえば、中国語の文字セットは数千種類の文字に対応している必要があります。cp932 および sjis 文字セットの追加情報については、セクション10.1.14.7.1「cp932 文字セット」を参照してください。

MySQL でのアジアの文字セットのサポートに関連したよくある質問および問題に対する回答については、セクションA.11「MySQL 5.6 FAQ: MySQL の中国語、日本語、および韓国語の文字セット」を参照してください。

  • big5 (Big5 繁体字中国語) 照合順序:

    • big5_bin

    • big5_chinese_ci (デフォルト)

  • cp932 (SJIS for Windows 日本語) 照合順序:

    • cp932_bin

    • cp932_japanese_ci (デフォルト)

  • eucjpms (UJIS for Windows 日本語) 照合順序:

    • eucjpms_bin

    • eucjpms_japanese_ci (デフォルト)

  • euckr (EUC-KR 韓国語) 照合順序:

    • euckr_bin

    • euckr_korean_ci (デフォルト)

  • gb2312 (GB2312 簡体字中国語) 照合順序:

    • gb2312_bin

    • gb2312_chinese_ci (デフォルト)

  • gbk (GBK 簡体字中国語) 照合順序:

    • gbk_bin

    • gbk_chinese_ci (デフォルト)

  • sjis (Shift-JIS 日本語) 照合順序:

    • sjis_bin

    • sjis_japanese_ci (デフォルト)

  • tis620 (TIS620 タイ語) 照合順序:

    • tis620_bin

    • tis620_thai_ci (デフォルト)

  • ujis (EUC-JP 日本語) 照合順序:

    • ujis_bin

    • ujis_japanese_ci (デフォルト)

big5_chinese_ci 照合順序は画数でソートします。

10.1.14.7.1 cp932 文字セット

cp932 が必要な理由

MySQL では sjis 文字セットは IANA で定義される Shift_JIS 文字セットに対応しており、これらは JIS X0201 および JIS X0208 文字セットをサポートしています。(http://www.iana.org/assignments/character-sets を参照してください。)

ただし、記述用語としてのSHIFT JISの意味は非常にあいまいになっており、さまざまなベンダーが定義した Shift_JIS に対する拡張も含める場合もあります。

たとえば、日本語 Windows 環境で使用されるSHIFT JISは、Microsoft による Shift_JIS の拡張であり、正式な名称は Microsoft Windows Codepage : 932 または cp932 です。Shift_JIS でサポートされる文字に加え、cp932 では、NEC 特殊文字、NEC 選定 IBM 拡張文字、IBM 選定文字などの拡張文字をサポートします。

多くの日本語ユーザーは、これらの拡張文字を使用するときに問題に直面してきました。これらの問題は次の要因によって生じていました。

  • MySQL が自動的に文字セットの変換を行なっていること。

  • 文字セットが Unicode (ucs2) を使用して変換されていること。

  • sjis 文字セットが、これらの拡張文字の変換をサポートしていないこと。

  • いわゆるSHIFT JISから Unicode への変換には複数の変換ルールが存在し、文字によっては、変換ルールに従って別々に Unicode に変換される場合があること。MySQL ではこれらの変換ルールのうち、1 つしかサポートしていません (詳細は後述します)。

MySQL の cp932 文字セットは、これらの問題を解決するように設計されています。

MySQL が文字セットの変換をサポートするので、異なる変換ルールを持つ IANA の Shift_JIScp932 を 2 つの異なる文字セットに区分することが重要になります。

cp932sjis との相違点

cp932 文字セットは次の点で sjis と異なります。

一部の文字については、ucs2 との間の変換は、sjiscp932 との場合と異なります。次の表に、これらの違いを示します。

ucs2 への変換:

sjis/cp932sjis -> ucs2 の変換cp932 -> ucs2 の変換
5C005C005C
7E007E007E
815C20152015
815F005CFF3C
8160301CFF5E
816120162225
817C2212FF0D
819100A2FFE0
819200A3FFE1
81CA00ACFFE2

ucs2 からの変換:

ucs2ucs2 -> sjis の変換ucs2 -> cp932 の変換
005C815F5C
007E7E7E
00A281913F
00A381923F
00AC81CA3F
2015815C815C
201681613F
2212817C3F
22253F8161
301C81603F
FF0D3F817C
FF3C3F815F
FF5E3F8160
FFE03F8191
FFE13F8192
FFE23F81CA

日本語文字セットのユーザーは、--character-set-client-handshake (または --skip-character-set-client-handshake) を使用すると大きな効果が得られることに注意してください。セクション5.1.3「サーバーコマンドオプション」を参照してください。

10.2 エラーメッセージ言語の設定

デフォルトで、mysqld はエラーメッセージを英語で生成しますが、チョコ語、デンマーク語、オランダ語、エストニア語、フランス語、ドイツ語、ギリシャ語、ハンガリー語、イタリア語、日本語、韓国語、ノルウェー語、ノルウェー語 (ニーノシュク)、ポーランド語、ポルトガル語、ルーマニア語、ロシア語、スロバキア語、スペイン語、スウェーデン語のほかの言語でも表示できます。

このセクションの説明を使用して、サーバーでエラーメッセージに使用する言語を選択できます。

MySQL 5.6 では、サーバーは、次の 2 つの場所でエラーメッセージファイルを検索します。

  • lc_messages_dirlc_messages (後者は言語名に変換されます) の 2 つのシステム変数値から構築されたディレクトリでファイルを検索しようとします。次のコマンドを使用してサーバーを起動するとします。

    shell> mysqld --lc_messages_dir=/usr/share/mysql --lc_messages=fr_FR

    この場合、mysqld は、ロケール fr_FR を言語 french にマップし、/usr/share/mysql/french ディレクトリでエラーファイルを検索します。

  • 前述のように構築されたディレクトリでメッセージファイルが見つからない場合、サーバーは、lc_messages 値を無視し、検索する場所として lc_messages_dir 値だけを使用します。

lc_messages_dir システム変数は、グローバル値だけを含み、読み取り専用です。lc_messages は、グローバル値とセッション値を含み実行時に変更できるので、サーバーの実行中にエラーメッセージ言語を変更でき、個々のクライアントはそれぞれ、そのセッション lc_messages 値を別のロケール名に変更することによって、異なるエラーメッセージ言語を使用できます。たとえば、サーバーがエラーメッセージに fr_FR ロケールを使用している場合、クライアントは、次のステートメントを実行すると、英語でエラーメッセージを受信できます。

mysql> SET lc_messages = 'en_US';

デフォルトでは、言語ファイルは、MySQL ベースディレクトリ下の share/mysql/LANGUAGE ディレクトリにあります。

エラーメッセージの (言語ではなく) 文字セットの変更の詳細は、セクション10.1.6「エラーメッセージの文字セット」を参照してください。

MySQL Internals: Error Messages」で入手できる MySQL Internals マニュアルの手順を使用すると、サーバーで生成されるエラーメッセージの内容を変更できます。エラーメッセージの内容を変更する場合は、MySQL のより新しいバージョンにアップグレードするごとに必ず変更を繰り返してください。

10.3 文字セットの追加

このセクションでは、MySQL に文字セットを追加する手順について説明します。適切な手順は、文字セットが単純か複雑かによって異なります。

  • ソートに特別な文字列照合ルーチンを必要とせず、マルチバイト文字のサポートを必要としない文字セットが、単純な文字セットです。

  • これらのどちらかの機能が必要な文字セットが、複雑な文字セットです。

たとえば、greekswe7 は単純な文字セットですが、big5czech は複雑な文字セットです。

次の手順を使用するには、MySQL ソース配布が必要です。この手順では、MYSET は追加する文字セットの名前を表します。

  1. MYSET<charset> 要素を sql/share/charsets/Index.xml ファイルに追加します。ファイル内既存の内容を、新しい内容を追加するためのガイドとして使用します。latin1<charset> 要素のリストの一部を以下に示します。

    <charset name="latin1"> <family>Western</family> <description>cp1252 West European</description> ... <collation name="latin1_swedish_ci" id="8" order="Finnish, Swedish"> <flag>primary</flag> <flag>compiled</flag> </collation> <collation name="latin1_danish_ci" id="15" order="Danish"/> ... <collation name="latin1_bin" id="47" order="Binary"> <flag>binary</flag> <flag>compiled</flag> </collation> ...
    </charset>

    <charset> 要素は、文字セットのすべての照合順序を一覧表示します。これらには少なくも、バイナリ照合順序とデフォルト (プライマリ) 照合順序が含まれます。デフォルト照合順序は多くの場合、general_ci (一般、大文字と小文字を区別) のサフィクスを使用して名前が付けられます。バイナリ照合順序をデフォルト照合順序にすることは可能ですが、通常、これらは異なります。デフォルト照合順序には primary フラグを付ける必要があります。バイナリ照合順序には binary フラグを付ける必要があります。

    それぞれの照合順序に一意の ID 番号を割り当てる必要があります。1024 から 2047 の ID 範囲は、ユーザー定義の照合順序に予約されています。現在使用されている照合順序 ID の最大値を検索するには、次のクエリーを使用します。

    SELECT MAX(ID) FROM INFORMATION_SCHEMA.COLLATIONS;
  2. このステップは、追加しているのが単純な文字セットか、複雑な文字セットかにより異なります。単純な文字セットには、構成ファイルだけが必要ですが、複雑な文字セットには、照合順序関数またはマルチバイト関数あるいはその両方を定義する C ソースファイルが必要です。

    単純な文字セットの場合、文字セットプロパティーについて記した構成ファイル (MYSET.xml) を作成します。sql/share/charsets ディレクトリにこのファイルを作成します。このファイルの土台として latin1.xml のコピーを使用できます。ファイルの構文は非常に単純です。

    • コメントは、通常の XML コメント (<!-- text -->) として記述されます。

    • <map> 配列要素内の単語は、任意の数の空白によって区切られます。

    • <map> 配列要素内の各単語は、16 進形式の数値で表す必要があります。

    • <ctype> 要素の <map> 配列要素には 257 語が含まれます。そのあとのほかの <map> 配列要素には 256 語が含まれます。セクション10.3.1「文字定義配列」を参照してください。

    • Index.xml 内の文字セットに対して <charset> 要素に一覧表示された照合順序ごとに、文字の順序を定義する <collation> 要素を MYSET.xml に含める必要があります。

    複雑な文字セットの場合、文字セットプロパティーについて記述し、文字セットに対する演算を適切に実行するために必要なサポートルーチンを定義した C ソースファイルを作成します。

  3. 構成情報を変更します。MYSYS の情報を追加するためのガイドとして、既存の構成情報を使用します。ここでの例では、文字セットにデフォルト照合順序とバイナリ照合順序があることを想定していますが、MYSET に追加の照合順序がある場合には、さらに多くの行が必要になります。

    1. mysys/charset-def.c を編集し、新しい文字セットの照合順序を登録します。

      宣言セクションに次の行を追加します。

      #ifdef HAVE_CHARSET_MYSETextern CHARSET_INFO my_charset_MYSET_general_ci;
      extern CHARSET_INFO my_charset_MYSET_bin;
      #endif

      登録セクションに次の行を追加します。

      #ifdef HAVE_CHARSET_MYSET add_compiled_collation(&my_charset_MYSET_general_ci); add_compiled_collation(&my_charset_MYSET_bin);
      #endif
    2. 文字セットが ctype-MYSET.c を使用する場合、strings/CMakeLists.txt を編集して、ctype-MYSET.cSTRINGS_SOURCES 変数の定義に追加します。

    3. cmake/character_sets.cmake を編集します。

      1. アルファベット順で CHARSETS_AVAILABLE の値に MYSET を追加します。

      2. アルファベット順で CHARSETS_COMPLEX の値に MYSET を追加します。これは単純な文字セットにも必要です。ない場合は、CMake-DDEFAULT_CHARSET=MYSET を認識しません。

  4. 再構成し、再コンパイルし、テストします。

10.3.1 文字定義配列

それぞれの単純な文字セットには、sql/share/charsets ディレクトリに置かれた構成ファイルがあります。MYSYS という名前の文字セットの場合、ファイルには MYSET.xml の名前が付けられます。これは、<map> 配列要素を使用して、文字セットプロパティーを一覧表示します。<map> 要素は、これらの要素内に表示されます。

  • <ctype> は文字ごとに属性を定義します。

  • <lower><upper> は、小文字と大文字を一覧表示します。

  • <unicode> は、8 ビット文字値を Unicode 値にマップします。

  • <collation> 要素は、比較とソートでの文字の順序を、照合順序ごとに 1 つの要素で示します。文字コード自体が順序を提供するので、バイナリ照合順序には <map> 要素は不要です。

strings ディレクトリ内の ctype-MYSET.c ファイルに実装された複雑な文字セットには、ctype_MYSET[]to_lower_MYSET[] などの対応する配列があります。すべての複雑な文字セットがすべての配列を持つわけではありません。例については、既存の ctype-*.c ファイルも参照してください。追加情報については、strings ディレクトリ内の CHARSET_INFO.txt ファイルを参照してください。

ほとんどの配列には、文字値でインデックスが付けられ、256 個の要素があります。<ctype> 配列には、文字値 + 1 でインデックスが付けられ、257 個の要素があります。これは、EOF を処理するための従来の規則です。

<ctype> 配列要素は、ビット値です。各要素は、文字セット内の単一の文字の属性について記述します。各属性は、include/m_ctype.h での定義に従って、ビットマスクに関連付けられます。

#define _MY_U 01
#define _MY_L 02
#define _MY_NMR 04
#define _MY_SPC 010
#define _MY_PNT 020
#define _MY_CTR 040
#define _MY_B 0100
#define _MY_X 0200 

所定の文字の <ctype> 値は、その文字について記述した適用可能なビットマスク値の結合である必要があります。たとえば、'A' は 16 進数 (_MY_X) と同様に大文字 (_MY_U) であるので、その ctype 値は次のように定義する必要があります。

ctype['A'+1] = _MY_U | _MY_X = 01 | 0200 = 0201

m_ctype.h のビットマスク値は 8 進数値ですが、MYSET.xml 内の <ctype> 配列の要素は 16 進値として書き込む必要があります。

<lower><upper> 配列は、文字セットの各メンバーに対応した小文字と大文字を保持します。例:

lower['A'] should contain 'a'
upper['a'] should contain 'A'

<collation> 配列は、比較およびソートでどのように文字を順序付けする必要があるかを示します。MySQL は、この情報の値に基づいて文字をソートします。場合によっては、これは <upper> 配列と同じであり、ソートで大文字と小文字が区別されないことになります。さらに複雑なソートルールについては (複雑な文字セットの場合)、セクション10.3.2「複雑な文字セットの文字列照合のサポート」での文字列照合の説明を参照してください。

10.3.2 複雑な文字セットの文字列照合のサポート

MYSET という名前の単純な文字セットの場合、ソートルールは、<collation> 要素内の <map> 配列要素を使用して、MYSET.xml 構成ファイルで指定されます。言語に関するソートルールが非常に複雑で、単純な配列では扱えない場合、strings ディレクトリ内の ctype-MYSET.c ソースファイルで文字列照合関数を定義する必要があります。

既存の文字セットからは、これらの関数がどのように実装されているかを示す最適なドキュメントおよび例が得られます。big5czechgbksjistis160 文字セットのファイルなど、strings ディレクトリ内の ctype-*.c ファイルを調べます。MY_COLLATION_HANDLER 構造を見て、どのように使用されているかを確認します。追加情報については、strings ディレクトリ内の CHARSET_INFO.txt ファイルも参照してください。

10.3.3 複雑な文字セットのマルチバイト文字のサポート

マルチバイト文字を含む MYSET という名前の新しい文字セットのサポートを追加する場合、strings ディレクトリ内の ctype-MYSET.c ソースファイルのマルチバイト文字関数を使用する必要があります。

既存の文字セットからは、これらの関数がどのように実装されているかを示す最適なドキュメントおよび例が得られます。euc_krgb2312gbksjisujis 文字セットのファイルなど、strings ディレクトリ内の ctype-*.c ファイルを調べます。MY_CHARSET_HANDLER 構造を見て、どのように使用されているかを確認します。追加情報については、strings ディレクトリ内の CHARSET_INFO.txt ファイルも参照してください。

10.4 文字セットへの照合順序の追加

照合順序は、文字列を比較およびソートする方法を定義した一連のルールです。MySQL でのそれぞれの照合順序は、単一の文字セットに属しています。すべての文字セットには少なくとも 1 つの照合順序が属し、ほとんどの文字セットのは 2 つ以上の照合順序が属しています。

照合順序は重みに基づいて文字を順序付けします。文字セット内のそれぞれの文字が重みにマップされています。重みが等しい文字は同等と見なされ、重みが等しくない文字は、その重みの相対的な大きさに従って比較されます。

WEIGHT_STRING() 関数を使用すると、文字列内の文字の重みを確認できます。重みを示した返される値はバイナリ文字列であるので、HEX(WEIGHT_STRING(str)) を使用して重みを出力可能な形式で表示すると便利です。次の例は、大文字と小文字を区別しない非バイナリ文字列である場合は、'AaBb' 内の大文字と小文字で重みは異ならないが、バイナリ文字列である場合は異なることを示します。

mysql> SELECT HEX(WEIGHT_STRING('AaBb' COLLATE latin1_swedish_ci));+------------------------------------------------------+
| HEX(WEIGHT_STRING('AaBb' COLLATE latin1_swedish_ci)) |
+------------------------------------------------------+
| 41414242 |
+------------------------------------------------------+
mysql> SELECT HEX(WEIGHT_STRING(BINARY 'AaBb'));+-----------------------------------+
| HEX(WEIGHT_STRING(BINARY 'AaBb')) |
+-----------------------------------+
| 41614262 |
+-----------------------------------+

セクション10.4.1「照合順序の実装タイプ」で説明するように、MySQL では複数の照合順序の実装をサポートしています。これらの中には、再コンパイルせずに、MySQL に追加できるものもあります。

  • 8 ビットの文字セットの単純な照合順序。

  • Unicode 文字セットの UCA ベースの照合順序。

  • バイナリ (xxx_bin) 照合順序。

以降のセクションでは、最初の 2 種類の照合順序を既存の文字セットに追加する方法について説明します。バイナリ照合順序については、既存の文字セットにもすでに用意されているので、ここでは追加方法は説明しません。

新しい照合順序を追加する手順のサマリー:

  1. 照合順序 ID を選択します。

  2. 照合順序に名前を付ける構成情報を追加し、文字順序付けルールについて記述します。

  3. サーバーを再起動します。

  4. 照合順序が存在していることを検証します。

ここでの説明では、MySQL を再コンパイルすることなく追加できる照合順序だけを取り上げます。再コンパイルを必要とする照合順序 (C ソースファイル内の関数を利用して実装されたものなど) を追加するには、セクション10.3「文字セットの追加」の手順を使用してください。ただし、完全な文字セットに必要なすべての情報を追加するのではなく、既存の文字セットに合わせて適切なファイルを変更します。つまり、文字セットの現在の照合順序ですでに存在するものに基づいて、新しい照合順序のデータ構造、関数、構成情報を追加します。

注記

既存の照合順序を変更すると、その照合順序を使用するカラムでインデックスの行順序に影響が及ぶことがあります。この場合、間違ったクエリー結果などの問題が起こらないように、これらのインデックスを再構築してください。詳細は、セクション2.11.3「テーブルまたはインデックスの再構築が必要かどうかのチェック」を参照してください。

追加のリソース

10.4.1 照合順序の実装タイプ

MySQL は複数のタイプの照合順序を実装します。

8 ビットの文字セットに対する単純な照合順序

この種の照合順序は、文字コードと重みの 1 対 1 のマッピングを定義した 256 個の重みの配列を使用して実装されます。latin1_swedish_ci がその一例です。これは、大文字と小文字を区別しない照合順序なので、大文字と小文字は同じ重みで、等しいものと見なされます。

mysql> SET NAMES 'latin1' COLLATE 'latin1_swedish_ci';Query OK, 0 rows affected (0.01 sec)
mysql> SELECT HEX(WEIGHT_STRING('a')), HEX(WEIGHT_STRING('A'));+-------------------------+-------------------------+
| HEX(WEIGHT_STRING('a')) | HEX(WEIGHT_STRING('A')) |
+-------------------------+-------------------------+
| 41 | 41 |
+-------------------------+-------------------------+
1 row in set (0.01 sec)
mysql> SELECT 'a' = 'A';+-----------+
| 'a' = 'A' |
+-----------+
| 1 |
+-----------+
1 row in set (0.12 sec)

実装の手順については、セクション10.4.3「8 ビットの文字セットへの単純な照合順序の追加」を参照してください。

8 ビット文字セットに対する複雑な照合順序

この種の照合順序は、セクション10.3「文字セットの追加」で説明しているように、文字を順序付けする方法を定義した C ソースファイル内の関数を使用して実装されます。

Unicode 以外のマルチバイト文字セットの照合順序

この種の照合順序では、8 ビット (シングルバイト) 文字とマルチバイト文字が異なる方法で処理されます。8 ビットの文字の場合、文字コードは大文字と小文字を区別しない形式で重みにマップされます。(たとえば、シングルバイト文字 'a''A' はどちらも重みが 0x41 です。)マルチバイト文字の場合、文字コードと重みの間には、2 種類の関係があります。

  • 重みが文字コードと等しい場合。sjis_japanese_ci がこの種の照合順序の一例です。マルチバイト文字 'ぢ' の文字コードは 0x82C0 であり、重みも 0x82C0 です。

    mysql> CREATE TABLE t1 -> (c1 VARCHAR(2) CHARACTER SET sjis COLLATE sjis_japanese_ci);Query OK, 0 rows affected (0.01 sec)
    mysql> INSERT INTO t1 VALUES ('a'),('A'),(0x82C0);Query OK, 3 rows affected (0.00 sec)
    Records: 3 Duplicates: 0 Warnings: 0
    mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;+------+---------+------------------------+
    | c1 | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
    +------+---------+------------------------+
    | a | 61 | 41 |
    | A | 41 | 41 |
    | ぢ | 82C0 | 82C0 |
    +------+---------+------------------------+
    3 rows in set (0.00 sec)
  • 文字コードが 1 対 1 で重みにマップされていても、必ずしもコードと重みが等しくない場合。gbk_chinese_ci がこの種の照合順序の一例です。マルチバイト文字 '膰' の文字コードは 0x81B0 ですが、重みは 0xC286 です。

    mysql> CREATE TABLE t1 -> (c1 VARCHAR(2) CHARACTER SET gbk COLLATE gbk_chinese_ci);Query OK, 0 rows affected (0.33 sec)
    mysql> INSERT INTO t1 VALUES ('a'),('A'),(0x81B0);Query OK, 3 rows affected (0.00 sec)
    Records: 3 Duplicates: 0 Warnings: 0
    mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;+------+---------+------------------------+
    | c1 | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
    +------+---------+------------------------+
    | a | 61 | 41 |
    | A | 41 | 41 |
    | 膰 | 81B0 | C286 |
    +------+---------+------------------------+
    3 rows in set (0.00 sec)

実装の手順については、セクション10.3「文字セットの追加」を参照してください。

Unicode マルチバイト文字セットの照合順序

これらの照合順序の一部は Unicode 照合順序アルゴリズム (UCA) に基づきますが、それ以外は基づいていません。

UCA に基づいていない照合順序では、文字コードと重みは 1 対 1 でマップしています。MySQL では、このような照合順序は大文字と小文字を区別せず、アクセント、濁音、破裂音を区別しません。utf8_general_ci がその一例です。'a''A''À'、および 'á' のそれぞれは文字コードは別々ですが、重みはすべて 0x0041 であり、等しいものと見なされます。

mysql> SET NAMES 'utf8' COLLATE 'utf8_general_ci';Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t1 -> (c1 CHAR(1) CHARACTER SET UTF8 COLLATE utf8_general_ci);Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t1 VALUES ('a'),('A'),('À'),('á');Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;+------+---------+------------------------+
| c1 | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
+------+---------+------------------------+
| a | 61 | 0041 |
| A | 41 | 0041 |
| À | C380 | 0041 |
| á | C3A1 | 0041 |
+------+---------+------------------------+
4 rows in set (0.00 sec)

MySQL の UCA ベースの照合順序には、次の 3 つのプロパティーがあります。

  • 文字に重みがある場合、それぞれの重みは 2 バイト (16 ビット) を使用します。

  • 文字の重みはゼロ (または空の重み) の場合があります。この場合、文字は無視できます。例:「U+0000 NULL」は重みがなく、無視できます。

  • 1 つの文字が 1 つの重みを持つ場合があります。例: 'a' には 0x0E33 の重みがあります。

    mysql> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';Query OK, 0 rows affected (0.05 sec)
    mysql> SELECT HEX('a'), HEX(WEIGHT_STRING('a'));+----------+-------------------------+
    | HEX('a') | HEX(WEIGHT_STRING('a')) |
    +----------+-------------------------+
    | 61 | 0E33 |
    +----------+-------------------------+
    1 row in set (0.02 sec)
  • 1 つの文字が複数の重みを持つ場合があります。これは拡張形式です。例: ドイツ語の文字 'ß' (SZ リガチャーまたは SHARP S) には、0x0FEA0FEA の重みがあります。

    mysql> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';Query OK, 0 rows affected (0.11 sec)
    mysql> SELECT HEX('ß'), HEX(WEIGHT_STRING('ß'));+-----------+--------------------------+
    | HEX('ß') | HEX(WEIGHT_STRING('ß')) |
    +-----------+--------------------------+
    | C39F | 0FEA0FEA |
    +-----------+--------------------------+
    1 row in set (0.00 sec)
  • 複数の文字が 1 つの重みを持つ場合があります。これは短縮形式です。例: 'ch' は、チェコ語の単一の文字であり、0x0EE2 の重みを持ちます。

    mysql> SET NAMES 'utf8' COLLATE 'utf8_czech_ci';Query OK, 0 rows affected (0.09 sec)
    mysql> SELECT HEX('ch'), HEX(WEIGHT_STRING('ch'));+-----------+--------------------------+
    | HEX('ch') | HEX(WEIGHT_STRING('ch')) |
    +-----------+--------------------------+
    | 6368 | 0EE2 |
    +-----------+--------------------------+
    1 row in set (0.00 sec)

複数の文字と複数の重みのマッピングも可能です (これは拡張形式を使用した短縮形式です) が、MySQL ではサポートされていません。

UCA に基づいていない照合順序に関する実装の手順については、セクション10.3「文字セットの追加」を参照してください。UCA 照合順序については、セクション10.4.4「Unicode 文字セットへの UCA 照合順序の追加」を参照してください。

その他の照合順序

上記のカテゴリのどれにも該当しない照合順序も少数存在します。

10.4.2 照合順序 ID の選択

各照合順序には一意の ID が必要です。照合順序を追加するには、現在使用されていない ID 値を選択する必要があります。1024 から 2047 の ID 範囲は、ユーザー定義の照合順序に予約されています。MySQL 5.6.3 以降、InnoDB テーブルは 2 バイトの照合順序 ID をサポートしています。MySQL 5.6.3 より前では、InnoDB テーブルは、255 を最大値とするシングルバイトの照合順序 ID だけをサポートしていました。MyISAM テーブルでは、MySQL 5.5 以降の 2 バイトの照合順序 ID をサポートしています。

選択した照合順序は次のコンテキストで表示されます。

  • INFORMATION_SCHEMA.COLLATIONS テーブルの ID カラム。

  • SHOW COLLATION 出力の Id カラム。

  • MYSQL_FIELD C API データ構造の charsetnr メンバー。

  • mysql_get_character_set_info() C API 関数で返される MY_CHARSET_INFO データ構造の number メンバー。

現在使用されている最大の ID を判別するには、次のステートメントを発行します。

mysql> SELECT MAX(ID) FROM INFORMATION_SCHEMA.COLLATIONS;+---------+
| MAX(ID) |
+---------+
| 210 |
+---------+

現在使用されているすべての ID のリストを表示するには、次のステートメントを発行します。

mysql> SELECT ID FROM INFORMATION_SCHEMA.COLLATIONS ORDER BY ID;+-----+
| ID |
+-----+
| 1 |
| 2 |
| ... |
| 52 |
| 53 |
| 57 |
| 58 |
| ... |
| 98 |
| 99 |
| 128 |
| 129 |
| ... |
| 210 |
+-----+
警告

MySQL 5.5 より前では、ユーザー定義の照合順序 ID の範囲が用意されており、1 から 254 の範囲で ID を選択する必要があります。この場合、MySQL をアップグレードすると、選択した照合順序 ID が新しい MySQL 配布に含められた照合順序に割り当てられていることがわかります。この場合、自身の照合順序には新しい値を選択する必要があります。

さらに、アップグレードする前に、変更する構成ファイルを保存する必要があります。適切にアップグレードすると、そのプロセスによって変更したファイルが置き換えられます。

10.4.3 8 ビットの文字セットへの単純な照合順序の追加

このセクションでは、MySQL Index.xml ファイル内の <charset> 文字セットの記述に関連付けられた <collation> 要素を書き込むことによって、8 ビット文字セットの単純な照合順序を追加する方法について説明します。ここで説明した手順では、MySQL の再コンパイルは不要です。この例では、latin1_test_ci という名前の照合順序を latin1 文字セットに追加します。

  1. セクション10.4.2「照合順序 ID の選択」で示したように、照合順序 ID を選択します。次のステップでは、1024 の ID を使用します。

  2. Index.xml および latin1.xml 構成ファイルを変更します。これらのファイルは、character_sets_dir システム変数によって名前の付けられたディレクトリに置かれます。使用しているシステムではパス名が異なることがありますが、次のようにして変数値を確認できます。

    mysql> SHOW VARIABLES LIKE 'character_sets_dir';+--------------------+-----------------------------------------+
    | Variable_name | Value |
    +--------------------+-----------------------------------------+
    | character_sets_dir | /user/local/mysql/share/mysql/charsets/ |
    +--------------------+-----------------------------------------+
  3. 照合順序の名前を選択して、Index.xml ファイルに表示します。照合順序を追加する文字セットの <charset> 要素を探し、照合順序名および ID を指定する <collation> 要素を追加して、名前を ID に関連付けます。例:

    <charset name="latin1"> ... <collation name="latin1_test_ci" id="1024"/> ...
    </charset>
  4. latin1.xml 構成ファイルで、照合順序に名前を付ける <collation> 要素と、0 から 255 の文字コードの文字コードと重みのマッピングテーブルを定義する <map> 要素を追加します。<map> 要素内のそれぞれの値は、16 進形式の数値にする必要があります。

    <collation name="latin1_test_ci">
    <map> 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49 44 4E 4F 4F 4F 4F 5C D7 5C 55 55 55 59 59 DE DF 41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49 44 4E 4F 4F 4F 4F 5C F7 5C 55 55 55 59 59 DE FF
    </map>
    </collation>
  5. サーバーを再起動し、このステートメントを使用して、照合順序の有無を検証します。

    mysql> SHOW COLLATION LIKE 'latin1_test_ci';+----------------+---------+------+---------+----------+---------+
    | Collation | Charset | Id | Default | Compiled | Sortlen |
    +----------------+---------+------+---------+----------+---------+
    | latin1_test_ci | latin1 | 1024 | | | 1 |
    +----------------+---------+------+---------+----------+---------+

10.4.4 Unicode 文字セットへの UCA 照合順序の追加

このセクションでは、MySQL Index.xml ファイルで <charset> 文字セットの記述内に <collation> 要素を書き込むことによって、Unicode 文字セットの UCA 照合順序を追加する方法について説明します。ここで説明した手順では、MySQL の再コンパイルは不要です。これは、http://www.unicode.org/reports/tr35/ で入手できる Locale Data Markup Language (LDML) 仕様のサブセットを使用します。この方法を使用すれば、照合順序全体を定義する必要はありません。代わりに、既存の基本照合順序から始め、基本照合順序とどのように異なるかという点で新しい照合順序について記述します。次の表は、UCA 照合順序を定義できる Unicode 文字セットの基本照合順序を一覧表示しています。utf16le のユーザー定義 UCA 照合順序は作成できません。このような照合順序のベースとして役立つ utf16le_unicode_ci 照合順序はありません。

表 10.1 ユーザー定義の UCA 照合順序に使用可能な MySQL 文字セット

文字セット基本照合順序
utf8utf8_unicode_ci
ucs2ucs2_unicode_ci
utf16utf16_unicode_ci
utf32utf32_unicode_ci

以降のセクションでは、LDML 構文を使用して定義された照合順序を追加する方法について説明し、MySQL でサポートされている LDML ルールのサマリーを示します。

10.4.4.1 LDML 構文を使用した UCA 照合順序の定義

MySQL を再コンパイルせずに Unicode 文字セットの UCA 照合順序を追加するには、次の手順を使用します。照合順序のソート特性の記述に使用する LDML ルールを把握していない場合は、セクション10.4.4.2「MySQL でサポートされる LDML 構文」を参照してください。

この例では、utf8_phone_ci という名前の照合順序を utf8 文字セットを追加します。この照合順序は、ユーザーが名前と電話番号を投稿する Web アプリケーションに関連したシナリオ用に設計されています。電話番号は、次のようなさまざまな形式で指定できます。

+7-12345-67
+7-12-345-67
+7 12 345 67
+7 (12) 345 67
+71234567

このような値を扱うときに生じる問題は、さまざまな形式が許容されることで、特定の電話番号の検索が非常に困難になるということです。この解決方法として、句読点文字を並べ替えて無視できるようにする新しい照合順序を定義します。

  1. セクション10.4.2「照合順序 ID の選択」で示したように、照合順序 ID を選択します。次のステップでは、1029 の ID を使用します。

  2. Index.xml 構成ファイルを変更します。このファイルは、character_sets_dir システム変数によって名前の付けられたディレクトリに置かれます。使用しているシステムではパス名が異なることがありますが、次のようにして変数値を確認できます。

    mysql> SHOW VARIABLES LIKE 'character_sets_dir';+--------------------+-----------------------------------------+
    | Variable_name | Value |
    +--------------------+-----------------------------------------+
    | character_sets_dir | /user/local/mysql/share/mysql/charsets/ |
    +--------------------+-----------------------------------------+
  3. 照合順序の名前を選択して、Index.xml ファイルに表示します。さらに、照合順序の順序付けルールを提供する必要があります。照合順序を追加する文字セットの <charset> 要素を探し、照合順序名および ID を指定する <collation> 要素を追加して、名前を ID に関連付けます。<collation> 要素内で、順序付けルールを含む <rules> 要素を提供します。

    <charset name="utf8"> ... <collation name="utf8_phone_ci" id="1029"> <rules> <reset>\u0000</reset> <i>\u0020</i> <!-- space --> <i>\u0028</i> <!-- left parenthesis --> <i>\u0029</i> <!-- right parenthesis --> <i>\u002B</i> <!-- plus --> <i>\u002D</i> <!-- hyphen --> </rules> </collation> ...
    </charset>
  4. その他の Unicode 文字セットに同様の照合順序が必要な場合は、ほかの <collation> 要素を追加します。たとえば、ucs2_phone_ci を定義するには、<collation> 要素を <charset name="ucs2"> 要素に追加します。それぞれの照合順序には一意の独自 ID が必要になります。

  5. サーバーを再起動し、このステートメントを使用して、照合順序の有無を検証します。

    mysql> SHOW COLLATION LIKE 'utf8_phone_ci';+---------------+---------+------+---------+----------+---------+
    | Collation | Charset | Id | Default | Compiled | Sortlen |
    +---------------+---------+------+---------+----------+---------+
    | utf8_phone_ci | utf8 | 1029 | | | 8 |
    +---------------+---------+------+---------+----------+---------+

次に、照合順序をテストして、目的のプロパティーがあることを確認します。

新しい照合順序を使用して、いくつかのサンプルの電話番号を含むテーブルを作成します。

mysql> CREATE TABLE phonebook ( ->  name VARCHAR(64), ->  phone VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_phone_ci -> );Query OK, 0 rows affected (0.09 sec)
mysql> INSERT INTO phonebook VALUES ('Svoj','+7 912 800 80 02');Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO phonebook VALUES ('Hf','+7 (912) 800 80 04');Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO phonebook VALUES ('Bar','+7-912-800-80-01');Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO phonebook VALUES ('Ramil','(7912) 800 80 03');Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO phonebook VALUES ('Sanja','+380 (912) 8008005');Query OK, 1 row affected (0.00 sec)

いくつかのクエリーを実行して、無視された句読点文字が実際にソートおよび比較で無視されているかどうかを確認します。

mysql> SELECT * FROM phonebook ORDER BY phone;+-------+--------------------+
| name | phone |
+-------+--------------------+
| Sanja | +380 (912) 8008005 |
| Bar | +7-912-800-80-01 |
| Svoj | +7 912 800 80 02 |
| Ramil | (7912) 800 80 03 |
| Hf | +7 (912) 800 80 04 |
+-------+--------------------+
5 rows in set (0.00 sec)
mysql> SELECT * FROM phonebook WHERE phone='+7(912)800-80-01';+------+------------------+
| name | phone |
+------+------------------+
| Bar | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM phonebook WHERE phone='79128008001';+------+------------------+
| name | phone |
+------+------------------+
| Bar | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM phonebook WHERE phone='7 9 1 2 8 0 0 8 0 0 1';+------+------------------+
| name | phone |
+------+------------------+
| Bar | +7-912-800-80-01 |
+------+------------------+
1 row in set (0.00 sec)

10.4.4.2 MySQL でサポートされる LDML 構文

このセクションでは、MySQL が認識する LDML 構文について説明します。これは、http://www.unicode.org/reports/tr35/ で入手できる LDML 仕様で説明されている構文のサブセットであり、詳細についてはこの仕様を参照してください。MySQL は、サイズの大きい構文のサブセットを認識するので、多くの場合、Unicode 共通ロケールデータリポジトリから照合順序定義をダウンロードして、該当する部分 (<rules> タグと </rules> タグの間の部分) を MySQL Index.xml ファイルに貼り付けることが可能です。ここで説明するルールは、文字のソートがプライマリレベルのみで行われることを除いて、すべてサポートされます。セカンダリ以上のソートレベルでの差を指定するルールは認識されますが (たとえば、照合順序の定義に含めることができます)、プライマリレベルでは等式として扱われます。

MySQL Server は、Index.xml ファイルの構文解析中に問題を検出すると、診断を生成します。セクション10.4.4.3「Index.xml の構文解析中の診断」を参照してください。

文字表現

LDML ルールで名前が付けられた文字は、文字どおりに、または \unnnn 形式で書き込めます。ただし、nnnn は 16 進 Unicode コードポイント値です。たとえば、Aá は、文字どおりに、または \u0041 および \u00E1 として書き込めます。16 進値内で、A から F の桁は、大文字と小文字を区別しません。\u00E1\u00e1 は同等になります。UCA 4.0.0 照合順序の場合、16 進表記は、Basic Multilingual Plane の文字にのみ使用でき、0000 から FFFF の BMP 範囲外の文字には使用できません。UCA 5.2.0 照合順序の場合、16 進表記をすべての文字に使用できます。

Index.xml ファイル自体は、UTF-8 エンコーディングを使用して書き込む必要があります。

構文ルール

LDML には、文字の順序付けを指定するリセットルールとシフトルールがあります。順序付けは、アンカーポイントを確立するリセットルールから開始し、そのアンカーポイントを基準として文字をソートする方法を示すシフトルールが続く一連のルールとして指定されます。

  • <reset> ルールはそれ自体ではどの順序付けも指定しません。その代わりにこれは、所定の文字に関連して後続のシフトルールを実行できるように、順序付けをリセットします。次のどちらのルールも、文字 'A' に関連して実行されるように後続のシフトルールをリセットします。

    <reset>A</reset>
    <reset>\u0041</reset>
  • <p><s>、および <t> のシフトルールは、文字と文字とのプライマリ、セカンダリ、およびターシャリの差を定義します。

    • プライマリの差を使用して、個々の文字を区別します。

    • セカンダリの差を使用して、アクセントバリエーションを区別します。

    • ターシャリの差を使用して、大文字と小文字のバリエーションを区別します。

    次のどちらのルールも、'G' 文字のプライマリシフトルールを指定します。

    <p>G</p>
    <p>\u0047</p>
  • <i> シフトルールは、ある文字が別の文字とまったく同じようにソートするよう指定します。次のルールは、'b''a' と同じようにソートします。

    <reset>a</reset>
    <i>b</i>
  • 略記されたシフト構文は、タグの単一のペアを使用して、複数のシフトルールを指定します。次の表は、略記された構文ルールと同等の略記されていないルールとの対応を示します。

    表 10.2 略記されたシフト構文

    略記された構文略記されていない構文
    <pc>xyz</pc><p>x</p><p>y</p><p>z</p>
    <sc>xyz</sc><s>x</s><s>y</s><s>z</s>
    <tc>xyz</tc><t>x</t><t>y</t><t>z</t>
    <ic>xyz</ic><i>x</i><i>y</i><i>z</i>

  • 拡張形式は、複数文字のシーケンスのアンカーポイントを確立するリセットルールです。MySQL は 2 から 6 文字長の拡張形式をサポートしています。次のルールは、プライマリレベルで 'z' を 3 文字のシーケンス 'abc' よりも大きくします。

    <reset>abc</reset>
    <p>z</p>
  • 短縮形式は、複数文字のシーケンスをソートするシフトルールです。MySQL は、2 から 6 文字長の短縮形式をサポートしています。次のルールは、プライマリレベルで 3 文字のシーケンス 'xyz''a' よりも大きくします。

    <reset>a</reset>
    <p>xyz</p>
  • 長い拡張形式と長い短縮形式を一緒に使用できます。次のルールは、プライマリレベルで 3 文字のシーケンス 'xyz' を 3 文字のシーケンス 'abc' よりも大きくします。

    <reset>abc</reset>
    <p>xyz</p>
  • 通常の拡張形式の構文では、<x><extend> 要素を使用して、拡張形式を指定します。次のルールは、セカンダリレベルで文字 'k' をシーケンス 'ch' よりも大きくします。つまり、'k' は、'c''h' が続いたあとの文字に拡張したかのように動作します。

    <reset>c</reset>
    <x><s>k</s><extend>h</extend></x>

    この構文は長いシーケンスを許可します。次のルールは、ターシャリレベルでシーケンス 'ccs' をシーケンス 'cscs' よりも大きくします。

    <reset>cs</reset>
    <x><t>ccs</t><extend>cs</extend></x>

    LDML 仕様では、通常の拡張形式構文を慎重を要するものと記述しています。詳細についてはその仕様を参照してください。

  • 前コンテキスト構文は、<x> および <context> 要素を使用して、文字の前のコンテキストによってソートが変更されるよう指定します。次のルールは、セカンダリレベルで '-''a' よりも大きくしますが、これは '-' の前に 'b' があったときだけです。

    <reset>a</reset>
    <x><context>b</context><s>-</s></x>
  • 前コンテキスト構文には、<extend> 要素を含めることができます。次のルールは、プライマリレベルで 'def''aghi' よりも大きくしますが、これは 'def' の前に 'abc' があったときだけです。

    <reset>a</reset>
    <x><context>abc</context><p>def</p><extend>ghi</extend></x>
  • リセットルールでは before 属性が許可されています。通常、リセットルールのあとのシフトルールは、リセット文字のあとにソートする文字を指定します。before 属性を伴うリセットルール後のシフトルールは、リセット文字の前にソートする文字を指定します。次のルールは、プライマリレベルで文字 'b''a' の直前に配置します。

    <reset before="primary">a</reset>
    <p>b</p>

    許容されている before 属性値は、名前または同等な数値でソートレベルを指定します。

    <reset before="primary">
    <reset before="1">
    <reset before="secondary">
    <reset before="2">
    <reset before="tertiary">
    <reset before="3">
  • リセットルールでは、リテラル文字ではなく、論理リセット位置に名前を付けることができます。

    <first_tertiary_ignorable/>
    <last_tertiary_ignorable/>
    <first_secondary_ignorable/>
    <last_secondary_ignorable/>
    <first_primary_ignorable/>
    <last_primary_ignorable/>
    <first_variable/>
    <last_variable/>
    <first_non_ignorable/>
    <last_non_ignorable/>
    <first_trailing/>
    <last_trailing/>

    次のルールは、プライマリレベルで 'z' を、Default Unicode Collation Element Table (DUCET) エントリを伴い、CJK ではない無視できない文字よりも大きくします。

    <reset><last_non_ignorable/></reset>
    <p>z</p>

    論理位置には、次の表に示すコードポイントが設定されています。

    表 10.3 論理リセット位置のコードポイント

    論理位置Unicode 4.0.0 コードポイントUnicode 5.2.0 コードポイント
    <first_non_ignorable/>U+02D0U+02D0
    <last_non_ignorable/>U+A48CU+1342E
    <first_primary_ignorable/>U+0332U+0332
    <last_primary_ignorable/>U+20EAU+101FD
    <first_secondary_ignorable/>U+0000U+0000
    <last_secondary_ignorable/>U+FE73U+FE73
    <first_tertiary_ignorable/>U+0000U+0000
    <last_tertiary_ignorable/>U+FE73U+FE73
    <first_trailing/>U+0000U+0000
    <last_trailing/>U+0000U+0000
    <first_variable/>U+0009U+0009
    <last_variable/>U+2183U+1D371

  • <collation> 要素は、シフトルールの文字重み計算に影響する shift-after-method 属性を許可します。この属性には、次の値が許可されています。

    • simple: before 属性を持たないリセットルールで、文字の重みを計算します。これは、属性が指定されない場合のデフォルトです。

    • expand: リセットルールのあとのシフトに拡張形式を使用します。

    '0''1'0E290E2A の重みを持ち、すべての基本ラテン文字を '0' から '1' の間に設定するとします。

    <reset>0</reset>
    <pc>abcdefghijklmnopqrstuvwxyz</pc>

    単純なシフトモードの場合、重みは次のように計算されます。

    'a' has weight 0E29+1
    'b' has weight 0E29+2
    'c' has weight 0E29+3
    ...

    ただし、'0' から '1' の間には 26 個の文字を設定するのに十分な未使用の位置がありません。数字と文字が混在する結果になります。

    これを解決するには shift-after-method="expand" を使用します。この場合、重みは次のように計算されます。

    'a' has weight [0E29][233D+1]
    'b' has weight [0E29][233D+2]
    'c' has weight [0E29][233D+3]
    ...

    233D は、文字 0xA48C の UCA 4.0.0 重みです。これは、最後の無視できない文字 (CJK を除き、照合順序で一種のもっとも大きな文字) です。UCA 5.2.0 も同様ですが、文字 0x1342E3ACA を使用します。

MySQL 固有の LDML 拡張機能

MySQL 5.6 では、LDML ルールの拡張機能によって、<collation> 要素は、照合順序が基づく UCA バージョンを示す version オプション属性を、<collation> タグに含めることができます。version 属性を省略すると、そのデフォルト値は 4.0.0 になります。たとえば、次の指定は、UCA 5.2.0 に基づいている照合順序を示します。

<collation id="nnn" name="utf8_xxx_ci" version="5.2.0">
...
</collation>

10.4.4.3 Index.xml の構文解析中の診断

MySQL Server は、Index.xml ファイルの構文解析中に問題が見つかったときに、診断を生成します。

  • 不明なタグはエラーログに書き込まれます。たとえば、照合順序定義に <aaa> タグが含まれる場合、次のメッセージが表示されます。

    [Warning] Buffered warning: Unknown LDML tag:
    'charsets/charset/collation/rules/aaa'
  • 照合順序の初期化が可能でない場合、サーバーは不明な照合順序エラーをレポートし、前の例のように問題点を説明した警告も生成します。それ以外の場合、照合順序の説明が全体的に正しいが、いくつかの不明なタグが含まれているときに、照合順序が初期化され、使用できます。不明な部分は無視されますが、警告がエラーログに生成されます。

  • 照合順序の問題によって、クライアントが SHOW WARNINGS で表示できる警告が生成されます。6 文字のサポートされる最大長より長い拡張形式が、リセットルールに含まれているとします。

    <reset>abcdefghi</reset>
    <i>x</i>

    この照合順序を使用しようとすると、次の警告が生成されます。

    mysql> SELECT _utf8'test' COLLATE utf8_test_ci;ERROR 1273 (HY000): Unknown collation: 'utf8_test_ci'
    mysql> SHOW WARNINGS;+---------+------+----------------------------------------+
    | Level | Code | Message |
    +---------+------+----------------------------------------+
    | Error | 1273 | Unknown collation: 'utf8_test_ci' |
    | Warning | 1273 | Expansion is too long at 'abcdefghi=x' |
    +---------+------+----------------------------------------+

10.5 文字セットの構成

デフォルトのサーバー文字セットおよび照合順序は、サーバー起動時に、--character-set-server オプションと --collation-server オプションで変更できます。照合順序は、デフォルト文字セットの正当な照合順序である必要があります。(各文字列セットに使用できる照合順序を特定するには、SHOW COLLATION ステートメントを使用します。)セクション5.1.3「サーバーコマンドオプション」を参照してください。

バイナリにコンパイルされない文字セットを使用しようとすると、次の問題が生じることがあります。

  • 文字セットが格納される場所 (通常、MySQL インストールディレクトリ下の share/mysql/charsets または share/charsets ディレクトリ) を判断するときに、プログラムが不正なパスを使用します。これは、該当プログラムを実行するときに --character-sets-dir オプションを使用することによって修正できます。たとえば、MySQL クライアントプログラムで使用されるディレクトリを指定するには、オプションファイルの [client] グループに記述します。ここに挙げる例は、それぞれ Unix または Windows の場合に設定がどのようになるかを示します。

    [client]
    character-sets-dir=/usr/local/mysql/share/mysql/charsets
    [client]
    character-sets-dir="C:/Program Files/MySQL/MySQL Server 5.6/share/charsets"
  • 文字セットは、動的にロードできない複雑な文字セットです。この場合、文字セットのサポートを使用してプログラムを再コンパイルする必要があります。

    Unicode 文字セットの場合、LDML 表記を使用することによって、再コンパイルせずに照合順序を定義できます。セクション10.4.4「Unicode 文字セットへの UCA 照合順序の追加」を参照してください。

  • 文字セットは動的な文字セットですが、その構成ファイルがありません。この場合、新しい MySQL 配布から文字セットの構成ファイルをインストールする必要があります。

  • 文字セットインデックスファイルに文字セットの名前が含まれていない場合、プログラムはエラーメッセージを表示します。このファイルの名前は Index.xml で、メッセージは次のとおりです。

    Character set 'charset_name' is not a compiled character set and is not
    specified in the '/usr/share/mysql/charsets/Index.xml' file

    この問題を解決するには、新しいインデックスファイルを取得するか、欠落している文字セットの名前を手動で現在のファイルに追加する必要があります。

次のようにしてクライアントプログラムに強制的に特定の文字セットを使用させることができます。

[client]
default-character-set=charset_name

これは通常は不要です。ただし、character_set_systemcharacter_set_server または character_set_client と異なり、(データベースオブジェクト識別子またはカラム値、あるいはその両方として) 手動で文字を入力した場合、これらの文字はクライアントからの出力に間違って表示されたり、出力自体が間違って書式設定されたりすることがあります。このような場合、--default-character-set=system_character_set を使用して MySQL クライアントを起動し、システム文字セットに一致するようにクライアント文字セットを設定すると、問題が修正されます。

MyISAM テーブルでは、myisamchk -dvv tbl_name を使用するとテーブルの文字セットの名前および数値を確認できます。

10.6 MySQL Server でのタイムゾーンのサポート

MySQL Server は複数のタイムゾーン設定を保持しています。

  • システムタイムゾーン。サーバーは、起動するときに、ホストマシンのタイムゾーンを特定し、これを使用して system_time_zone システム変数で設定しようとします。その後、この値は変更しません。

    mysqld_safe--timezone=timezone_name オプションを使用すると、起動時に MySQL Server のシステムタイムゾーンを設定できます。mysqld を起動する前に、TZ 環境変数を設定することによって設定することもできます。--timezone または TZ に許可される値は、システムによって異なります。許容可能な値を確認するには、オペレーティングシステムのドキュメントを参照してください。

  • サーバーの現在のタイムゾーン。time_zone グローバルシステム変数は、サーバーが現在動作しているタイムゾーンを示します。time_zone の初期値は 'SYSTEM' であり、これはサーバーのタイムゾーンがシステムタイムゾーンと同じであることを示します。

    コマンド行で --default-time-zone=timezone オプションを使用すると、初期グローバルサーバータイムゾーン値を起動時に明示的に指定できます。または、オプションファイルで次の行を使用できます。

    default-time-zone='timezone'

    SUPER 権限がある場合は、実行時に次のステートメントを使用すると、サーバータイムゾーンのグローバル値を設定できます。

    mysql> SET GLOBAL time_zone = timezone;
  • 接続ごとのタイムゾーン。接続するそれぞれのクライアントには、time_zone セッション変数で指定された、それぞれのタイムゾーン設定があります。最初、セッション変数は、time_zone グローバル変数から値を取得しますが、クライアントは次のステートメントを使用して、それぞれのタイムゾーンを変更できます。

    mysql> SET time_zone = timezone;

現在のセッションのタイムゾーン設定は、ゾーンを区別する時間値の表示とストレージに影響します。これには、NOW()CURTIME() などの関数で表示される値や、TIMESTAMP カラムに保存し、そこから読み出す値も含まれます。TIMESTAMP カラムの値は、ストレージでは現在のタイムゾーンから UTC に、読み出しでは UTC から現在のタイムゾーンに変換されます。

現在のタイムゾーン設定は、UTC_TIMESTAMP() 関数などによって表示される値、または DATETIMEDATETIME カラムの値には影響しません。また、これらのデータ型の値も UTC で格納されません。タイムゾーンは、TIMESTAMP 値から変換するときにのみ適用されます。DATETIME、または DATETIME 値に対してロケール固有の演算を実行する場合、これらの値を UTC に変換し、演算を実行してから、元に変換し直します。

グローバルおよびクライアント固有のタイムゾーンの現在値は、次のように取得できます。

mysql> SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;

timezone 値は、次の複数の形式で指定でき、大文字と小文字を区別しません。

  • 'SYSTEM' 値は、タイムゾーンをシステムタイムゾーンと同じにする必要があることを示します。

  • この値は、'+10:00''-6:00' など、UTC からのオフセットを示す文字列として指定できます。

  • この値は、'Europe/Helsinki''US/Eastern''MET' などの名前付きのタイムゾーンとして指定できます。名前付きのタイムゾーンは、mysql データベース内のタイムゾーン情報テーブルが作成され移入されている場合にのみ使用できます。

MySQL のインストール手順では、mysql データベース内にタイムゾーンテーブルを作成しますが、これらをロードしません。次の手順を使用して、手動でこれを行う必要があります。(以前のバージョンから MySQL 4.1.3 以降にアップグレードする場合は、mysql データベースをアップグレードすることでテーブルを作成できます。セクション4.4.7「mysql_upgrade — MySQL テーブルのチェックとアップグレード」の手順を使用してください。テーブルを作成したあとでロードできます。)

注記

情報は変更することがあるので、タイムゾーン情報のロードは必ずしも 1 回だけの操作とはかぎりません。たとえば、米国、メキシコ、一部のカナダのサマータイムのルールは、2007 年に変更されました。このような変更が起きた場合、古いルールを使用したアプリケーションは旧式になり、MySQL Server で使用されている情報を最新の状態に維持するために、タイムゾーンテーブルをリロードする必要が生じることがあります。このセクションの最後のノートを参照してください。

システムに独自の zoneinfo データベース (タイムゾーンについて述べたファイルセット) がある場合、タイムゾーンテーブルに入力するために mysql_tzinfo_to_sql プログラムを使用する必要があります。このようなシステムには、Linux、FreeBSD、Solaris、OS X などがあります。これらのファイルの 1 つの適切な場所は /usr/share/zoneinfo ディレクトリです。システムに zoneinfo データベースがない場合、このセクションで後述するダウンロード可能なパッケージを使用できます。

mysql_tzinfo_to_sql プログラムはタイムゾーンテーブルのロードに使用されます。コマンド行で、zoneinfo ディレクトリのパス名を mysql_tzinfo_to_sql に渡し、出力を mysql プログラムに送信します。例:

shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

mysql_tzinfo_to_sql は、システムのタイムゾーンファイルを読み取り、そのファイルから SQL ステートメントを生成します。mysql はこれらのステートメントを処理して、タイムゾーンテーブルをロードします。

mysql_tzinfo_to_sql を使用すると、単一のタイムゾーンファイルをロードしたり、うるう秒情報を生成したりできます。

  • タイムゾーン名 tz_name に対応した単一のタイムゾーンファイル tz_file をロードするには、次のように mysql_tzinfo_to_sql を呼び出します。

    shell> mysql_tzinfo_to_sql tz_filetz_name | mysql -u root mysql

    このアプローチでは、サーバーが認識する名前付きゾーンごとに、個別のコマンドを実行してタイムゾーンファイルをロードする必要があります。

  • タイムゾーンがうるう秒に対応する必要がある場合は、次のようにうるう秒の情報を初期化します。ここで tz_file はタイムゾーンファイルの名前です。

    shell> mysql_tzinfo_to_sql --leap tz_file | mysql -u root mysql
  • mysql_tzinfo_to_sql の実行後、以前にキャッシュしたすべてのタイムゾーンデータを使用し続けないように、サーバーを再起動することをお勧めします。

zoneinfo データベース (Windows など) を含まないシステムの場合、MySQL Developer Zone でダウンロードに使用できる事前に構築されたタイムゾーンテーブルのパッケージを使用できます。

https://dev.mysql.com/downloads/timezones.html

このタイムゾーンパッケージには、MyISAM のタイムゾーンテーブル用に、.frm.MYD.MYI などのファイルが含まれています。これらのテーブルを mysql データベースの一部にする必要があるため、ファイルを MySQL Server のデータディレクトリの mysql サブディレクトリに入れてください。サーバーを停止してからこれを行い、そのあとで再起動します。

警告

システムに zoneinfo データベースがある場合は、ダウンロード可能なパッケージを使用しないでください。代わりに、mysql_tzinfo_to_sql ユーティリティーを使用してください。そうしないと、MySQL とシステム上のほかのアプリケーション間で日時処理に違いが生じることがあります。

レプリケーションセットアップのタイムゾーン設定の詳細は、セクション17.4.1「レプリケーションの機能と問題」を参照してください。

10.6.1 タイムゾーンの変更による現在の時間の維持

前述のように、タイムゾーンルールが変更すると、古いルールを使用するアプリケーションが旧式になります。現在の時間に維持するには、システムが現在のタイムゾーン情報を使用していることを確認する必要があります。MySQL の場合、現在の時間に維持するために考慮する 2 つの要素があります。

  • オペレーティングシステムの時間は、そのタイムゾーンが SYSTEM に設定されている場合、MySQL Server が時間に使用する値に影響します。オペレーティングシステムが最新のタイムゾーン情報を使用していることを確認します。ほとんどのオペレーティングシステムでは、最新の更新またはサービスパックによってシステムは時間の変更に対応できます。時間の変更に対処した更新については、オペレーティングシステムベンダーの Web サイトを確認してください。

  • システムの /etc/localtime タイムゾーンファイルを、mysqld の起動時に有効なものとは異なるルールを使用するバージョンに置き換えた場合、更新したルールを使用するように mysqld を再起動する必要があります。そうしないと、システムが時間を変更したときに mysqld が認識されないことがあります。

  • MySQL で名前付きのタイムゾーンを使用する場合、mysql データベース内のタイムゾーンテーブルが最新になっていることを確認します。システムに独自の zoneinfo データベースがある場合は、zoneinfo データベースを更新するたびに、このセクションで前述した手順を使用して MySQL タイムゾーンテーブルをリロードする必要があります。システムに独自の zoneinfo データベースがない場合、MySQL Developer Zone で更新がないか調べます。新しい更新が利用できる場合は、これをダウンロードし使用して、現在のタイムゾーンテーブルを置き換えます。mysqld は、検索したタイムゾーン情報をキャッシュするので、タイムゾーンテーブルを置き換えたあとは、mysqld を再起動して、古くなったタイムゾーンデータを提供し続けないようにする必要があります。

サーバーのタイムゾーン設定として使用するか、独自のタイムゾーンを設定するクライアントが使用するために、名前付きタイムゾーンが使用できるかどうか不確かな場合は、タイムゾーンテーブルが空かどうかを調べてください。次のクエリーは、タイムゾーン名を含むテーブルに行があるかどうかを判断します。

mysql> SELECT COUNT(*) FROM mysql.time_zone_name;+----------+
| COUNT(*) |
+----------+
| 0 |
+----------+

カウントがゼロの場合、テーブルが空であることを示します。この場合、名前付きタイムゾーンを使用できず、テーブルを更新する必要はありません。カウントがゼロより大きい場合、テーブルは空ではなく、その内容が名前付きタイムゾーンのサポートに使用できることを示します。この場合、名前付きタイムゾーンを使用するユーザーが、正しいクエリー結果が得られるように、必ずタイムゾーンテーブルをリロードしてください。

サマータイムのルール変更に対して MySQL インストールが正しく更新されているかどうかを確認するには、次のようなテストを使用します。この例では、3 月 11 日午前 2 時に米国で行われる 2007 年 DST の 1 時間の変更に適切な値を使用しています。

テストでは次の 2 つのクエリーを使用します。

SELECT CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central');
SELECT CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central');

2 つの時間値は、DST 変更が行われる時間を示し、名前付きタイムゾーンの使用には、タイムゾーンテーブルを使用する必要がにあります。結果では、両方のクエリーで同じ結果が返されることが期待されます (「米国/中央」タイムゾーンの同等の値に変換された入力時間)。

タイムゾーンテーブルを更新する前に、次のような正しくない結果が表示されます。

mysql> SELECT CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central');+------------------------------------------------------------+
| CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central') |
+------------------------------------------------------------+
| 2007-03-11 01:00:00 |
+------------------------------------------------------------+
mysql> SELECT CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central');+------------------------------------------------------------+
| CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central') |
+------------------------------------------------------------+
| 2007-03-11 02:00:00 |
+------------------------------------------------------------+

テーブルの更新後に、正しい結果が表示されます。

mysql> SELECT CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central');+------------------------------------------------------------+
| CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central') |
+------------------------------------------------------------+
| 2007-03-11 01:00:00 |
+------------------------------------------------------------+
mysql> SELECT CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central');+------------------------------------------------------------+
| CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central') |
+------------------------------------------------------------+
| 2007-03-11 01:00:00 |
+------------------------------------------------------------+

10.6.2 タイムゾーンのうるう秒のサポート

うるう秒値は、:59:59 で終わる時間部分を使用して返されます。これは、NOW() などの関数が、うるう秒の間、2、3 秒連続して同じ値を返すことがあることを意味します。:59:60 または :59:61 で終わる時間部分を持つリテラル時間値が無効と見なされることに変わりはありません。

うるう秒の 1 秒前の TIMESTAMP 値を検索する必要がある場合、'YYYY-MM-DD hh:mm:ss' 値での比較を使用すると異常な結果が得られることがあります。この点について次の例で説明します。ローカルタイムゾーンを UTC に変更するので、内部値 (UTC での値) と表示値 (タイムゾーン修正が適用された値) の差がなくなります。

mysql> CREATE TABLE t1 ( ->  a INT, ->  ts TIMESTAMP DEFAULT NOW(), ->  PRIMARY KEY (ts) -> );Query OK, 0 rows affected (0.01 sec)
mysql> -- change to UTCmysql> SET time_zone = '+00:00';Query OK, 0 rows affected (0.00 sec)
mysql> -- Simulate NOW() = '2008-12-31 23:59:59'mysql> SET timestamp = 1230767999;Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 (a) VALUES (1);Query OK, 1 row affected (0.00 sec)
mysql> -- Simulate NOW() = '2008-12-31 23:59:60'mysql> SET timestamp = 1230768000;Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 (a) VALUES (2);Query OK, 1 row affected (0.00 sec)
mysql> -- values differ internally but display the samemysql> SELECT a, ts, UNIX_TIMESTAMP(ts) FROM t1;+------+---------------------+--------------------+
| a | ts | UNIX_TIMESTAMP(ts) |
+------+---------------------+--------------------+
| 1 | 2008-12-31 23:59:59 | 1230767999 |
| 2 | 2008-12-31 23:59:59 | 1230768000 |
+------+---------------------+--------------------+
2 rows in set (0.00 sec)
mysql> -- only the non-leap value matchesmysql> SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:59';+------+---------------------+
| a | ts |
+------+---------------------+
| 1 | 2008-12-31 23:59:59 |
+------+---------------------+
1 row in set (0.00 sec)
mysql> -- the leap value with seconds=60 is invalidmysql> SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:60';Empty set, 2 warnings (0.00 sec)

これを回避するには、うるう秒の修正が適用されている、実際にカラムに格納されている UTC 値に基づいた比較を使用します。

mysql> -- selecting using UNIX_TIMESTAMP value return leap valuemysql> SELECT * FROM t1 WHERE UNIX_TIMESTAMP(ts) = 1230768000;+------+---------------------+
| a | ts |
+------+---------------------+
| 2 | 2008-12-31 23:59:59 |
+------+---------------------+
1 row in set (0.00 sec)

10.7 MySQL Server のロケールサポート

lc_time_names システム変数で示されたロケールは、曜日および月の名前と短縮形を表示するために使用する言語を制御します。この変数は DATE_FORMAT()DAYNAME()、および MONTHNAME() 関数の出力に影響を与えます。

lc_time_names は、STR_TO_DATE() または GET_FORMAT() 関数には影響しません。

lc_time_names 値は、FORMAT() の結果に影響しませんが、この関数は、結果の数値の小数点、桁区切り、および区切り文字のグルーピングに使用するロケールを指定できるようにするオプションの 3 番目のパラメータを取ります。許可されるロケール値は、lc_time_names システム変数の正当な値と同じです。

ロケール名には、'ja_JP''pt_BR' など、IANA (http://www.iana.org/assignments/language-subtag-registry) に記載された言語および地域のサブタグが含まれます。システムのロケール設定とは無関係にデフォルト値は 'en_US' ですが、サーバーの起動時に値を設定することも、SUPER 権限がある場合には GLOBAL 値を設定することもできます。どのクライアントでも、lc_time_names の値を調べたり、その SESSION 値を設定してそれ自体の接続用のロケールに影響を与えたりできます。

mysql> SET NAMES 'utf8';Query OK, 0 rows affected (0.09 sec)
mysql> SELECT @@lc_time_names;+-----------------+
| @@lc_time_names |
+-----------------+
| en_US |
+-----------------+
1 row in set (0.00 sec)
mysql> SELECT DAYNAME('2010-01-01'), MONTHNAME('2010-01-01');+-----------------------+-------------------------+
| DAYNAME('2010-01-01') | MONTHNAME('2010-01-01') |
+-----------------------+-------------------------+
| Friday | January |
+-----------------------+-------------------------+
1 row in set (0.00 sec)
mysql> SELECT DATE_FORMAT('2010-01-01','%W %a %M %b');+-----------------------------------------+
| DATE_FORMAT('2010-01-01','%W %a %M %b') |
+-----------------------------------------+
| Friday Fri January Jan |
+-----------------------------------------+
1 row in set (0.00 sec)
mysql> SET lc_time_names = 'es_MX';Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@lc_time_names;+-----------------+
| @@lc_time_names |
+-----------------+
| es_MX |
+-----------------+
1 row in set (0.00 sec)
mysql> SELECT DAYNAME('2010-01-01'), MONTHNAME('2010-01-01');+-----------------------+-------------------------+
| DAYNAME('2010-01-01') | MONTHNAME('2010-01-01') |
+-----------------------+-------------------------+
| viernes | enero |
+-----------------------+-------------------------+
1 row in set (0.00 sec)
mysql> SELECT DATE_FORMAT('2010-01-01','%W %a %M %b');+-----------------------------------------+
| DATE_FORMAT('2010-01-01','%W %a %M %b') |
+-----------------------------------------+
| viernes vie enero ene |
+-----------------------------------------+
1 row in set (0.00 sec)

影響を受けた関数それぞれの曜日または月の名前は、utf8 から character_set_connection システム変数で指定される文字セットに変換されます。

lc_time_names は次のどのロケール値にも設定できます。MySQL でサポートされるロケールのセットは、オペレーティングシステムでサポートされるものと異なる場合があります。

ar_AE: アラビア語 - アラブ首長国連邦ar_BH: アラビア語 - バーレーン
ar_DZ: アラビア語 - アルジェリアar_EG: アラビア語 - エジプト
ar_IN: アラビア語 - インドar_IQ: アラビア語 - イラク
ar_JO: アラビア語 - ヨルダンar_KW: アラビア語 - クウェート
ar_LB: アラビア語 - レバノンar_LY: アラビア語 - リビア
ar_MA: アラビア語 - モロッコar_OM: アラビア語 - オマーン
ar_QA: アラビア語 - カタールar_SA: アラビア語 - サウジアラビア
ar_SD: アラビア語 - スーダンar_SY: アラビア語 - シリア
ar_TN: アラビア語 - チュニジアar_YE: アラビア語 - イエメン
be_BY: ベラルーシ語 - ベラルーシbg_BG: ブルガリア語 - ブルガリア
ca_ES: カタロニア語 - スペインcs_CZ: チェコ語 - チェコ
da_DK: デンマーク語 - デンマークde_AT: ドイツ語 - オーストリア
de_BE: ドイツ語 - ベルギーde_CH: ドイツ語 - スイス
de_DE: ドイツ語 - ドイツde_LU: ドイツ語 - ルクセンブルク
el_GR: ギリシャ語 - ギリシャen_AU: 英語 - オーストラリア
en_CA: 英語 - カナダen_GB: 英語 - イギリス
en_IN: 英語 - インドen_NZ: 英語 - ニュージーランド
en_PH: 英語 - フィリピンen_US: 英語 - 米国
en_ZA: 英語 - 南アフリカen_ZW: 英語 - ジンバブエ
es_AR: スペイン語 - アルゼンチンes_BO: スペイン語 - ボリビア
es_CL: スペイン語 - チリes_CO: スペイン語 - コロンビア
es_CR: スペイン語 - コスタリカes_DO: スペイン語 - ドミニカ共和国
es_EC: スペイン語 - エクアドルes_ES: スペイン語 - スペイン
es_GT: スペイン語 - グアテマラes_HN: スペイン語 - ホンジュラス
es_MX: スペイン語 - メキシコes_NI: スペイン語 - ニカラグア
es_PA: スペイン語 - パナマes_PE: スペイン語 - ペルー
es_PR: スペイン語 - プエルトリコes_PY: スペイン語 - パラグアイ
es_SV: スペイン語 - エルサルバドルes_US: スペイン語 - 米国
es_UY: スペイン語 - ウルグアイes_VE: スペイン語 - ベネズエラ
et_EE: エストニア語 - エストニアeu_ES: バスク語 - バスク
fi_FI: フィンランド語 - フィンランドfo_FO: フェーロー語 - フェロー諸島
fr_BE: フランス語 - ベルギーfr_CA: フランス語 - カナダ
fr_CH: フランス語 - スイスfr_FR: フランス語 - フランス
fr_LU: フランス語 - ルクセンブルクgl_ES: ガリシア語 - スペイン
gu_IN: グジャラート語 - インドhe_IL: ヘブライ語 - イスラエル
hi_IN: ヒンディー語 - インドhr_HR: クロアチア語 - クロアチア
hu_HU: ハンガリー語 - ハンガリーid_ID: インドネシア語 - インドネシア
is_IS: アイスランド語 - アイスランドit_CH: イタリア語 - スイス
it_IT: イタリア語 - イタリアja_JP: 日本語 - 日本
ko_KR: 韓国語 - 韓国lt_LT: リトアニア語 - リトアニア
lv_LV: ラトビア語 - ラトビアmk_MK: マケドニア語 - マケドニア
mn_MN: モンゴル語 - モンゴルms_MY: マレー語 - マレーシア
nb_NO: ノルウェー語 (ブークモール) - ノルウェーnl_BE: オランダ語 - ベルギー
nl_NL: オランダ語 - オランダno_NO: ノルウェー語 - ノルウェー
pl_PL: ポーランド語 - ポーランドpt_BR: ポルトガル語 - ブラジル
pt_PT: ポルトガル語 - ポルトガルrm_CH: ロマンシュ語 - スイス
ro_RO: ルーマニア語 - ルーマニアru_RU: ロシア語 - ロシア
ru_UA: ロシア語 - ウクライナsk_SK: スロバキア語 - スロバキア
sl_SI: スロベニア語 - スロベニアsq_AL: アルバニア語 - アルバニア
sr_RS: セルビア語 - ユーゴスラビアsv_FI: スウェーデン語 - フィンランド
sv_SE: スウェーデン語 - スウェーデンta_IN: タミル語 - インド
te_IN: テルグ語 - インドth_TH: タイ語 - タイ
tr_TR: トルコ語 - トルコuk_UA: ウクライナ語 - ウクライナ
ur_PK: ウルドゥー語 - パキスタンvi_VN: ベトナム語 - ベトナム
zh_CN: 中国語 - 中国zh_HK: 中国語 - 香港
zh_TW: 中国語 - 台湾 
関連キーワード:  セット,照合順序,します,10,latin1,utf8,MySQL,SET,および,mysql