【问题标题】:Oracle mutating tablesOracle 变异表
【发布时间】:2018-10-20 23:09:15
【问题描述】:

我有这个程序,它计算为汽车支付的总金额,并确定如果金额等于价格,是否可以将汽车状态更改为“已售出”。

我知道问题出在 car_payment 中的查询,但我找不到其他方法来计算金额的总和,请有人帮助我吗?

create or replace trigger tr_paid_car
    before insert
    or update of amount
    on car_payment
    for each row

declare 
    v_amount number;
    v_car_status_id car_status.car_status_id%type;
    v_price car.price%type;
begin
    select sum(amount)
        into v_amount
        from car_payment
        where car_id = :new.car_id;

    if inserting then 
        v_amount := v_amount + :new.amount;
    elsif updating then
        v_amount := v_amount + :new.amount - :old.amount;
    end if;

    select price
        into v_price
        from car
        where car_id = :new.car_id;

    if v_amount >= v_price then
        select car_status_id
        into v_car_status_id
        from car_status
        where description = 'SOLD';

        update car
            set car_status_id = v_car_status_id
            where car_id = :new.car_id;
    end if;
end;

/

【问题讨论】:

  • 如果您必须在计算中使用触发器并触发正在查询的同一个表,那么最好的选择可能是 PRAGMA AUTONOMOUS_TRANSACTION 以避免变异表错误。
  • 认真考虑不要使用触发器来执行应用程序逻辑。应用程序应调用 PL/SQL API 来报告汽车“已售出”。该 API 应检查付款金额是否等于价格,如果不相等,则向其调用者返回失败。
  • 我支持@MatthewMcPeak 的评论。将此代码从触发器中取出。使用插入和更新过程构建一个包。将包上的执行权限授予您的开发人员和用户,但不允许直接在桌面上执行 DML。然后把这个逻辑放在程序中,你就很成功了。

标签: oracle plsql mutating-table


【解决方案1】:

创建另一个名为:GET_CAR_PAY_AMT 的函数,如下所示。

CREATE OR REPLACE FUNCTION GET_CAR_PAY_AMT(p_car_id car_payment.car_id%type) return number
as
pragma autonomous_transaction;
x number;
begin
select sum(amount)
        into x
        from car_payment
        where car_id = p_car_id;
return x;
end GET_CAR_PAY_AMT;

现在使用函数 GET_CAR_PAY_AMT 代替触发器中的 SELECT 语句,如下所示:

替换下面的SQL:

select sum(amount)
into v_amount
from car_payment
where car_id = :new.car_id;

与:

v_amount := GET_CAR_PAY_AMT(:new.car_id);

【讨论】:

  • 我不会说。将 SELECT 移到函数中这一事实没有任何意义,它仍然会引发 mutating table 错误。
  • 是吗,我再来一次。
  • 我已经通过在函数中添加“PRAGMA AUTONOMOUS_TRANSACTION”更新了答案,并在我的网站上对其进行了测试,现在它没有引发任何变异错误。
猜你喜欢
  • 2015-02-15
  • 2011-01-09
  • 2019-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
相关资源
最近更新 更多