处理唯一约束错误并尝试使用循环自动生成唯一值最多 n 次

Posted

技术标签:

【中文标题】处理唯一约束错误并尝试使用循环自动生成唯一值最多 n 次【英文标题】:Handling unique constraint error and trying to auto generate a unique value upto n times using a loop 【发布时间】:2018-09-06 23:53:28 【问题描述】:

我正在尝试将自动生成的值插入到表中。如果存在唯一约束错误,我想获取一个新值并将最新值插入表中。我想在抛出唯一约束错误之前尝试生成唯一值最多 10 次。

这是我目前所拥有的。

BEGIN
    autoGenValue := x
FOR i in 1..10 LOOP
    BEGIN
      INSERT INTO mainTbl(A,
                   B, 
                   C)
      VALUES(autoGenValue,
               b,
               c ) 
    EXCEPTION
          WHEN DUP_VAL_ON_INDEX
            THEN
                SELECT lpad(NVL(MAX(SUBSTR(A, -2)), '00')+1,4,'0')
                INTO maxSeq
                FROM RecvTbl

                SELECT car_id||maxSeq
                INTO autoGenValue 
                FROM DUAL;

         WHEN OTHERS THEN
             EXIT;          
     END;
   END LOOP;

    UPDATE RecvTbl
         SET A = autoGenValue 
         WHERE A = x;  
END;
COMMIT;      

x 是最初计算的自动生成值,我尝试将其插入mainTbl。如果存在唯一约束错误,我将遵循一些必需的逻辑(此处简化)来获取所需的唯一值。我尝试了 10 次(如果需要)。当没有唯一约束错误时退出并更新recvTbl 的值,因为我需要它以供将来计算。

通过我的代码,我注意到在插入mainTbl 后该值正在递增,即使没有唯一约束错误并且插入recvTbl 中的值是递增值而不是@ 中的值987654327@.

任何想法我做错了什么?

【问题讨论】:

你真正做错的是没有使用序列。这可能是一个有趣的练习,但这不是你应该投入生产的东西。它无法扩展,也无法在多用户环境中工作。 我没有使用序列,因为用于生成 autoGenValue 的 car_id 前缀每天都在变化。并且 max seq 每天从 0001 开始。 car_id 对于两种不同的格式也有两种不同的类型,但生成的所有 ID 都放在同一个表中。考虑到我选择这种方式的一切。我在这里提出问题时简化了所有逻辑。 那你应该使用代码控制表。 【参考方案1】:

问题是你没有成功退出.....

如果存在除 DUP_VAL_ON_INDEX 以外的任何错误,则退出循环,但如果插入成功,则继续循环。

所以下一次循环时你会得到一个 DUP_VAL_ON_INDEX 错误并递增。

您可以使用类似下面的内容(未经测试)来设置成功变量,然后在它为真时立即退出循环。

BEGIN
autoGenValue := x;
v_success := false;
FOR i in 1..10 LOOP
    BEGIN
      INSERT INTO mainTbl(A,
                   B, 
                   C)
      VALUES(autoGenValue,
               b,
               c ) ;
      v_success := true;
    EXCEPTION
          WHEN DUP_VAL_ON_INDEX
            THEN
                SELECT lpad(NVL(MAX(SUBSTR(A, -2)), '00')+1,4,'0')
                INTO maxSeq
                FROM RecvTbl

                SELECT car_id||maxSeq
                INTO autoGenValue 
                FROM DUAL;

     WHEN OTHERS THEN
     EXIT;          
     END;
     if v_success = true then
       exit;
     end if;
   END LOOP;

    UPDATE RecvTbl
         SET A = autoGenValue 
         WHERE A = x;  
END;
COMMIT;      

【讨论】:

是的,问题是没有 EXIT 成功。我的印象是“当其他人”会包括其他例外情况。为什么你认为它在第二次迭代后退出了循环?我注意到 RecvTbl 中的值只是 MainTbl 中值的 +1。我希望它在 10 次迭代后退出,因此该值应该是 MainTbl 中的值的 +10。

以上是关于处理唯一约束错误并尝试使用循环自动生成唯一值最多 n 次的主要内容,如果未能解决你的问题,请参考以下文章

“ORA-00001:违反了唯一约束”,即使使用异常

Golang:重复键值违反唯一约束

MySQL笔记2.4表的约束,2.5设置表的字段值自动增加

oracle唯一约束错误信息

尝试向 MySQL 中的 table.column 添加唯一约束时出现重复条目​​错误

oracle数据导入时,提示违反唯一约束性?