Une instruction INSERT dans SQL peut uniquement être insérée dans une table et ne peut répertorier que les colonnes de cette table. Vous ne pouvez pas inclure votre colonne source
dans l'instruction INSERT, car ce n'est pas une colonne de la table alias
. Les déclencheurs peuvent vous permettre d'insérer dans une table secondaire, mais le déclencheur doit connaître la valeur à insérer. Dans ce cas, le déclencheur n'a aucun moyen d'obtenir la valeur pour source
.
Cette tâche est beaucoup plus facile à faire avec deux instructions INSERT.
INSERT IGNORE INTO alias SET author_id = ?, alias = ?;
INSERT INTO alias_source ...
Mais vous avez un problème parce que votre table alias
a une colonne auto-incrément id
, mais cette colonne ne fait pas partie d'une clé. Dans InnoDB, vous devez faire de la colonne auto-incrément la première colonne d'une clé.
Votre table alias_source
a une clé étrangère faisant référence à alias(id)
mais ce n'est pas autorisé. Une clé étrangère doit référencer une clé de la table parent. Il doit référencer la clé unique ou primaire et référencer toutes les colonnes de la clé (sinon, vous obtenez une ligne dans une table enfant qui peut faire référence à plusieurs lignes dans la table parent, ce qui n'a aucun sens).
Si vous souhaitez utiliser une colonne à incrémentation automatique pour votre table alias
, définissez-la comme clé primaire et attribuez une contrainte UNIQUE secondaire aux autres colonnes.
CREATE TABLE alias (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
authors_id INT NOT NULL,
alias VARCHAR(150) NOT NULL,
UNIQUE KEY (author_id,alias));
Ensuite, interrogez le id
après l'insertion. Si vous avez inséré une nouvelle ligne, ou si la ligne existait déjà, vous obtiendrez le id
pour la ligne avec l'auteur et l'alias choisis.
INSERT IGNORE INTO alias SET author_id = ?, alias = ?;
SELECT id FROM alias WHERE author_id = ? AND alias = ? INTO @id;
INSERT INTO alias_source SET alias_id = @id, source = ?;
Re votre question dans le commentaire suivi:
Bonne idée, mais il ne fonctionne pas comme vous pensez. Vous pouvez faire un ensemble factice de id=id
et définir une variable de session comme effet secondaire.
mysql> insert into alias set author_id=1, alias='alias'
on duplicate key update id = @id:=id;
mysql> select @id;
+------+
| @id |
+------+
| NULL |
+------+
Mais pourquoi n'a-t-il pas défini la variable de session sur l'ID?Parce que cet insert était pas une copie, il s'agissait d'une nouvelle ligne. La valeur id
n'avait donc pas encore été générée par auto-incrémentation au moment où l'IODKU était exécutée.
Si vous faites ensuite la même IODKU pour une ligne qui est un double, la valeur id
a déjà été ajouté à la ligne, de sorte que vous obtenez la valeur dans l'effet secondaire:
mysql> insert into alias set author_id=1, alias='alias'
on duplicate key update id = @id:=id;
mysql> select @id;
+------+
| @id |
+------+
| 1 |
+------+
Donc, vous devrez écrire le code de l'application de toute façon pour vérifier si @id
est NULL ou non, et faire une requête SELECT id
si @id
est NULL.
Cela semble plus compliqué que de simplement faire le SELECT id
comme une action standard après le INSERT IGNORE
comme je l'ai montré ci-dessus.
Merci pour la réponse @ facture! Mais est-il possible d'utiliser ON DUPLICATE KEY et de stocker l'ID dupliqué dans @id? Passer la deuxième déclaration? –