Contrairement au moteur MySQL Myisam, le moteur InnoDb ne peut pas gérer lorsqu'une colonne d'une clé primaire composite est déclarée AUTO_INCREMENT
. Par exemple, considérons le tableau suivant:
CREATE TABLE `ExampleTable` (
`KeyPartA` mediumint(8) unsigned NOT NULL,
`KeyPartB` smallint(5) unsigned NOT NULL,
`Data` text NOT NULL,
PRIMARY KEY (`KeyPartA`,`KeyPartB`)
) ENGINE=InnoDB;
Maintenant simuler AUTO_INCREMENT
, J'ai appris, il est possible de créer le déclencheur suivant
DELIMITER $$
CREATE TRIGGER ExampleAutoIncrement BEFORE INSERT ON ExampleTable
FOR EACH ROW BEGIN
SET NEW.KeyPartB = (
SELECT IFNULL(MAX(KeyPartB), 0) + 1
FROM ExampleTable
WHERE KeyPartA = NEW.KeyPartA
);
END $$
DELIMITER ;
Maintenant, les insertions fonctionnent correctement, générant des valeurs auto-incrémentées. Malheureusement, je ne peux pas penser à un moyen judicieux d'obtenir la valeur clé nouvellement créée.
Ni LAST_INSERT_ID()
_ NOR CANAL DE COLLABLE DE C, car il n'y a pas de colonne AUTO_INCREMENT
. Il n'est également pas possible de définir la valeur avec LAST_INSERT_ID(IFNULL(MAX(KeyPartB), 0) + 1)
à l'intérieur de la gâchette ExampleAutoIncrement
, car MySQL réinitialise la valeur après la finition de la gâchette.
La seule façon dont j'ai pensé était de délivrer une SELECT MAX(KeyPartB) FROM ExampleTable WHERE KeyPartA = ?
après un insert, qui défait tout le but de la gâchette. C'est à dire. Je pourrais aussi bien faire cela avant l'insertion et l'incrémentation manuellement.
Existe-t-il un moyen d'obtenir la valeur clé incrémentée de la gâchette ou d'un autre moyen de simuler le AUTO_INCREMENT
Je veux?
Ma solution est dans Migration de Myisam à Innodb . Ça va quelque chose comme:
BEGIN;
SELECT @id := IFNULL(MAX(id),0) + 1 FROM foo WHERE other = 123 FOR UPDATE;
INSERT INTO foo
(other, id, ...)
VALUES
(123, @id, ...);
COMMIT;
Avoir une transaction est obligatoire pour empêcher un autre thread de saisir le même identifiant.