PL / SQL条件语句在触发器中使用两个表

时间:2012-06-18 06:04:54

标签: sql oracle join plsql triggers

我正在开发一个简单的触发器,可在添加新发票行时更新产品的库存数量。 我工作得很好;但我开始认为在实际应用中,在允许更新之前验证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;
/

这对我来说不是一个主要问题,正如我所说,可能有不同的方式;我刚刚开始学习这些东西,并希望看到可能的东西。谢谢你的帮助。

1 个答案:

答案 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