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


13.2.5 INSERT 構文

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name,...)] 
    [(col_name,...)]
    {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

または:

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name,...)]
    SET col_name={expr | DEFAULT}, ...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

または:

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name,...)] 
    [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE
      col_name=expr
        [, col_name=expr] ... ]

INSERT は、既存のテーブルに新しい行を挿入します。このステートメントの INSERT ... VALUES および INSERT ... SET 形式は、明示的に指定された値に基づいて行を挿入します。INSERT ... SELECT 形式は、別の 1 つまたは複数のテーブルから選択された行を挿入します。INSERT ... SELECT については、セクション13.2.5.1「INSERT ... SELECT 構文」でさらに詳細に説明されています。

MySQL 5.6.2 以降では、パーティション化されたテーブルに挿入する場合、どのパーティションおよびサブパーティションが新しい行を受け入れるかを制御できます。PARTITION オプションは、テーブルの 1 つ以上のパーティションまたはサブパーティション (またはその両方) の名前のカンマ区切りリストを受け取ります。特定の INSERT ステートメントによって挿入される行がリストされているいずれかのパーティションに一致しない場合、INSERT ステートメントは Found a row not matching the given partition set エラーで失敗します。詳細および例については、セクション19.5「パーティション選択」を参照してください。

古い行を上書きするには、INSERT の代わりに REPLACE を使用できます。REPLACE は、古い行を複製する一意のキー値を含む新しい行の処理において INSERT IGNORE に相当するものです。新しい行は、破棄されるのではなく、古い行を置き換えるために使用されます。セクション13.2.8「REPLACE 構文」を参照してください。

tbl_name は、行が挿入されるテーブルです。このステートメントによって値が提供されるカラムは、次のように指定できます。

  • テーブル名のあとにカラム名のカンマ区切りリストを指定できます。この場合は、指定された各カラムの値を VALUES リストまたは SELECT ステートメントで指定する必要があります。

  • INSERT ... VALUES または INSERT ... SELECT にカラム名のリストを指定しない場合は、テーブル内のすべてのカラムの値を VALUES リストまたは SELECT ステートメントで指定する必要があります。テーブル内のカラムの順序がわからない場合は、DESCRIBE tbl_name を使用して見つけます。

  • SET 句は、カラム名を明示的に示します。

カラム値は、次のいくつかの方法で指定できます。

  • 厳密な SQL モードで実行していない場合、値が明示的に指定されていないカラムはすべて、デフォルトの (明示的または暗黙的な) 値に設定されます。たとえば、テーブル内のすべてのカラムを指定していないカラムリストを指定した場合、指定されていないカラムはそのデフォルト値に設定されます。デフォルト値の割り当てについては、セクション11.6「データ型デフォルト値」で説明されています。セクション1.7.3.3「無効データの制約」も参照してください。

    デフォルト値が含まれていないすべてのカラムの値を明示的に指定しないかぎり、INSERT ステートメントでエラーが生成されるようにする場合は、厳密モードを使用するようにしてください。セクション5.1.7「サーバー SQL モード」を参照してください。

  • カラムを明示的にそのデフォルト値に設定するには、キーワード DEFAULT を使用します。これにより、テーブル内の各カラムの値が含まれていない不完全な VALUES リストを書かなくても済むため、いくつかのカラムを除くすべてのカラムに値を割り当てる INSERT ステートメントの記述が容易になります。そうでない場合は、VALUES リスト内の各値に対応するカラム名のリストを書き出す必要があります。

    また、特定のカラムのデフォルト値を生成する式で使用できるより一般的な形式として DEFAULT(col_name) を使用することもできます。

  • カラムリストと VALUES リストの両方が空である場合、INSERT は、各カラムがそのデフォルト値に設定された行を作成します。

    INSERT INTO tbl_name () VALUES();

    厳密モードでは、いずれかのカラムにデフォルト値が含まれていない場合、エラーが発生します。それ以外の場合、MySQL は、明示的に定義されたデフォルト値が含まれていないすべてのカラムに対して暗黙のデフォルト値を使用します。

  • expr を指定して、カラム値を指定できます。これには、式の型がカラムの型に一致しない場合は型変換が行われる可能性があり、特定の値の変換によって、データ型に応じて異なる値が挿入されることがあります。たとえば、文字列 '1999.0e-2'INTFLOATDECIMAL(10,6)、または YEAR カラムに挿入すると、それぞれ、値 199919.992119.992100、および 1999 が挿入されます。INT および YEAR カラムに格納される値が 1999 である理由は、文字列から整数への変換では、その文字列の最初の、有効な整数または年と見なすことができる部分だけが調べられるためです。浮動小数点および固定小数点数カラムの場合、文字列から浮動小数点への変換では、文字列全体を有効な浮動小数点値と見なします。

    expr は、以前に値リスト内に設定された任意のカラムを参照できます。たとえば、次のステートメントは、col2 の値が、前に割り当てられている col1 を参照しているため実行可能です。

    INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);

    ただし、次のステートメントは、col1 の値が、col1 のあとに割り当てられている col2 を参照しているため正当ではありません。

    INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);

    1 つの例外として、AUTO_INCREMENT 値を含むカラムがあります。AUTO_INCREMENT 値はほかの値の割り当てのあとに生成されるため、割り当て内の AUTO_INCREMENT カラムへの参照はすべて 0 を返します。

