Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 27.1Mb
PDF (A4) - 27.2Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


MySQL 5.6 リファレンスマニュアル  /  ...  /  YEAR(2) の制限と YEAR(4) への移行

11.3.4 YEAR(2) の制限と YEAR(4) への移行

このセクションでは、YEAR(2) の使用時に生じる可能性のある問題を取り上げ、既存の YEAR(2) カラムを YEAR(4) に変換するための情報について説明します。

YEAR(4)YEAR(2) の値の内部範囲は同じですが (1901 から 2155、および 0000)、YEAR(2) の表示幅は、表示値が内部値の最後の 2 桁しか示さず、世紀を表す最初の 2 桁を省略するので、その型があいまいになります。特定の状況下では情報が失われる結果になることもあります。このため、YEAR データ型が必要なときは必ず、アプリケーション全体で YEAR(2) の使用を避け、YEAR(4) を使用するよう検討してください。MySQL 5.6.6 以降では、4 以外の表示値の YEAR データ型 (特に YEAR(2)) のサポートが縮小し、今後のリリースで完全に廃止される予定なので、ある時点で変換が必要になります。

YEAR(2) の制限

YEAR(2) データ型に関する問題には、表示値のあいまいさと、値のダンプおよびリロード時または文字列への変換時に情報損失の可能性があります。

  • YEAR(2) の表示値はあいまいな場合があります。次の例で示すように、異なる内部値を持つ最大 3 つの YEAR(2) 値を同じ表示値にできます。

    mysql> CREATE TABLE t (y2 YEAR(2), y4 YEAR(4));
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> INSERT INTO t (y2) VALUES(1912),(2012),(2112);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> UPDATE t SET y4 = y2;
    Query OK, 3 rows affected (0.00 sec)
    Rows matched: 3  Changed: 3  Warnings: 0
    
    mysql> SELECT * FROM t;
    +------+------+
    | y2   | y4   |
    +------+------+
    |   12 | 1912 |
    |   12 | 2012 |
    |   12 | 2112 |
    +------+------+
    3 rows in set (0.00 sec)
    
  • mysqldump を使用して、前述の項目に作成されたテーブルをダンプする場合、ダンプファイルは、同じ 2 桁の表現 (12) を使用してすべての y2 値を表します。ダンプファイルからテーブルをリロードした場合、すべての結果の行に内部値 2012 と表示値 12 を含まれるので、これらの違いが失われます。

  • YEAR(2) または YEAR(4) データ値を文字列形式に変換した場合、YEAR 型の表示幅が使用されます。YEAR(2)YEAR(4) の両方のカラムに 1970 の値が含まれるとします。それぞれのカラムを文字列に割り当てた結果、それぞれ '70''1970' の値になります。つまり、YEAR(2) から文字列への変換で情報の損失が起こります。

  • 1970 から 2069 の範囲から外れた値は、CSV テーブルの YEAR(2) カラムに挿入されるときに、間違って格納されます。たとえば、2111 を挿入すると、表示値は 11 になりますが、内部値は 2011 になります。

これらの問題を避けるには、YEAR(2) ではなく YEAR(4) を使用してください。移行戦略に関した提案は、このセクションで後述します。

MySQL 5.6 の YEAR(2) サポートの縮小

