I have an Oracle trigger that needs to read from a table after deleting a row. Essentially, I need to count up the remaining rows that are similar to the current row, and if that count is zero, update a field elsewhere. After two days of hammering around, I haven't been able to figure out how to restructure my thought process to allow me to do this.
Here is an example:
CREATE OR REPLACE TRIGGER Di_PatMustBeWell
FOR EACH ROW
SELECT NUMDISEASES INTO Numdiseases
where Di_Patient = :OLD.Di_Patient;
IF( NumDiseases != 1 ) THEN
UPDATE Patient SET Pat_Sick = 0 WHERE Pat_Person = :OLD.Di_Patient;
Short answer - no trigger, no mutating.
Yow can use the trigger with
pragma autonomous_transaction for counting of remaining diagnoses for certain patient, but it's is not recommended way to do this.
Better you create new function or procedure to implement your logic on deleted diagnosis. Something like this:
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
An alternative solution, if you prefer (or must) to use a trigger in your application - declare internal function returning count of patient's diagnoses in the trigger body:
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
Hope it helps you a bit.