VALUES 構文を使用する INSERT ステートメントは複数の行を挿入できます。これを行うには、それぞれが括弧で囲まれ、カンマで区切られた、カラム値の複数のリストを含めます。例:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

各行の値リストは、括弧で囲まれている必要があります。次のステートメントは、リスト内の値の数がカラム名の数に一致しないため不正です。

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3,4,5,6,7,8,9);

このコンテキストでは、VALUEVALUES のシノニムです。どちらも、値リストの数については何も示しておらず、値リストが 1 つの場合でも複数の場合でも使用できます。

INSERT に関して影響を受けた行の値は、ROW_COUNT() 関数 (セクション12.14「情報関数」を参照してください) または mysql_affected_rows() C API 関数 (セクション23.8.7.1「mysql_affected_rows()」を参照してください) を使用して取得できます。

INSERT ... VALUES ステートメントを複数の値リストまたは INSERT ... SELECT とともに使用した場合、このステートメントは、次の形式の情報文字列を返します。

Records: 100 Duplicates: 0 Warnings: 0

Records は、このステートメントによって処理された行数を示します。(これは、Duplicates が 0 以外であることがあるため、必ずしも実際に挿入された行数ではありません。)Duplicates は、何らかの既存の一意のインデックス値を複製しているために挿入できなかった行数を示します。Warnings は、何らかの点で問題があったカラム値を挿入するための試行回数を示します。警告は、次のいずれかの条件で発生する場合があります。

  • NOT NULL として宣言されているカラムへの NULL の挿入。複数行の INSERT ステートメントまたは INSERT INTO ... SELECT ステートメントの場合、このカラムは、そのカラムデータ型の暗黙のデフォルト値に設定されます。これは、数値型では 0、文字列型では空の文字列 ('')、および日付と時間型では0の値です。サーバーは SELECT からの結果セットを検査して、それが単一行を返すかどうかを確認しないため、INSERT INTO ... SELECT ステートメントは複数行の挿入と同じ方法で処理されます。(単一行の INSERT の場合は、NULLNOT NULL カラムに挿入されても警告は発生しません。代わりに、このステートメントがエラーで失敗します。)

  • 数値カラムの、そのカラムの範囲外にある値への設定。この値は、その範囲のもっとも近い端点にクリップされます。

  • 数値カラムへの '10.34 a' などの値の割り当て。後続の非数値のテキストは取り除かれ、残りの数値部分が挿入されます。文字列値に先頭の数値部分が含まれていない場合、このカラムは 0 に設定されます。

  • 文字列カラム (CHARVARCHARTEXT、または BLOB) への、そのカラムの最大長を超える文字列の挿入。この値は、そのカラムの最大長に切り捨てられます。

  • 日付または時間カラムへの、そのデータ型として不正な値の挿入。このカラムは、その型の適切な 0 の値に設定されます。

C API を使用している場合は、mysql_info() 関数を呼び出すことによって情報文字列を取得できます。セクション23.8.7.35「mysql_info()」を参照してください。

INSERTAUTO_INCREMENT カラムを含むテーブルに行を挿入した場合、そのカラムに使用された値は SQL の LAST_INSERT_ID() 関数を使用して検索できます。C API 内からは、mysql_insert_id() 関数を使用します。

注記

これらの 2 つの関数が、必ずしも同じ動作を行うとは限りません。AUTO_INCREMENT カラムに関連した INSERT ステートメントの動作については、セクション12.14「情報関数」およびセクション23.8.7.37「mysql_insert_id()」でさらに詳細に説明されています。

