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


13

J'ai table1et table2dans MySQL. Les deux ont une auto_incrementclé primaire id.

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

Réponses:


13

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, ça va INSERT INTO table1 SELECT * FROM table2(au fait, vous n'avez pas besoin des parenthèses). Cela signifie que les valeurs id dans table2recopie tel quel, et table1ne pas générer de nouvelles valeurs.

Si vous souhaitez table1 générer de nouvelles valeurs, vous ne pouvez pas le 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.


N'y a-t-il pas une option qui autorise / interdit l'insertion de 0 comme valeur? (Concernant votre 2ème paragraphe)
Sascha Rambeaud

1
Oui, SQL_MODE = NO_AUTO_VALUE_ON_ZERO , sinon nous ne pourrions jamais insérer une valeur zéro littérale dans une colonne AI. Si vous utilisez ce mode SQL, NULL fonctionne toujours pour activer le générateur AI, ou omettre la colonne fonctionne également.
Bill Karwin

@BillKarwin, Concernant votre dernier paragraphe, après avoir obtenu le sous-résultat select * from table, n'y a-t-il aucun moyen d'opérer sur ce sous-résultat pour supprimer sa première colonne?
Pacerier

@Pacerier, si je comprends bien, vous demandez si select *peut signifier select * except for the first column. La réponse est non. select *demande toujours toutes les colonnes de cette table. Si vous voulez un sous-ensemble, vous devez épeler les colonnes souhaitées.
Bill Karwin

@BillKarwin, Hmm, je pensais faire pivoter le tableau pour faire des clauses where verticales, puis le faire pivoter par exemple, select*from transpose(select*from(transpose(select*from table where Id=1))where col_name<>Id)ou peut-être plus succinctement select*from table where Id=1 and $col<>Id, qu'en pensez-vous?
Pacerier

3

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.


2
Intelligent, mais pour moi, cela compte comme énonçant la liste complète des noms de colonnes que vous souhaitez insérer.
Bill Karwin

1
Eh bien, mysql l'énonce automatiquement par rapport à le faire manuellement. Si vous avez des tableaux avec beaucoup de colonnes, cela vous empêchera d'en manquer un ou d'en mal orthographier quelques-uns.
curmil
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.