web-dev-qa-db-fra.com

Comment les clés auto_increment sont-elles gérées dans INSERT (SELECT * FROM ...)

J'ai table1 Et table2 Dans MySQL. Les deux ont une clé primaire auto_incrementid.

Si les schémas de table correspondent et que je fais INSERT INTO table1 (SELECT * FROM table2) que se passe-t-il en ce qui concerne les nouvelles lignes insérées dans table1? Gardent-ils leurs anciennes valeurs id et génèrent-ils des conflits lorsqu'une ligne de table1 A la même id? Les nouvelles valeurs sont-elles générées par auto_increment? Cela dépend-il du moteur de stockage ou du verrouillage?

13
Thomas Johnson

Vous pouvez insérer dans une colonne à incrémentation automatique et spécifier une valeur. C'est bon; il remplace simplement le générateur d'incrémentation automatique.

Si vous essayez d'insérer une valeur NULL ou 0 ou DEFAULT, ou si vous omettez la colonne d'incrémentation automatique des colonnes de votre instruction INSERT, cela active le générateur d'incrémentation automatique.

Donc, c'est bien de INSERT INTO table1 SELECT * FROM table2 (au fait, vous n'avez pas besoin des parenthèses). Cela signifie que les valeurs id dans table2 sera copié mot pour mot et table1 va pas générer de nouvelles valeurs.

Si vous vouleztable1 pour générer de nouvelles valeurs, vous ne pouvez pas faire SELECT *. Soit vous utilisez null ou 0 pour la colonne id:

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

Sinon, vous omettez la colonne de la liste des colonnes de l'instruction INSERT et de la liste de sélection de l'instruction SELECT:

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

Avant de demander, il n'y a pas de syntaxe en SQL pour "sélectionner * sauf pour une colonne". Vous devez préciser la liste complète des noms de colonnes que vous souhaitez insérer.

13
Bill Karwin

L'identifiant de la sélection sera la même valeur insérée dans le tableau. Cela entraînera une erreur si vous essayez de dupliquer des lignes existantes.

Bill Karwin: Avant de demander, il n'y a pas de syntaxe en SQL pour "sélectionner * sauf pour une colonne".

Cela peut être réalisé avec un peu de créativité:

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;

Ainsi, la nouvelle ligne recevra un identifiant incrémenté automatiquement au lieu de l'identifiant de la ligne sélectionnée.

3
curmil