INSERT ステートメントは、次の修飾子をサポートします。

  • DELAYED キーワードを使用した場合は、挿入される 1 つまたは複数の行をサーバーがバッファーに配置するため、INSERT DELAYED ステートメントを発行しているクライアントはただちに続行できます。そのテーブルが使用中である場合、サーバーはそれらの行を保持します。そのテーブルが未使用である場合、サーバーは行の挿入を開始する一方、そのテーブルに対する新しい読み取り要求が存在するかどうかを定期的にチェックします。存在する場合は、そのテーブルがふたたび未使用になるまで、遅延された行のキューは中断されます。セクション13.2.5.2「INSERT DELAYED 構文」を参照してください。

    DELAYED は、INSERT ... SELECT または INSERT ... ON DUPLICATE KEY UPDATE では無視されます。

    DELAYED はまた、テーブルやトリガーにアクセスする関数を使用しているか、または関数やトリガーから呼び出された INSERT でも無視されます。

    注記

    MySQL 5.6.6 現在、INSERT DELAYED は非推奨であり、将来のリリースで削除されます。代わりに INSERT (DELAYED を付けない) を使用してください。

  • LOW_PRIORITY キーワードを使用した場合、INSERT の実行は、ほかのどのクライアントもそのテーブルから読み取らなくなるまで遅延されます。これには、既存のクライアントが読み取っている間や、INSERT LOW_PRIORITY ステートメントが待機している間に読み取りを開始したほかのクライアントが含まれます。そのため、読み取り負荷の高い環境では、INSERT LOW_PRIORITY ステートメントを発行したクライアントが非常に長い時間 (場合によっては無期限に) 待機することになるおそれがあります。(これは、クライアントをただちに続行できるようにする INSERT DELAYED とは対照的です。)MyISAM テーブルで LOW_PRIORITY を使用すると、並列挿入が無効になるため、通常はこれを行わないようにしてください。セクション8.10.3「同時挿入」を参照してください。

    HIGH_PRIORITY を指定すると、サーバーが --low-priority-updates オプションで起動されている場合に、その効果がオーバーライドされます。また、同時挿入も使用されなくなります。セクション8.10.3「同時挿入」を参照してください。

    LOW_PRIORITYHIGH_PRIORITY は、テーブルレベルのロックのみを使用するストレージエンジン (MyISAMMEMORYMERGE など) にのみ影響を与えます。

  • IGNORE キーワードを使用した場合、INSERT ステートメントの実行中に発生したエラーは無視されます。たとえば、IGNORE を使用しない場合は、テーブル内の既存の UNIQUE インデックスまたは PRIMARY KEY 値を複製する行によって重複キーエラーが発生し、このステートメントは中止されます。IGNORE を指定すると、その行が破棄され、エラーは発生しません。代わりに、無視されたエラーが警告を生成する可能性がありますが、重複キーエラーは生成しません。

    IGNORE には、特定の値に一致するパーティションが見つからないパーティション化されたテーブルへの挿入でも同様の効果があります。IGNORE を指定しない場合、このような INSERT ステートメントはエラーで中止されます。ただし、INSERT IGNORE が使用されている場合は、一致しない値を含む行に対する挿入操作が暗黙のうちに失敗しますが、一致した行はすべて挿入されます。例については、セクション19.2.2「LIST パーティショニング」を参照してください。

    IGNORE が指定されていない場合は、エラーをトリガーするデータ変換によってステートメントが中止されます。IGNORE を指定すると、無効な値はもっとも近い値に調整されて挿入されます。警告は生成されますが、ステートメントは中止されません。mysql_info() C API 関数を使用すると、テーブルに実際に挿入された行数を確認できます。

  • ON DUPLICATE KEY UPDATE を指定したとき、UNIQUE インデックスまたは PRIMARY KEY に重複した値を発生させる行が挿入された場合は、古い行の UPDATE が実行されます。行ごとの影響を受けた行の値は、その行が新しい行として挿入された場合は 1、既存の行が更新された場合は 2、既存の行がその現在の値に設定された場合は 0 です。mysqld への接続時に CLIENT_FOUND_ROWS フラグを mysql_real_connect() に指定すると、既存の行がその現在の値に設定された場合の影響を受けた行の値は (0 ではなく) 1 になります。セクション13.2.5.3「INSERT ... ON DUPLICATE KEY UPDATE 構文」を参照してください。

テーブルに挿入するには、そのテーブルに対する INSERT 権限が必要です。ON DUPLICATE KEY UPDATE 句が使用されていて、重複キーのために代わりに UPDATE が実行される場合、このステートメントには、更新されるカラムに対する UPDATE 権限が必要です。読み取られるが、変更されないカラムの場合は、SELECT 権限のみが必要です (ON DUPLICATE KEY UPDATE 句にある col_name=expr 割り当ての右側でのみ参照されるカラムの場合など)。

MySQL 5.6.6 より前は、テーブルレベルのロックを採用した MyISAM などのストレージエンジンを使用しているパーティション化されたテーブルに影響を与える INSERT によって、そのテーブルのすべてのパーティションがロックされました。これは、INSERT ... PARTITION ステートメントにも当てはまりました。(これは、行レベルロックを採用した InnoDB などのストレージエンジンでは発生しておらず、現在も発生しません。)MySQL 5.6.6 以降では、MySQL はパーティションロックプルーニングを使用します。これにより、行が挿入されるパーティションだけが実際にロックされるようになります。詳細は、セクション19.6.4「パーティショニングとロック」を参照してください。