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


1.7.3.3 無効データの制約

デフォルトでは、MySQL は無効または不適切なデータ値を許容しており、これらをデータエントリに対する有効な値に強制的に変更します。ただし、厳密 SQL モードを有効にして、サーバーが不良値を拒否し、不良値が発生するステートメントを中止するという従来の方法に近い不良値の取り扱いを選択できます。セクション5.1.7「サーバー SQL モード」を参照してください。

このセクションでは、MySQL のデフォルトの (許可されている) 動作のほか、厳密 SQL モードとこれがどのように異なるかについて説明します。

厳密モードを使用していない場合、NOT NULL カラムに NULL を挿入したり、数値カラムに大きすぎる数値を挿入したりするなど、正しくない値をカラムに挿入すると、MySQL は、エラーを生成するのではなく、カラムを最適可能値に設定します。この動作ルールについて、次に詳しく説明します。

  • 数値カラムに範囲外の値を格納しようとすると、MySQL Server は代わりに、0、指定可能な最小値、または指定可能な最大値 (いずれも無効値に近い値) を格納します。

  • 文字列については、MySQL は空白文字列、またはカラム内に格納可能な最長文字列を格納します。

  • 数字で始まらない文字列を数値カラムに格納しようとすると、MySQL Server は 0 を格納します。

  • セクション1.7.3.4「ENUM および SET の制約」で説明するように、ENUM カラムと SET カラムの無効な値は処理されます。

  • MySQL では、特定の不正なデータ値を、DATE カラムと DATETIME カラムに格納できます ('2000-02-31''2000-02-00' など)。この場合、アプリケーションが厳密 SQL モードを有効にしていなければ、これらを格納する前に日付を検証するのはアプリケーションに任されます。MySQL が日付値を格納し、ちょうど同じ値を検索できる場合、MySQL は与えられたとおりに格納します。日付が完全に不正な場合 (サーバーの格納能力を超えている場合) は、代わりに特殊なゼロ日付値である '0000-00-00' がカラムに格納されます。

  • NULL 値を使用することができないカラムに NULL を格納しようとすると、単一行の INSERT ステートメントに対するエラーが生じます。複数行の INSERT ステートメントや INSERT INTO ... SELECT ステートメントに対して、MySQL Server は、カラムデータ型に暗黙のデフォルト値を格納します。一般に、これは数値型には 0、文字列型には空の文字列 ('')、および日時型にはゼロ値になります。暗黙のデフォルト値については、セクション11.6「データ型デフォルト値」で説明されています。

  • INSERT ステートメントがカラムに対して値を指定しない場合、MySQL は、カラム定義に明示的な DEFAULT 句が含まれていると、そのデフォルト値を挿入します。定義に DEFAULT のような句が含まれていなければ、MySQL はカラムデータ型に暗黙のデフォルト値を挿入します。

非厳密モードで前述のルールを使用する理由は、ステートメントが実行を開始するまで、これらの条件をチェックできないからです。ストレージエンジンでロールバックがサポートされていない可能性があるため、複数の行を更新したあとで問題が発生した場合は、単にロールバックすればよいというわけにはいきません。ステートメントを終了するというオプションは、ここまでよくはありません。この場合、更新が未完了のため、最悪のシナリオになる可能性があります。この場合、できるかぎり最善を尽くし、何も起こらなかったように続けることがお勧めです。

MySQL 5.0.2 以降では、STRICT_TRANS_TABLES または STRICT_ALL_TABLES SQL モードを使用して、より厳密な入力値処理を選択できます。

SET sql_mode = 'STRICT_TRANS_TABLES';
SET sql_mode = 'STRICT_ALL_TABLES';

STRICT_TRANS_TABLES は、トランザクションストレージエンジンに対して厳密モードを有効にし、非トランザクションエンジンに対してもある程度有効にします。これは、次のように動作します。

  • トランザクションストレージエンジンの場合、ステートメント内で生じる不良データ値は、ステートメントの実行中止やロールバックを引き起こします。

  • 非トランザクションストレージエンジンの場合、ステートメントは、挿入または更新される最初の行でエラーが発生した場合に中止します。(トランザクションテーブルの場合と同じように、最初の行でエラーが生じた場合、ステートメントを中止して、テーブルを変更しないままにしておくことができます。)2 行以降でエラーが生じた場合、最初の行によってテーブルがすでに変更されているため、ステートメントは中止しません。代わりに、不良データ値が調整され、この結果、エラーではなく警告が発せられます。言い換えると、STRICT_TRANS_TABLES を使用すると、テーブルを変更せずに行える場合は、間違った値によって、MySQL はこれまでに行われたすべての更新をロールバックします。ただし、いったんテーブルが変更されると、それ以降に生じるエラーは調整や警告になります。

より厳密なチェックの場合にも、STRICT_ALL_TABLES を有効にします。これは、STRICT_TRANS_TABLES と同じですが、非トランザクションストレージエンジンの場合に、2 行目以降の行の不良データであっても、エラーによりステートメントが中止する点が異なります。これは、非トランザクションテーブルで複数行の挿入または更新の途中でエラーが発生した場合、部分更新が行われることを意味します。これより前の行は挿入または更新されますが、エラーの時点以降の行は挿入も更新もされません。非トランザクションテーブルでこれを回避するには、単一行ステートメントを使用するか、エラーではなく変換警告が許容できる場合は STRICT_TRANS_TABLES を使用してください。初めから問題を避けるには、MySQL でカラム内容をチェックさせないようにしてください。データベースに有効な値だけを渡していることをアプリケーションに確認させることがもっとも安全です (多くの場合で高速になります)。

厳密モードオプションのいずれかで、IGNORE のない INSERT または UPDATE ではなく、INSERT IGNORE または UPDATE IGNORE を使用することによって、エラーを警告として処理することができます。