Das Grundproblem ist die ungeeignete Erzeugung des Wertes für den Primärschlüssel.
Select count(ID) into c from ...
Wehe es wird ein Datensatz gelöscht - dann gerät das ganze System durcheinander.
Besser ist da:
Select Max(ID)+1 into c from ...
Aber auch das ist nicht wasserdicht wenn mehr als ein Prozess/Thread das abarbeitet.
Was man hier wirklich bräuchte wäre ein
Generator.
Dann würde man zuerst mit dem Generator eine "neue Nummer ziehen" und könnte dann sicher sein, dass es keine Kollisionen von anderen Prozessen gibt.