#mysql #mysql-workbench
Вопрос:
Эта процедура берет название бренда, сопоставляет его с названиями брендов в таблице продуктов и создает кампанию. Когда я вызываю эту процедуру BrandNameCampaign с вводом имени бренда, которого НЕТ в таблице продуктов, она все еще создает кампанию. Я знаю, что это потому, что я сохранил запрос вставки вне цикла, где он проверяет, имеет ли курсор camp_c нулевые значения или нет. Однако, если я помещу запрос в цикл повтора курсора, он выдаст код ошибки: 1062 повторяющаяся запись » x «(x-это int) для кампании «ключ».ПЕРВИЧНЫЙ».
Как исправить свой код, чтобы новая кампания не вставлялась в таблицу без создания/запуска триггера? Я хочу, чтобы это работало в рамках этой процедуры.
Код таблицы
create table Product ( ProductID int not null, ProductType varchar (20) not null, PackageType varchar(20) not null, YearProduced int not null, Price float not null, Brand varchar(255) not null, PRIMARY KEY (ProductID) ) create table Campaign ( CampaignID int not null, CampaignStartDate date not null, CampaignEndDate date, PRIMARY KEY (CampaignID) ) create table DiscountDetails ( ProductID int not null, CampaignID int not null, MembershipLevel varchar(20) not null, Discount int not null, primary key (ProductID, CampaignID, MembershipLevel), foreign key (ProductID) references Product (ProductID), foreign key (CampaignID) references Campaign (CampaignID) )
Процессуальный кодекс
create procedure BrandNameCampaign (in brandname varchar(50)) begin declare v_finished int default 0; declare prod_id int; declare newcampid int; declare camp_brand varchar(255); declare camp_c cursor for select productid, brand from product where brandname = brand order by price desc limit 5; declare continue handler for not found set v_finished = 1; SELECT MAX(CampaignID) INTO newcampid FROM campaign; set newcampid = 1 newcampid; insert into `Campaign`(`CampaignID`,`CampaignStartDate`,`CampaignEndDate`) values (newcampid,date_add(curdate(), interval 4 week), date_add( curdate(), interval 8 week)); -- working with cursor open camp_c; repeat fetch camp_c into prod_id, camp_brand; if not (v_finished = 1) then insert into discountdetails values (prod_id, newcampid, 'S', 20); insert into discountdetails values (prod_id, newcampid, 'G', 30); insert into discountdetails values (prod_id, newcampid, 'P', 40); end if; until v_finished end repeat; close camp_c; end//
Ответ №1:
Одним из решений было бы использовать:
insert ignore into `Campaign` ...
ignore
Средства не генерируют ошибку, если вставка приводит к дубликату ключа или другому типу ошибки.
Другим решением может быть использование логической переменной:
declare v_do_insert tinyint(1) default true; ... repeat insert into `Campaign`(`CampaignID`,`CampaignStartDate`,`CampaignEndDate`) select newcampid, date_add(curdate(), interval 4 week), date_add( curdate(), interval 8 week) from dual where v_do_insert=true; set v_do_insert = false; ... until v_finished end repeat;
В этом примере значение insert...select
будет вставлять одну строку в первый раз через цикл, но затем на последующих итерациях цикла v_do_insert
теперь равно false, поэтому insert...select
будет вставляться ноль строк.
Комментарии:
1. оба варианта работают, хотя я чувствую, что последний более безопасен, чем вариант игнорировать. Можете ли вы высказать некоторые соображения относительно опции игнорировать.
2. Один из недостатков
ignore
заключается в том, что он игнорирует другие типы ошибок, кроме повторяющихся ключей.