Если все значения cascos
равны нулю для начала, то обновления во втором l oop будут перезаписывать изменения, сделанные в первом l oop. Быстрое решение состоит в том, чтобы открыть c2
после завершения первого l oop, а не перед ним.
Однако вы можете упростить код следующим образом:
begin
for r in (
select p.cod_pais
from pais p
join pertenece_a pe on pe.cod_pais = p.cod_pais
join organizacion o on o.cod_organizacion = pe.cod_organizacion
where o.siglas = 'ONU'
and nvl(p.cascos,'?') <> 'S'
for update
)
loop
update pais set cascos = 'S'
where cod_pais = r.cod_pais;
end loop;
update pais set cascos = 'N' where cascos is null;
end;
A дальнейший рефакторинг будет состоять в том, чтобы переписать все как один update
или merge
, и не иметь никакой явной обработки курсора или циклов. Это также было бы более эффективно, потому что один оператор SQL лучше, чем один в строке, и вы могли бы избежать двух проходов через pais
, хотя, возможно, если это очень маленькая таблица, это не имеет большого значения.
Кстати, вам не нужно проверять IF NOT C1%ISOPEN
, потому что вы только что объявили c1
и не открыли его, поэтому он не может быть открыт. Также хорошей практикой является использование явного синтаксиса соединения в стиле ANSI, поскольку сложнее пропустить условия соединения.
Кроме того, вы должны использовать стандартный тип строки varchar2
для всех символьных столбцов и никогда char
. Распространенной ошибкой считается, что char
имеет какое-то особое преимущество для коротких значений, но это не так, а использование нестандартных типов приводит только к ошибкам.