Задать вопрос
IgorPI
@IgorPI

Как избежать ошибки при вставке?

Коллеги, приветствую!

Генерирую 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');
  • Вопрос задан
  • 47 просмотров
Подписаться 1 Простой 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы