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

Posted

技术标签:

【中文标题】“ORA-00001:违反了唯一约束”,即使使用异常【英文标题】:"ORA-00001: unique constraint violated" even when using an exception 【发布时间】:2013-12-04 12:42:04 【问题描述】:

我的 PL-SQL 代码有问题,因为我有一个将行插入表的 for 循环,问题是有时会尝试插入重复的值,所以我收到 ORA-00001 错误。 我添加了一个例外来避免这种情况,但它似乎不起作用......你能帮帮我吗? :)

这是我的代码(出错的那个):

 if (x = 1) then
         if (proyec(alumno_rec.alumno_codigo, alumno_rec.plan_codigo,   asignatura_rec.asignatura_codigo) is not null) then
            begin
            insert into proyeccion (alumno_codigo, asignatura_codigo, proyeccionestado_codigo) 
                        values (alumno_rec.alumno_codigo, proyec(alumno_rec.alumno_codigo, alumno_rec.plan_codigo, asignatura_rec.asignatura_codigo), 1);
            EXCEPTION 
            WHEN DUP_VAL_ON_INDEX THEN 
               update proyeccion set asignatura_codigo=proyec(alumno_rec.alumno_codigo, alumno_rec.plan_codigo, asignatura_rec.asignatura_codigo) 
               where alumno_codigo=alumno_rec.alumno_codigo;
            end;
         end if; 
      end if;

这是上面提到的功能:

create or replace function proyec(cod_alum alumno.alumno_codigo%type, plan_cod   alumno.plan_codigo%type, cod_asig asignatura.asignatura_codigo%type)
   return number is
asig number;
begin
   select asignatura_codigo
   into asig
   from requisito
   where requisito_codigo=cod_asig and 
         plan_codigo=plan_cod and 
         asignatura_codigo in (select asignatura_codigo from matricula where alumno_codigo=cod_alum);
   return asig;
end;
/

这里是完整的主要代码供参考:

set serveroutput on size 10000
declare
   cursor alum is
      select alumno_codigo, plan_codigo 
      from alumno
      where alumno_codigo in (select alumno_codigo from matricula where alumno_codigo = alumno.alumno_codigo);
   cursor asig is
      select asignatura_codigo
      from asignatura;
   x number;
begin
   for alumno_rec in alum loop
      update alumno set alumno_promedio=prom(alumno_rec.alumno_codigo) where alumno_codigo=alumno_rec.alumno_codigo; 
      update alumno set alumno_semestre=sem(cred(alumno_rec.alumno_codigo)) where alumno_codigo=alumno_rec.alumno_codigo;
      if (perdida(alumno_rec.alumno_codigo)>1) then
         update alumno set alumnoestado_codigo=3 where alumno_codigo=alumno_rec.alumno_codigo;
      end if;
      for asignatura_rec in asig loop
          select alumnoestado_codigo into x from alumno where alumno_codigo=alumno_rec.alumno_codigo;
          if (perdida2(alumno_rec.alumno_codigo, asignatura_rec.asignatura_codigo)=2) then
             update alumno set alumnoestado_codigo=3 where alumno_codigo=alumno_rec.alumno_codigo;
          elsif (perdida2(alumno_rec.alumno_codigo, asignatura_rec.asignatura_codigo)>2) then 
             update alumno set alumnoestado_codigo=4 where alumno_codigo=alumno_rec.alumno_codigo;
          elsif x is null then
             update alumno set alumnoestado_codigo=1 where alumno_codigo=alumno_rec.alumno_codigo;
          end if;
          if (x = 1) then
             if (proyec(alumno_rec.alumno_codigo, alumno_rec.plan_codigo, asignatura_rec.asignatura_codigo) is not null) then
                begin
                insert into proyeccion (alumno_codigo, asignatura_codigo, proyeccionestado_codigo) 
                        values (alumno_rec.alumno_codigo, proyec(alumno_rec.alumno_codigo, alumno_rec.plan_codigo, asignatura_rec.asignatura_codigo), 1);
                EXCEPTION 
                WHEN DUP_VAL_ON_INDEX THEN 
                   update proyeccion set asignatura_codigo=proyec(alumno_rec.alumno_codigo, alumno_rec.plan_codigo, asignatura_rec.asignatura_codigo) 
               where alumno_codigo=alumno_rec.alumno_codigo;
                end;
             end if; 
          end if;
      end loop;
  end loop;
end;
/

【问题讨论】:

也许更新语句会生成 ORA-00001? 就像 Rene 说的 - 检查你在桌子上的所有独特约束。我敢打赌 asignatura_codigo 列在其中之一中,并且您的更新语句打破了约束。 【参考方案1】:

DUP_VAL_ON_INDEX 异常不能直接用在函数中;

根据 Oracle 文档,DUP_VAL_ON_INDEX 异常不会传播

运行异常

在查询中:“因为某些 SQL 函数在内部使用此异常来发出信号

那个

他们是

已完成,如果您在

中引发此异常,则不应依赖该异常被传播

函数是

作为查询的一部分调用。”

【讨论】:

如果你想让它在函数中传播,请声明异常

以上是关于“ORA-00001:违反了唯一约束”,即使使用异常的主要内容,如果未能解决你的问题,请参考以下文章

oracle唯一约束错误信息

具有序列提供的 id 的主键列上的唯一约束违规

leecode第二天-使用异或找出数组中的非重复元素

即使在使用 SingleChildScrollView() 包装 column() 后也无法在小部件上滚动

protobuf-net 可以用来(反)序列化包含异构对象的列表吗?

「LibreOJ β Round #2」计算几何瞎暴力