Oracle
 sql >> база данни >  >> RDS >> Oracle

Как да избегнем грешки при мутиране на таблицата

Кратък отговор - без тригер, без мутация.

Можете да използвате тригера с pragma autonomous_transaction за преброяване на оставащите диагнози за определен пациент, но това не е препоръчителен начин да направите това. По-добре е да създадете нова функция или процедура, за да приложите логиката си при изтрита диагноза. Нещо като това:

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

Алтернативно решение, ако предпочитате (или трябва) да използвате тригер в приложението си - декларирайте вътрешна функция, връщаща броя на диагнозите на пациента в тялото на тригера:

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

Надявам се да ви помогне малко.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво да направите, ако получите неправилна порядкова грешка при отметка, когато използвате SQL Server с нашия Oracle ODBC драйвер

  2. Oracle Text няма да работи с NVARCHAR2. Какво друго може да не е налично?

  3. Условно дефинирайте курсор

  4. Как да използвам Oracle Ref Cursor от C# ODP.NET като параметър на ReturnValue, без да използвам съхранена функция или процедура?

  5. Как мога да изпълня собствен SQL скрипт в JPA/Hibernate?