如何在 mysql 的游标循环中只发生一次插入
how to have insertion happen only once in a cursor loop in mysql
此过程采用品牌名称并将其与产品中的品牌名称相匹配 table 并创建广告系列。
当我使用产品 table 中不存在的品牌名称的输入调用此过程 BrandNameCampaign 时,它仍在创建活动。我知道这是因为我将插入查询保留在检查 camp_c 游标是否具有空值的循环之外。
但是,如果我将查询放在游标的重复循环中,它会生成一个错误代码:1062 duplicate entry 'x' (x being an int) for key 'campaign.PRIMARY'.
如何修复我的代码,以便在没有 creating/firing 触发器的情况下不会将新广告系列插入 table。我希望它在此过程中工作。
Table代码
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//
一种解决方案是使用:
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
现在为假,因此 insert...select
将插入零行。
此过程采用品牌名称并将其与产品中的品牌名称相匹配 table 并创建广告系列。 当我使用产品 table 中不存在的品牌名称的输入调用此过程 BrandNameCampaign 时,它仍在创建活动。我知道这是因为我将插入查询保留在检查 camp_c 游标是否具有空值的循环之外。 但是,如果我将查询放在游标的重复循环中,它会生成一个错误代码:1062 duplicate entry 'x' (x being an int) for key 'campaign.PRIMARY'.
如何修复我的代码,以便在没有 creating/firing 触发器的情况下不会将新广告系列插入 table。我希望它在此过程中工作。
Table代码
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//
一种解决方案是使用:
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
现在为假,因此 insert...select
将插入零行。