我如何在 pl/sql 中解决此触发器?
How do i resolve this trigger in pl/sql?
我想要一个触发器,不超过 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'));
有两个问题。
问题 1:我猜您希望触发器在 count(codi_proj) 大于 3.When 时触发 您正在插入第 4 条记录 触发器不会触发,因为触发器在"before insert" 这意味着它被计数为 3 并且不会考虑当前记录 inserted.So 来修复它你可以修改触发器来执行大于或等于 contador >= 3
代码将起作用完美。
问题 2:testing.If 的方法还有另一个问题,您正在通过将记录插入项目来测试触发器,如 post 中所述您必须在每次插入后提交(或 DML)operation.Trigger 像任何其他数据库对象一样从数据的持久状态读取。
感谢您的帮助,我已经部分解决了这个问题。但是,当我插入它时,它可以工作,但是当我更新它时,当我在同一个项目中有超过 3 个工人时,它就不起作用。
我认为它不起作用,因为升级需要一个程序 运行 另一个程序
你至少不会用当前的行级触发器方法做你想做的事。
原因是行级触发器 无法访问导致它触发 的 table。结果,语句 "select ... from empleats ... will throw the exception "ORA-04091: table 正在发生变化,trigger/function 可能看不到它”,因为触发器触发以响应针对 table empleats 的 DML。
更好的过程是在业务规则层甚至应用程序级别进行此检查。但是,如果您坚持使用触发器,可以通过 after statement 触发器来完成。该触发器确实必须(或至少应该)处理可能超过最大员工限制的多个项目。
所以(参见 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;
我想要一个触发器,不超过 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'));
有两个问题。
问题 1:我猜您希望触发器在 count(codi_proj) 大于 3.When 时触发 您正在插入第 4 条记录 触发器不会触发,因为触发器在"before insert" 这意味着它被计数为 3 并且不会考虑当前记录 inserted.So 来修复它你可以修改触发器来执行大于或等于 contador >= 3
代码将起作用完美。
问题 2:testing.If 的方法还有另一个问题,您正在通过将记录插入项目来测试触发器,如 post 中所述您必须在每次插入后提交(或 DML)operation.Trigger 像任何其他数据库对象一样从数据的持久状态读取。
感谢您的帮助,我已经部分解决了这个问题。但是,当我插入它时,它可以工作,但是当我更新它时,当我在同一个项目中有超过 3 个工人时,它就不起作用。 我认为它不起作用,因为升级需要一个程序 运行 另一个程序
你至少不会用当前的行级触发器方法做你想做的事。 原因是行级触发器 无法访问导致它触发 的 table。结果,语句 "select ... from empleats ... will throw the exception "ORA-04091: table 正在发生变化,trigger/function 可能看不到它”,因为触发器触发以响应针对 table empleats 的 DML。 更好的过程是在业务规则层甚至应用程序级别进行此检查。但是,如果您坚持使用触发器,可以通过 after statement 触发器来完成。该触发器确实必须(或至少应该)处理可能超过最大员工限制的多个项目。 所以(参见 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;