我正在开发一个简单的触发器,可在添加新发票行时更新产品的库存数量。 我工作得很好;但我开始认为在实际应用中,在允许更新之前验证QOH是否足够是明智的。我确定我可以为此编写一个单独的触发器,但是我想看看是否可以在触发器中为条件语句连接两个表。
这是我已经得到的;在那里的任何地方添加一个SELECT语句会导致所有地狱崩溃,所以我在调用条件之前如何声明PRODUCT.P_QOH有点难过。
CREATE OR REPLACE TRIGGER trg_prod_QOH_on_line_add
BEFORE INSERT ON LINE
FOR EACH ROW
BEGIN
IF :NEW.LINE_UNITS > PRODUCT.P_QOH THEN
RAISE_APPLICATION_ERROR(-20202, 'Insufficient quantity on hand');
ELSE
UPDATE PRODUCT
SET P_QOH = P+QOH - :NEW.LINE_UNITS;
WHERE PRODUC.P_CODE = :NEW.P_CODE;
END IF;
END;
/
这对我来说不是一个主要问题,正如我所说,可能有不同的方式;我刚刚开始学习这些东西,并希望看到可能的东西。谢谢你的帮助。
答案 0 :(得分:3)
你进入危险区域试图通过触发器强制执行这样的规则。您要求的解决方案是:
create or replace trigger trg_prod_qoh_on_line_add
before insert on line
for each row
declare
v_qoh product.p_qoh%type;
begin
select p_qoh
into v_qoh
from product
where product.p_code = :new.p_code;
if :new.line_units > v_qoh then
raise_application_error(-20202, 'Insufficient quantity on hand');
else
update product
set p_qoh = p_qoh - :new.line_units
where product.p_code = :new.p_code;
end if;
end;
然而,在具有多个并发用户的系统中,这是不安全解决方案。假设产品' X'有p_qoh = 10然后有2个用户这样做:
user1> insert into line (p_code, line_units) values ('X', 7);
user2> insert into line (p_code, line_units) values ('X', 8);
user1> commit;
user2> commit;
两个会议都会看到' X'有p_qoh = 10所以两者都会成功,product.p_qoh最终会为-5。一切都腐败了!
安全的解决方案是在产品上创建检查约束:
alter table product add constraint prod_qoh_chk check (p_qoh >= 0);
现在您的触发器可以简单:
create or replace trigger trg_prod_qoh_on_line_add
before insert on line
for each row
begin
update product
set p_qoh = p+qoh - :new.line_units;
where produc.p_code = :new.p_code;
end;
这会引发一个不太友好的错误消息,如:
ORA-02290: check constraint (MYSCHEMA.PROD_QOH_CHECK) violated
您可以将其捕获到触发器中并提供所需的消息:
create or replace trigger trg_prod_qoh_on_line_add
before insert on line
for each row
begin
update product
set p_qoh = p+qoh - :new.line_units;
where produc.p_code = :new.p_code;
exception
when others then
if sqlerrm like 'ORA-02291:%(MYSCHEMA.PROD_QOH_CHECK)%' then
raise_application_error(-20202,'Insufficient quantity on hand');
else
raise;
end if;
end;
现在,如果我们重新运行上面的2用户场景:
user1> insert into line (p_code, line_units) values ('X', 7);
user2> insert into line (p_code, line_units) values ('X', 8);
user1> commit;
此时user2的插入失败并显示错误消息:
ORA-20202: Insufficient quantity on hand