INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
INSERT ... SELECT
を使用すると、1 つまたは多数のテーブルから多数の行をテーブルにすばやく挿入できます。例:
INSERT INTO tbl_temp2 (fld_id)
SELECT tbl_temp1.fld_order_id
FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
INSERT ... SELECT
ステートメントには、次の条件が適用されます。
重複キー違反の原因になる行を無視するには、
IGNORE
を指定します。DELAYED
は、INSERT ... SELECT
では無視されます。-
INSERT
ステートメントのターゲットテーブルが、クエリーのSELECT
部分のFROM
句に現れてもかまいません。(これは、一部の古いバージョンの MySQL では不可能でした。)ただし、テーブルに挿入し、さらにサブクエリーで同じテーブルから選択することはできません。テーブルからの選択とそのテーブルへの挿入を同時に行う場合、MySQL は
SELECT
からの行を保持するための一時テーブルを作成してから、それらの行をターゲットテーブルに挿入します。ただし、TEMPORARY
テーブルを同じステートメント内で 2 回参照することはできないため、t
がTEMPORARY
テーブルのときにINSERT INTO t ... SELECT ... FROM t
を使用できない点は引き続き残ります (セクションB.5.7.2「TEMPORARY テーブルに関する問題」を参照してください)。 AUTO_INCREMENT
カラムは、通常どおりに機能します。バイナリログを使用して元のテーブルを確実に再作成できるようにするために、MySQL では、
INSERT ... SELECT
ステートメントでの並列挿入が許可されません。SELECT
とINSERT
が同じテーブルを参照している場合のあいまいなカラム参照の問題を回避するには、SELECT
部分で使用されている各テーブルの一意のエイリアスを指定し、その部分にあるカラム名を適切なエイリアスで修飾します。
MySQL 5.6.2 からは、テーブルの名前に続く PARTITION
オプションでソースまたはターゲットテーブル (またはその両方) のどのパーティションまたはサブパーティション (またはその両方) を使用するかを明示的に選択できます。PARTITION
がこのステートメントの SELECT
部分にあるソーステーブルの名前とともに使用されている場合は、そのパーティションリストで指定されているパーティションまたはサブパーティションの行のみが選択されます。PARTITION
がこのステートメントの INSERT
部分のターゲットテーブルの名前とともに使用されている場合は、選択されたすべての行を、このオプションに続くパーティションリストで指定されているパーティションまたはサブパーティションに挿入できる必要があります。そうでない場合、INSERT ... SELECT
ステートメントは失敗します。詳細および例については、セクション19.5「パーティション選択」を参照してください。
ON DUPLICATE KEY UPDATE
の値の部分では、SELECT
部分で GROUP BY
を使用していないかぎり、ほかのテーブル内のカラムを参照できます。1 つの副作用として、値の部分にある一意でないカラム名を修飾しなければならない点があります。
ORDER BY
句のない SELECT
ステートメントが行を返す順序は特定されていません。つまり、レプリケーションを使用している場合、このような SELECT
がマスターとスレーブ上で行を同じ順序で返す保証はありません。これにより、マスターとスレーブの間で不整合が発生する場合があります。これが発生しないようにするために、レプリケートされる INSERT ... SELECT
ステートメントは常に INSERT ... SELECT ... ORDER BY
として記述するようにしてください。column
column
の選択は、マスターとスレーブの両方で間違いなく行が同じ順序で返されるかぎり問題にはなりません。セクション17.4.1.16「レプリケーションと LIMIT」も参照してください。
この問題のために、MySQL 5.6.4 から、INSERT ... SELECT ON DUPLICATE KEY UPDATE
および INSERT IGNORE ... SELECT
ステートメントには、ステートメントベースのレプリケーションには安全でないというフラグが付けられます。この変更により、このようなステートメントは、ステートメントベースモードを使用しているときはログ内に警告を生成し、MIXED
モードを使用しているときは行ベース形式を使用してログに記録されます。(Bug #11758262、Bug #50439)
セクション17.1.2.1「ステートメントベースおよび行ベースレプリケーションのメリットとデメリット」も参照してください。
MySQL 5.6.6 より前は、テーブルレベルのロックを採用した MyISAM
などのストレージエンジンを使用しているパーティション化されたテーブルに対して機能した INSERT ... SELECT
ステートメントによって、ソースおよびターゲットテーブルのすべてのパーティションがロックされました。(これは、行レベルロックを採用した InnoDB
などのストレージエンジンを使用しているテーブルでは発生しておらず、現在も発生しません。)MySQL 5.6.6 以降では、ターゲットテーブルのすべてのパーティションがロックされますが、ソーステーブルは実際に読み取られたパーティションのみがロックされます。詳細は、セクション19.6.4「パーティショニングとロック」を参照してください。