web-dev-qa-db-ja.com

auto_incrementキーはINSERTでどのように処理されますか(SELECT * FROM ...)

MySQLに_table1_と_table2_があります。どちらにも基本的な_auto_increment_キーidがあります。

テーブルスキーマが一致し、私がINSERT INTO table1 (SELECT * FROM table2)を実行すると、_table1_に挿入された新しい行に関して何が起こりますか? _table1_の行に同じidがある場合、古いid値を保持し、競合を生成しますか? auto_incrementによって新しい値が生成されますか?ストレージエンジンまたはロックに依存しますか?

13
Thomas Johnson

自動インクリメント列に挿入して値を指定できます。これは問題ありません。自動インクリメントジェネレーターをオーバーライドするだけです。

NULLまたは0またはDEFAULTの値を挿入しようとした場合、またはINSERTステートメントの列から自動インクリメント列を省略した場合、これにより自動インクリメントジェネレーターがアクティブになります。

したがって、INSERT INTO table1 SELECT * FROM table2で問題ありません(ちなみに、括弧は必要ありません)。つまり、table2のid値はそのままコピーされ、table1notで新しい値を生成します。

wanttable1を使用して新しい値を生成する場合、SELECT *は実行できません。 id列にnullまたは0を使用します。

INSERT INTO table1 SELECT 0, col1, col2, col3, ... FROM table2;

または、INSERTステートメントの列リストとSELECTステートメントの選択リストの両方から列を省略します。

-- No id in either case:
INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3, ... FROM table2;

質問する前に、SQLには「select * for one column」以外の構文はありません。挿入する列名の完全なリストを入力する必要があります。

13
Bill Karwin

選択からのIDは、テーブルに挿入されたものと同じ値になります。既存の行を複製しようとすると、エラーになります。

Bill Karwin:質問する前に、SQLには「select * for one column」以外の構文はありません。

これはいくつかの創造性で達成できます:

SET @sql = CONCAT('INSERT INTO <table> SELECT null, 
    ', (SELECT GROUP_CONCAT(COLUMN_NAME) 
    FROM information_schema.columns 
    WHERE table_schema = '<database>' 
    AND table_name = '<table>' 
    AND column_name NOT IN ('id')), ' 
from <table> WHERE id = <id>');  

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

これにより、選択された行のIDではなく、自動増分されたIDが新しい行に取得されます。

3
curmil