MySQL 8.0 リファレンスマニュアル


13.2.6 INSERT ステートメント

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [(col_name [, col_name] ...)]
    { {VALUES | VALUE} (value_list) [, (value_list)] ...
      |
      VALUES row_constructor_list
    }
    [AS row_alias[(col_alias [, col_alias] ...)]]
    [ON DUPLICATE KEY UPDATE assignment_list]

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [AS row_alias[(col_alias [, col_alias] ...)]]
    SET assignment_list
    [ON DUPLICATE KEY UPDATE assignment_list]

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [(col_name [, col_name] ...)]
    [AS row_alias[(col_alias [, col_alias] ...)]]
    {SELECT ... | TABLE table_name}
    [ON DUPLICATE KEY UPDATE assignment_list]

value:
    {expr | DEFAULT}

value_list:
    value [, value] ...

row_constructor_list:
    ROW(value_list)[, ROW(value_list)][, ...]

assignment:
    col_name = [row_alias.]value

assignment_list:
    assignment [, assignment] ...

INSERT は、既存のテーブルに新しい行を挿入します。 INSERT ... VALUESINSERT ... VALUES ROW() および INSERT ... SET 形式のステートメントは、明示的に指定された値に基づいて行を挿入します。 INSERT ... SELECT 形式は、別の 1 つまたは複数のテーブルから選択された行を挿入します。 MySQL 8.0.19 以降で INSERT ... TABLE を使用して、単一のテーブルから行を挿入することもできます。 INSERTON DUPLICATE KEY UPDATE 句を使用すると、行が挿入されて UNIQUE インデックスまたは PRIMARY KEY で値が重複する場合に、既存の行を更新できます。 MySQL 8.0.19 以降では、1 つ以上のオプションのカラムアライスを持つ行エイリアスを ON DUPLICATE KEY UPDATE で使用して、挿入する行を参照できます。

INSERT ... SELECT および INSERT ... ON DUPLICATE KEY UPDATE の詳細は、セクション13.2.6.1「INSERT ... SELECT ステートメント」 および セクション13.2.6.2「INSERT ... ON DUPLICATE KEY UPDATE ステートメント」 を参照してください。

MySQL 8.0 では、DELAYED キーワードは受け入れられますが、サーバーでは無視されます。 この理由については、セクション13.2.6.3「INSERT DELAYED ステートメント」 を参照してください。

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

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

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

  • テーブル名の後にカンマ区切りのカラム名のカッコ付きリストを指定します。 この場合、各名前付きカラムの値は、VALUES リスト、VALUES ROW() リストまたは SELECT ステートメントで指定する必要があります。 INSERT TABLE フォームの場合、ソーステーブルのカラム数は挿入されるカラム数と一致する必要があります。

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

  • SET 句は、各カラムに割り当てる値とともに、カラムを名前で明示的に指定します。

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

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

    厳密な SQL モードが有効になっている場合、デフォルト値を持たないすべてのカラムに明示的な値が指定されていないと、INSERT ステートメントはエラーを生成します。 セクション5.1.11「サーバー SQL モード」を参照してください。

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

    INSERT INTO tbl_name () VALUES();

    厳密モードが有効になっていない場合、MySQL では、デフォルトが明示的に定義されていないカラムに暗黙的なデフォルト値が使用されます。 厳密モードが有効な場合、いずれかのカラムにデフォルト値がないとエラーが発生します。

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

  • 生成されたカラムが明示的ににに挿入される場合、許可される値は DEFAULT のみです。 生成されるカラムの詳細は、セクション13.1.20.8「CREATE TABLE および生成されるカラム」 を参照してください。

  • 式では、DEFAULT(col_name) を使用してカラム col_name のデフォルト値を生成できます。

  • カラム値を提供する式 expr の型変換は、式のデータ型がカラムのデータ型と一致しない場合に発生することがあります。 特定の値を変換すると、カラムタイプに応じて異なる値が挿入される可能性があります。 たとえば、文字列'1999.0e-2'INT, FLOAT, DECIMAL(10,6) に挿入したり、YEAR カラムを挿入すると、値 1999, 19.9921, 19.992100 または 1999 がそれぞれ挿入されます。 文字列から数値への変換では、文字列の初期部分のみが有効な整数または年とみなされる可能性があるため、INT および YEAR カラムに格納される値は 1999 です。 FLOAT および DECIMAL カラムの場合、文字列から数値への変換では、文字列全体が有効な数値とみなされます。

  • 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);

    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);

各値リストには、行ごとに挿入されるのと同じ数の値が含まれている必要があります。 次のステートメントは、それぞれ 3 つの値のリストではなく、9 つの値のリストが 1 つ含まれているため、無効です:

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

このコンテキストでは、VALUEVALUES のシノニムです。 値リストの数やリスト当たりの値の数については何も意味しません。 リストごとの値の数に関係なく、単一の値リストまたは複数のリストのいずれかを使用できます。

VALUES ROW() 構文を使用する INSERT ステートメントでは、複数の行を挿入することもできます。 この場合、各値リストは、次のように ROW() (行コンストラクタ) 内に含まれている必要があります:

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

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

複数の値リスト、INSERT ... SELECT または INSERT ... TABLEINSERT ... VALUES または INSERT ... VALUES ROW() を使用する場合、このステートメントは次の形式で情報文字列を返します:

Records: N1 Duplicates: N2 Warnings: N3

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

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 の値に設定されます。

  • AUTO_INCREMENT のカラム値を含む INSERT の例は、セクション3.6.9「AUTO_INCREMENT の使用」 を参照してください。

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

    注記

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

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

  • LOW_PRIORITY 修飾子を使用すると、ほかのクライアントがテーブルから読み取ることがなくなるまで、INSERT の実行が遅延されます。 これには、既存のクライアントが読み取っている間や、INSERT LOW_PRIORITY ステートメントが待機している間に読み取りを開始したほかのクライアントが含まれます。 したがって、INSERT LOW_PRIORITY ステートメントを発行するクライアントが非常に長い時間待機する可能性があります。

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

    注記

    同時挿入が無効になるため、LOW_PRIORITY は通常、MyISAM テーブルでは使用しないでください。 セクション8.11.3「同時挿入」を参照してください。

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

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

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

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

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

    詳細は、IGNORE がステートメントの実行に与える影響を参照してください。

    古い行を上書きするには、INSERT の代わりに REPLACE を使用できます。 REPLACE は、古い行を複製する一意のキー値を含む新しい行の処理における INSERT IGNORE の対応する機能です: 新しい行は、破棄されるのではなく、古い行を置き換えます。 セクション13.2.9「REPLACE ステートメント」を参照してください。

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

  • INSERT DELAYED は MySQL 5.6 で非推奨となり、最終的な削除がスケジュールされています。 MySQL 8.0 では、DELAYED 修飾子は受け入れられますが無視されます。 代わりに INSERT (DELAYED を付けない) を使用してください。 セクション13.2.6.3「INSERT DELAYED ステートメント」を参照してください。


関連キーワード:  ステートメント, INSERT, カラム, 挿入, CREATE, TABLE, テーブル, col, リスト, VALUES