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


13.2.6.1 INSERT ... SELECT ステートメント

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

value:
    {expr | DEFAULT}

assignment:
    col_name = value

assignment_list:
    assignment [, assignment] ...

INSERT ... SELECT を使用すると、複数のテーブルから選択できる SELECT ステートメントの結果から、テーブルに多数の行をすばやく挿入できます。 例:

INSERT INTO tbl_temp2 (fld_id)
  SELECT tbl_temp1.fld_order_id
  FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;

MySQL 8.0.19 以降、次に示すように、SELECT のかわりに TABLE ステートメントを使用できます:

INSERT INTO ta TABLE tb;

TABLE tb は、SELECT * FROM tb と同等です。 これは、ソーステーブルのすべてのカラムをターゲットテーブルに挿入し、WHERE によるフィルタリングが不要な場合に便利です。 また、TABLE の行は ORDER BY を使用して 1 つ以上のカラムで順序付けでき、挿入される行数は LIMIT 句を使用して制限できます。 詳細は、セクション13.2.12「TABLE ステートメント」を参照してください。

次の条件は、INSERT ... SELECT ステートメント、および特に明記されている場合を除き、INSERT ... TABLE にも適用されます:

  • 重複キー違反の原因になる行を無視するには、IGNORE を指定します。

  • INSERT ステートメントのターゲットテーブルは、クエリーの SELECT 部分の FROM 句に、または TABLE によって指定されたテーブルとして指定できます。 ただし、テーブルに挿入し、さらにサブクエリーで同じテーブルから選択することはできません。

    同じテーブルから選択して同じテーブルに挿入する場合、MySQL は、SELECT の行を保持する内部一時テーブルを作成し、それらの行をターゲットテーブルに挿入します。 ただし、同じステートメントで TEMPORARY テーブルを 2 回参照することはできないため、tTEMPORARY テーブルの場合は INSERT INTO t ... SELECT ... FROM t を使用できません。 同じ理由で、t が一時テーブルの場合は INSERT INTO t ... TABLE t を使用できません。 セクション8.4.4「MySQL での内部一時テーブルの使用」およびセクションB.3.6.2「TEMPORARY テーブルに関する問題」を参照してください。

  • AUTO_INCREMENT カラムは、通常どおりに機能します。

  • バイナリログを使用して元のテーブルを再作成できるようにするために、MySQL では INSERT ... SELECT または INSERT ... TABLE ステートメントの同時挿入が許可されていません (セクション8.11.3「同時挿入」 を参照)。

  • SELECTINSERT が同じテーブルを参照している場合のあいまいなカラム参照の問題を回避するには、SELECT 部分で使用されている各テーブルの一意のエイリアスを指定し、その部分にあるカラム名を適切なエイリアスで修飾します。

    TABLE ステートメントはエイリアスをサポートしていません。

ソーステーブルまたはターゲットテーブル (あるいはその両方) のどのパーティションまたはサブパーティション (あるいはその両方) を、テーブルの名前に続く PARTITION オプションとともに使用するかを明示的に選択できます。 PARTITION がこのステートメントの SELECT 部分にあるソーステーブルの名前とともに使用されている場合は、そのパーティションリストで指定されているパーティションまたはサブパーティションの行のみが選択されます。 PARTITION をステートメントの INSERT 部分のターゲットテーブルの名前とともに使用する場合、選択したすべての行を、オプションの後のパーティションリストで指定されたパーティションまたはサブパーティションに挿入できる必要があります。 それ以外の場合、INSERT ... SELECT ステートメントは失敗します。 詳細および例については、セクション24.5「パーティション選択」を参照してください。

TABLE は、PARTITION オプションをサポートしていません。

INSERT ... SELECT ステートメントの場合、ON DUPLICATE KEY UPDATE 句で SELECT カラムを参照できる条件については、セクション13.2.6.2「INSERT ... ON DUPLICATE KEY UPDATE ステートメント」 を参照してください。 これは、INSERT ... TABLE でも機能します。

ORDER BY 句のない SELECT ステートメントまたは TABLE ステートメントが行を戻す順序は、非決定的です。 つまり、レプリケーションを使用している場合、このような SELECT がソースとスレーブで同じ順序で行を返すことは保証されないため、それらの間に不整合が生じる可能性があります。 これが発生しないようにするには、ソースとレプリカで同じ行順序を生成する ORDER BY 句を使用して、レプリケートされる INSERT ... SELECT ステートメントまたは INSERT ... TABLE ステートメントを常に記述します。 セクション17.5.1.18「レプリケーションと LIMIT」も参照してください。

この問題のため、INSERT ... SELECT ON DUPLICATE KEY UPDATE および INSERT IGNORE ... SELECT ステートメントには、ステートメントベースレプリケーションに対して安全でないというフラグが付けられます。 このようなステートメントは、ステートメントベースのモードの使用時にエラーログに警告を生成し、MIXED モードの使用時に行ベースの形式を使用してバイナリログに書き込まれます。 (Bug #11758262、Bug #50439)

セクション17.2.1.1「ステートメントベースおよび行ベースレプリケーションのメリットとデメリット」も参照してください。


関連キーワード:  ステートメント, TABLE, CREATE, テーブル, INSERT, DROP, サブクエリー, 参照, FUNCTION, カラム