Как разрешить этот триггер в pl / sql? - PullRequest
0 голосов
/ 05 мая 2020

Я хочу иметь триггер, не более 3 сотрудников работают над данным проектом это код, который у меня есть, но работает не очень хорошо, иногда работает, а иногда не работает.

create or replace trigger t_maxim_empleats_projecte
before insert or update of codi_proj
on empleats
for each row
declare
contador number(5);
begin
select count(codi_proj) into contador from empleats where codi_proj= :new.codi_proj;
if contador > 3 then
RAISE_APPLICATION_ERROR(-20000, 'No poden haver-hi més de 3 empleats en un
mateix projecte.');
end if;
end;

Это все, что у меня есть в моих SQL таблицах:

create table Projectes(
    codi_proj   number(5), 
    nom_proj    varchar2(25),
    pressupost  number(10,2),
    primary key (codi_proj)
);

create table Empleats(
    codi_emp    number(5),
    nom_emp varchar2(15),
    sou     number(10,2),
    codi_dept   number(5),
    codi_proj   number(5),
    data_alta   date,
    primary key (codi_emp),
        foreign key (codi_dept)   references Departaments(codi_dept) on delete set null,
        foreign key (codi_proj)   references Projectes(codi_proj) on delete set null
);

insert into projectes(codi_proj, nom_proj, pressupost)
values (1, 'Daisy', 240000);

insert into projectes(codi_proj, nom_proj, pressupost)
values (2, 'CLAM', 63000);

insert into projectes(codi_proj, nom_proj, pressupost)
values (3, 'Vocal Processor', 600000);

insert into empleats(codi_emp, nom_emp, sou, codi_dept, codi_proj,data_alta)
values (1, 'Maria', 21000, 1, 1,TO_DATE('10/10/1980','dd/mm/yyyy'));

insert into empleats(codi_emp, nom_emp, sou, codi_dept, codi_proj,data_alta)
values (2, 'Josep', 18000, 1, 1,TO_DATE('01/08/1982','dd/mm/yyyy'));

insert into empleats(codi_emp, nom_emp, sou, codi_dept, codi_proj,data_alta)
values (3, 'Ramon', 48000, 4, 2,TO_DATE('05/04/2005','dd/mm/yyyy'));

Ответы [ 3 ]

1 голос
/ 05 мая 2020

Есть две проблемы.

Проблема 1: я предполагаю, что вы ожидаете, что триггер сработает, когда count (codi_proj) больше 3. Когда вы вставляете четвертую запись, триггер не срабатывает, поскольку триггер срабатывает в момент «перед вставкой», который означает, что он получает счет как 3 и не будет учитывать текущую вставляемую запись. Поэтому, чтобы исправить это, вы можете изменить триггер, чтобы он делал больше или равный contador >= 3, код будет работать отлично.

Проблема 2 : Есть еще одна проблема с подходом к тестированию. Если вы тестируете триггер, вставляя записи в проекты, как описано в сообщении, вы должны иметь фиксацию после каждой операции вставки (или DML). Триггер, как и любой другой объект базы данных, читает из постоянное состояние данных.

0 голосов
/ 06 мая 2020

Вы не собираетесь делать то, что хотите, по крайней мере, с подходом триггера текущего уровня строки. Причина в том, что триггер уровня строки не может получить доступ к таблице, из-за которой он сработал . В результате оператор "select ... from empleats ... вызовет исключение" ORA-04091: таблица мутирует, триггер / функция может не видеть ее ", потому что триггер срабатывает в ответ на DML против таблицы empleats. Лучше процесс состоит в том, чтобы выполнить эту проверку на уровне бизнес-правил или даже на уровне приложения. Однако, если вы настаиваете на триггере, это может быть выполнено с помощью триггера after . Этот триггер действительно должен (или по крайней мере, должен) иметь дело с возможностью нескольких проектов, превышающих максимальное количество сотрудников. Итак (см. fiddle ):

create or replace trigger limit_3_emp_per_proj_ais
           after insert on employees 
declare
   k_new_msg_line    constant            varchar2(3)  := chr(10) || '  ';
   k_max_emp_message constant            varchar2(80) := 
       'No rows inserted!' || k_new_msg_line || 'Following Projects have exceed max of 3 employees:'; 
   cursor proj_over_3_emp is
         select proj.name, proj.proj_id, count(*)
           from projects  proj 
           join employees emp
             on (emp.proj_id = proj.proj_id)
          group by proj.proj_id, proj.name    
         having count(*) > 3 
          order by proj.proj_id;

   l_proj_exceeds_3_emp                varchar2(3500) := null;           
begin 
   for proj_emp in proj_over_3_emp  
   loop 
       l_proj_exceeds_3_emp := l_proj_exceeds_3_emp || k_new_msg_line ||
                               proj_emp.name || '(' || proj_emp.proj_id || ')';
   end loop; 

   if l_proj_exceeds_3_emp is not null
   then 
      raise_application_error( -20199,k_max_emp_message || l_proj_exceeds_3_emp);
   end if;

end limit_3_emp_per_proj_ais;
0 голосов
/ 05 мая 2020

Благодаря вашей помощи я частично решил проблему. Однако, когда я вставляю его, он работает, но когда я обновляю его, он не работает, когда у меня более 3 рабочих в одном проекте. Я думаю, что это не сработает, потому что для обновления нужна процедура, запускающая другую процедуру

...