MySQL 5.6.6 以降で、YEAR(2) のサポートは縮小されます。

  • 新しいテーブルの YEAR(2) カラム定義は、YEAR(4) に (警告付きで) 変換されます。

    mysql> CREATE TABLE t1 (y YEAR(2));
    Query OK, 0 rows affected, 1 warning (0.03 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 1818
    Message: YEAR(2) column type is deprecated. Creating YEAR(4) column instead.
    1 row in set (0.00 sec)
    
    mysql> SHOW CREATE TABLE t1\G
    *************************** 1. row ***************************
           Table: t1
    Create Table: CREATE TABLE `t1` (
      `y` year(4) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)
    
  • 既存のテーブルの YEAR(2)YEAR(2) として残され、古いバージョンの MySQL と同様にクエリーで処理されます。ただし、複数のプログラムまたはステートメントが、YEAR(2)YEAR(4) に自動的に変換します。

    • テーブルの再構築を招く ALTER TABLE ステートメント。

    • REPAIR TABLE (YEAR(2) カラムがテーブルに含まれることが CHECK TABLE で検出された場合に、使用するように推奨されます)。

    • mysql_upgrade (REPAIR TABLE を使用します)。

    • mysqldump でのダンプおよびダンプファイルのリロード。上記の 3 つの項目が実行する変換とは異なり、ダンプとリロードは値を変更する可能性があります。

    MySQL アップグレードでは通常、最後の 2 つの項目のうち少なくとも 1 つを含みます。ただし、YEAR(2) については mysql_upgrade をお勧めします。前述のように値を変更する可能性があるので、mysqldump は使用しないでください。

YEAR(2) から YEAR(4) への移行

YEAR(2) カラムを YEAR(4) に変換するには、手動でアップグレードなしにいつでも行えます。または、YEAR(2) のサポートが縮小したバージョンの MySQL (MySQL 5.6.6 以降) にアップグレードしてから、MySQL で YEAR(2) カラムを自動的に変換できます。後者の場合は、データのダンプとリロードによるアップグレードは行わないでください。データ値を変更する可能性があります。さらに、レプリケーションを使用する場合は、注意の必要なアップグレードに関する考慮事項があります。

YEAR(2) カラムを YEAR(4) に手動で変換するには、ALTER TABLE を使用してください。テーブル t1 に次の定義があるとします。

CREATE TABLE t1 (ycol YEAR(2) NOT NULL DEFAULT '70');

次のように ALTER TABLE を使用してカラムを変更します。必ず、NOT NULLDEFAULT などのすべてのカラム属性を含めてください。

ALTER TABLE t1 MODIFY ycol YEAR(4) NOT NULL DEFAULT '1970';

ALTER TABLE ステートメントは、YEAR(2) 値を変更しないでテーブルを変換します。サーバーがレプリケーションマスターである場合、ALTER TABLE ステートメントはスレーブに複製され、各対応するテーブルを変更します。

別の移行方法では、バイナリアップグレードを実行します。データのダンプおよびリロードを行わないで MySQL 5.6.6 以降をインストールします。続いて、mysql_upgrade を実行します。これは、REPAIR TABLE を使用して、データ値を変更しないで YEAR(2) カラムを YEAR(4) に変換します。サーバーがレプリケーションマスターである場合、--skip-write-binlog オプションを付けて mysql_upgrade を呼び出さないかぎり、REPAIR TABLE ステートメントはスレーブに複製され、各対応するテーブルを変更します。

レプリケーションサーバーへのアップグレードでは通常、新しいバージョンの MySQL へのスレーブのアップグレードと、マスターのアップグレードが行われます。たとえば、マスターとスレーブの両方で MySQL 5.5 が実行している場合、通常のアップグレードシーケンスでは、スレーブを 5.6 にアップグレードしてからマスターを 5.6 にアップグレードします。MySQL 5.6.6 以降での YEAR(2) の異なる扱いに関しては、このアップグレードシーケンスにより問題が生じます。スレーブがアップグレードされているが、マスターがまだアップグレードされていないとします。この場合、マスター上に YEAR(2) カラムを含んだテーブルを作成すると、スレーブ上では YEAR(4) カラムを含むテーブルが作成されます。この結果、ステートメントベースのレプリケーションを使用した場合、これらの操作はマスターとスレーブで異なる結果になります。

  • 数値 0 の挿入。結果の値は、マスター上では 2000 の内部値になりますが、スレーブ上では 0000 の内部値になります。

  • 文字列への YEAR(2) の変換。この操作は、マスター上では YEAR(2) の表示値を使用しますが、スレーブ上では YEAR(4) の表示値を使用します。

このような問題を避けるには、次の戦略のいずれかを使用します。

  • ステートメントベースのレプリケーションの代わりに行ベースのレプリケーションを使用します。

  • アップグレード前に、マスター上のすべての YEAR(2) カラムを YEAR(4) に変更します。(前述のように ALTER TABLE を使用します。)続いて、YEAR(2) から YEAR(4) の移行でマスターとスレーブ間で違いが生じることなく、通常どおりに (最初にスレーブ、次にマスター) アップグレードできます)。

mysqldump でデータをダンプし、アップグレードしたあとにダンプファイルをリロードするという移行方法は使用しないでください。前述のように、これは YEAR(2) 値を変更する可能性があります。

YEAR(2) から YEAR(4) への移行では、次のような条件下で動作が変更された可能性がないかどうかアプリケーションコードの検査も行う必要があります。

  • YEAR カラムを選択すれば正確に 2 桁が生成されると予想しているコード。

  • 0YEAR(2) または YEAR(4) に挿入すると、それぞれ 2000 または 0000 の内部値になるという、数値 0 の挿入に対する別々の処理に対応していないコード。


User Comments
Sign Up Login You must be logged in to post a comment.