Вместо того, чтобы удалять один из дублирующих кодов, вы создаете третий курс с тем же кодом и пытаетесь переместить всех студентов на любом из старых курсов на новый. Ошибка предполагает, что у вас есть студенты, которые уже зачислены на оба старых курса.
Ваш запрос цикла курсора:
SELECT *
FROM course
WHERE code = v_course_code AND id != new_course_id
Он найдет все записи о соединении для и старых версий кода, а затем обновление установит все из этих записей о соединении в тот же новый идентификатор.
Если есть какие-либо учащиеся, перечисленные с обоими старыми идентификаторами для кода - что будет разрешено вашим составным уникальным ключом - тогда они оба будут обновлены до того же нового идентификатора.
Скажем, курсы, на которые вы смотрите, [обновлены для вашего примера кода]:
ID CODE
-- ----
1 C_13
2 C_13
и у вас есть записи о соединении для студентов обоих курсов, например:
ID_STUDENT ID_COURSE
---------- ---------
1 1
1 2
Вы создаете новый курс:
ID CODE
-- ----
3 C_13
Ваш цикл курсора ищет code = 'ABC' and ID != 3
, который находит идентификаторы 1 и 2. Итак, на первой итерации цикла up обновите строки с идентификатором 1, так что теперь у вас есть:
ID_STUDENT ID_COURSE
---------- ---------
1 3
1 2
Затем во второй итерации вы пытаетесь обновить строки с идентификатором 2, что попытается произвести:
ID_STUDENT ID_COURSE
---------- ---------
1 3
1 3
, который нарушит уникальное ограничение - отсюда и ошибка.
Возможно, вы вообще не хотите создавать новый курс, но в любом случае вам нужно удалить дубликаты записей из student_course
, то есть строк, которые станут дубликатами при обновлении. В основном вам нужно найти студентов с записями для обоих существующих идентификаторов курса и удалить любой из них. Если вам все равно, что это будет делать:
delete from student_course sc1
where id_course in (
select id
from course
where code = 'C_13'
)
and exists (
select null
from student_course sc2
join course c on c.id = sc.id_course
where sc2.id_student = sc1.id_student
and sc2.id_course > sc1.id_course
and c.code = 'C_13'
);
но есть и другие (возможно, лучшие) способы.
Затем вы можете обновить все оставшиеся записи соединения для обоих старых идентификаторов до вашего нового идентификатора; или объединить один из старых идентификаторов и удалить другой.
(Ваш вопрос подразумевает, что вы хотите решить общую задачу самостоятельно, поэтому я воздержусь от попыток предложить полное решение - надеюсь, это поможет вам понять и решить вашу главную проблему ...)