MySQLでは、デフォルトで無効や不適切なデータ値が許可されており、データ入力の際にそれらを有効値に強制変換します。しかし、サーバSQLモードを変更することで、不良値が生じた際にサーバが拒絶やステートメントの実行を中止するような、従来により近い不良値の処理方法が選択できます。項4.2.6. 「SQL モード」 を参照してください。
このセクションでは、MySQLのデフォルト(許可されている)処理方法と厳格SQLモードの処理方法の相違点について説明しています。
厳格モードを使用していない場合、NOT
NULLカラムにおけるNULLや数値カラムにおける大きすぎる数値のように「正しくない」
値をカラムに挿入すると、MySQL
ではエラーを生成するのではなく、カラムを「最適可能値」に設定します。この動作規則について、以下に詳しく説明します。
数値カラムに範囲外の値を格納しようとすると、代わりにMySQLサーバは0、使用可能な最小値、または使用可能な最大値(いずれも無効値に近い値)を 格納します。
文字列については、MySQLは空白文字列、またはカラム内で格納可能な最長文字列を格納します。
数値カラムに数値で始まらない文字列を格納しようとすると、MySQLサーバは0を格納します。
ENUMやSETカラムに対する無効値は、項1.8.6.3. 「ENUMおよびSET制約」に記載のとおりに処理されます。
MySQLでは、DATEやDATETIMEカラム('2000-02-31'や'2000-02-00'のようなもの)に、特定の不正確なデータ値を格納することが許可されています。これは、SQLサーバはデータ検証を行なわないことを意味します。データ値が格納できるか、または正確に同値が検索できる場合、MySQLはそれを既存値として格納します。日付が完全に不正確(サーバの格納能力を超えている)の場合は、代わりに特定の「ゼロ」日付値'0000-00-00'がカラムに格納されます。
NULL値を使用することができないカラムにNULLを格納しようとすると、単一行INSERTステートメントに対するエラーが生じます。複数行INSERTステートメントやINSERT
INTO ...
SELECTステートメントに対して、MySQLサーバは、カラムデータ型に含まれるデフォルト値を格納します。たいていこれは、数値型の0、文字列型の空白文字列('')、および日時型の「ゼロ」値です。暗黙のデフォルト値に関しては
項10.1.4. 「データタイプデフォルト値」
で説明されています。
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は、より厳格なチェックについても使用できます。.非トランザクショナルストレージエンジンでは2行以降の不良値に対してもエラーがステートメント実行を中止する、という点を除くと、上記のことはSTRICT_TRANS_TABLESと同じです。これは、非トランザクショナルテーブルへの複数行挿入もしくは更新の途中でエラーが生じた場合、部分的な更新のみが行なわれるということを意味します。より前の行が挿入または更新されますが、それらはエラーから生じるものではありません。非トランザクショナルテーブルでこのことを避けるには、エラーよりも変換警告のほうが適切な場合、単一行ステートメントまたはSTRICT_TRANS_TABLESのどちらかを使用してください。初期段階でこのような問題を避けるには、MySQLでカラム内容をチェックさせないようにしてください。データベースに対して確実に有効値のみが通過するようにアプリケーションを設定することが、最も安全(であり、時には高速)な方法です。
厳格モードオプションのいずれかで、IGNOREを用いずにINSERTやUPDATEよりも、INSERT
IGNOREまたはUPDATE
IGNOREを用いることで、エラーを警告として処理することができます。
