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


12

私が持っているtable1table2MySQLのインチ どちらにも主auto_incrementキーがありますid

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

回答:


13

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

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

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

新しい値を生成したい 場合はtable1できません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」以外の構文はありません。挿入する列名の完全なリストを入力する必要があります。


値として0の挿入を許可/禁止するオプションはありませんか?(2番目の段落について)
Sascha Rambeaud

1
はい、SQL_MODE = NO_AUTO_VALUE_ON_ZERO、それ以外の場合、リテラルのゼロ値をAI列に挿入することはできません。このSQLモードを使用する場合でも、NULLはAIジェネレーターをアクティブにするために機能します。または、列を省略しても機能します。
Bill Karwin 2014年

@BillKarwin、最後の段落について、サブ結果を取得した後select * from table、このサブ結果を操作して最初の列を削除する方法はありませんか?
Pacerier、2015

私が正しく理解していれば場合@Pacerier、あなたが求めているselect *意味することができますselect * except for the first column。答えはいいえだ。select *常にそのテーブルのすべての列を要求します。サブセットが必要な場合は、必要な列を詳しく説明する必要があります。
ビルカーウィン2015

@BillKarwin、うーん、垂直のwhere句を実行するためにテーブルをピボットしてから、たとえばselect*from transpose(select*from(transpose(select*from table where Id=1))where col_name<>Id)それをもっと簡潔にピボットして戻すselect*from table where Id=1 and $col<>Idことを考えていましたが、どう思いますか?
Pacerier 2015

3

選択からの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が新しい行に取得されます。


2
賢いですが、私にとっては、挿入する列名の完全なリストをスペルアウトしたと見なされます。
ビルカーウィン2014年

1
まあそれはmysqlが手動で行うのではなく、自動的にスペルアウトすることです。多数の列を持つテーブルがある場合は、1つ欠落したり、いくつかのスペルミスを防ぐことができます。
カーミル2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.