Oracle
 sql >> Database >  >> RDS >> Oracle

Come evitare errori di mutazione della tabella

Risposta breve:nessun trigger, nessun mutante.

Puoi usare il trigger con pragma autonomous_transaction per il conteggio delle diagnosi rimanenti per un determinato paziente, ma non è un modo consigliato per farlo. È meglio creare una nuova funzione o procedura per implementare la logica sulla diagnosi eliminata. Qualcosa del genere:

create table Diagnosis as select 456 idDiseases, 123 di_patient from dual;
/
create table diagnosisCount as select 1 numDiseases, 123 di_patient from dual;
/
create table Patient as select 123 Pat_Person, 1 Pat_Sick from dual;
/
drop trigger di_patmustbewell;

create or replace function deleteDiagnosis(idDiseases number) return number is
    rows_ number;
    di_patient number;
    Numdiseases number;
begin
    <<del>> begin 
        delete Diagnosis where IdDiseases = deleteDiagnosis.IdDiseases
        returning Diagnosis.di_patient into deleteDiagnosis.di_patient
        ;
        rows_ := sql%rowcount;
        if rows_ != 1 then raise too_many_rows; end if;
    end del;
    select count(1) into deleteDiagnosis.numDiseases from Diagnosis where Di_Patient = deleteDiagnosis.di_patient;
    if deleteDiagnosis.numdiseases = 0 then <<upd>> begin 
        update Patient set Pat_Sick = 0 where Pat_Person = deleteDiagnosis.di_patient;
        exception when others then 
            dbms_output.put_line('Cannot update Patient di_patient='||di_patient);
            raise;
    end upd; end if;
    return rows_;
end;
/
show errors

declare rows_ number :=  deleteDiagnosis(456);
begin dbms_output.put_line('deleted '||rows_||' rows'); end;
/

deleted 1 rows

select * from Patient;
PAT_PERSON   PAT_SICK
---------- ----------
       123          0

Una soluzione alternativa, se preferisci (o devi) utilizzare un trigger nella tua applicazione:dichiara la funzione interna restituendo il conteggio delle diagnosi del paziente nel corpo del trigger:

create or replace trigger di_patmustbewell
after delete on diagnosis for each row
declare
    numdiseases number;
    function getNumDiagnosis (di_patient number) return number is
        ret number;
        pragma autonomous_transaction;
    begin
        select count(1) into ret from diagnosis where di_patient = getNumDiagnosis.di_patient;
        return ret;
    end getNumDiagnosis;    
begin
    numDiseases := getNumDiagnosis(:old.di_patient);
    if(numdiseases = 0) then
        update patient set pat_sick = 0 where pat_person = :old.di_patient;
    end if;
end;
/
show errors;

Trigger DI_PATMUSTBEWELL compiled

Spero di esserti stato d'aiuto.