Коллеги, приветствую!
Генерирую SQL Dump для последующей вставки.
Есть вероятность, что
LAST_INSERT_ID() может оказаться ложным.
То есть, может не принадлежать той самой последней вставке, к которой должен.
Поля защищены ключами
схема следующаяCREATE TABLE `features` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci',
`type` ENUM('enum','bool','text') NOT NULL COMMENT '(DC2Type:enum_feature_type)' COLLATE 'utf8mb4_unicode_ci',
`value` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`organization_id` BIGINT(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `UNIQ_BFC0DC135E237E0632C8A3DE` (`name`, `organization_id`),
INDEX `IDX_BFC0DC1332C8A3DE` (`organization_id`),
INDEX `IDX_BFC0DC135E237E06` (`name`),
CONSTRAINT `FK_BFC0DC1332C8A3DE` FOREIGN KEY (`organization_id`) REFERENCES `organizations` (`id`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=88
;
CREATE TABLE `features_values` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`feature_id` BIGINT(20) NULL DEFAULT NULL,
`name` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci',
PRIMARY KEY (`id`),
UNIQUE INDEX `UNIQ_5C5A47755E237E0660E4B879` (`name`, `feature_id`),
INDEX `IDX_5C5A477560E4B879` (`feature_id`),
INDEX `IDX_5C5A47755E237E06` (`name`),
CONSTRAINT `FK_5C5A477560E4B879` FOREIGN KEY (`feature_id`) REFERENCES `features` (`id`) ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=509
;
Dump
-- begin Этой строки может и не бть и вставка произойдёт (вставка А)
INSERT IGNORE INTO `features` (`name`, `type`, `value`, `organization_id`) VALUES ('Wi-Fi', 'bool', 'true', 309604);
-- end
-- begin А это строка может присутствовать в базе и вставки не будет. (вставка B)
INSERT IGNORE INTO `features` (`name`, `type`, `value`, `organization_id`) VALUES ('услуги', 'enum', NULL, 309604);
SELECT @feature_id := LAST_INSERT_ID(); /* предназначено для B, но есть вероятность, что получу ID от вставки A */
INSERT IGNORE INTO `features_values` (`feature_id`, `name`) VALUES
(@feature_id, 'хирургия'),
(@feature_id, 'эстетическая стоматология'),
(@feature_id, 'эндодонтия'),
(@feature_id, 'имплантология'),
(@feature_id, 'рентгенография'),
(@feature_id, 'ортодонтия'),
(@feature_id, 'челюстно-лицевая хирургия'),
(@feature_id, 'протезирование'),
(@feature_id, 'терапия');
-- end
-- begin
INSERT IGNORE INTO `features` (`name`, `type`, `value`, `organization_id`) VALUES ('Wi-Fi', 'bool', 'true', 309604);
-- end
-- begin
INSERT IGNORE INTO `features` (`name`, `type`, `value`, `organization_id`) VALUES ('оплата картой', 'bool', 'true', 309604);
-- end
Как избежать этой неприятности?
Я обозначил маркеры
-- begin
-- end
Это 1 единица, какого либо запроса.
В идеале, было бы не плохо, если можно было бы проверить, была ли выполнена вставка A, а после вставлять B
-- begin (вставка A)
INSERT IGNORE INTO `features` (`name`, `type`, `value`, `organization_id`) VALUES ('услуги', 'enum', NULL, 309604);
SELECT LAST_INSERT_ID() INTO @feature_id
INSERT IGNORE INTO `features_values` (`feature_id`, `name`) VALUES /* (вставка B) */
(@feature_id, 'хирургия'),
(@feature_id, 'эстетическая стоматология'),
(@feature_id, 'эндодонтия'),
(@feature_id, 'имплантология'),
(@feature_id, 'рентгенография'),
(@feature_id, 'ортодонтия'),
(@feature_id, 'челюстно-лицевая хирургия'),
(@feature_id, 'протезирование'),
(@feature_id, 'терапия');
-- end
Вот пример моих опасений
INSERT INTO `features` (`name`, `organization_id`) VALUES ('Авто', 18);
/* Если не получится вставить, то всё пропало */
INSERT INTO `features` (`name`, `organization_id`) VALUES ('Авто', 19);
SELECT LAST_INSERT_ID() INTO @feature_id;
INSERT INTO `features_values` (`feature_id`, `name`) VALUES
(@feature_id, 'Tesla Model S'),
(@feature_id, 'Tesla Model X'),
(@feature_id, 'Tesla Cybertruck');