我试图从PL / SQL中的同一语句中捕获两个不同的异常。
以下是我使用的代码:
create or replace procedure NewCouponGen
IS
v_min number(10) := 1000;
v_max number(10) := 99999;
v_winkel_id varchar2(200);
v_suc number(1,0);
v_new_code number(10);
CURSOR c_winkel IS
SELECT id
FROM WINKEl;
BEGIN
OPEN c_winkel;
LOOP
FETCH c_winkel INTO v_winkel_id;
v_suc := 0;
WHILE v_suc = 0
LOOP
select floor(dbms_random.value(v_min,v_max)) num INTO v_new_code from dual;
INSERT INTO WINKEL_COUPON (WINKEL_ID, COUPON_ID) VALUES (v_winkel_id, v_new_code);
-- CATCH UNQUE EXEPTION
--IF v_winkel_id != UNIQUE THEN v_suc = 1
--IF v_new_code != UNIQUE THEN KEEP ON LOOPING
--IF INSERT IS SUCCES THEN v_suc = 1
END LOOP;
EXIT WHEN c_winkel%notfound;
END LOOP;
CLOSE c_winkel;
END NewCouponGen;
答案 0 :(得分:1)
最简单的事情就是不要打第一个例外。有一个提示忽略重复违规,但这将适用于两个唯一约束,因此它在这里不是很有用。您可以查询是否已存在WINKEL_ID
的记录,只有在没有的情况下才会插入;或者作为单个陈述,您可以使用合并:
create or replace procedure NewCouponGen
IS
v_min number(10) := 1000;
v_max number(10) := 99999;
v_winkel_id varchar2(200);
v_new_code number(10);
CURSOR c_winkel IS
SELECT id
FROM WINKEl;
BEGIN
OPEN c_winkel;
LOOP
FETCH c_winkel INTO v_winkel_id;
EXIT WHEN c_winkel%notfound;
LOOP
BEGIN
v_new_code := floor(dbms_random.value(v_min,v_max));
MERGE INTO WINKEL_COUPON TGT
USING (SELECT v_winkel_id AS WINKEL_ID, v_new_code AS COUPON_ID FROM DUAL) SRC
ON (TGT.WINKEL_ID = SRC.WINKEL_ID)
WHEN NOT MATCHED THEN
INSERT (TGT.WINKEL_ID, TGT.COUPON_ID) VALUES (SRC.WINKEL_ID, SRC.COUPON_ID);
EXCEPTION
WHEN dup_val_on_index THEN
CONTINUE; -- duplicate coupon ID
END;
EXIT; -- merge was skipped because winkel ID exists, or was successful
END LOOP;
END LOOP;
CLOSE c_winkel;
END NewCouponGen;
/
合并只会尝试插入,如果它没有看到WINKEL_ID
已经存在记录,那么您将无法从该列获得唯一的约束违规。如果从COUPON_ID
约束中得到一个,那么包含合并的内部块上的异常处理程序 - 只存在允许捕获异常 - 将再次向您发送循环。
我也完全取出v_suc
旗帜;并在获取后将exit when
子句移动到直接 - 否则您将始终尝试从游标中插入最后一个ID的两个值;并从select .. from dual
中取出上下文切换,因为您可以直接将该随机值分配给变量。
您也不需要v_new_code
变量,您可以在合并中获取值:
MERGE INTO WINKEL_COUPON TGT
USING (SELECT v_winkel_id AS WINKEL_ID,
floor(dbms_random.value(v_min,v_max)) AS COUPON_ID FROM DUAL) SRC
ON (TGT.WINKEL_ID = SRC.WINKEL_ID)
WHEN NOT MATCHED THEN
INSERT (TGT.WINKEL_ID, TGT.COUPON_ID) VALUES (SRC.WINKEL_ID, SRC.COUPON_ID);
答案 1 :(得分:-1)
您可以使用CONTINUE继续循环,并选择EXIT WHEN退出循环
LOOP -- After CONTINUE statement, control resumes here
select floor(dbms_random.value(v_min,v_max)) num INTO v_new_code from dual;
IF (v_new_code =='keep on looping condition') THEN
CONTINUE; --stops current loop and goes on to next iteration
END IF;
INSERT INTO WINKEL_COUPON (WINKEL_ID, COUPON_ID) VALUES (v_winkel_id, v_new_code);
EXIT WHEN v_suc==1; --or other exit conditions
END LOOP;