You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle UPDATE BEFORE TRIGGER问题:含油食谱vegetariana列禁止修改失效

原触发器存在的问题
  • 语法结构错误:DECLARE 关键字必须放在PL/SQL块的BEGIN之前,原代码写在了BEGIN之后不符合Oracle语法规范
  • 表名拼写错误:查询时写的表名Ingredint是笔误,正确表名应为Ingredient
  • 触发变量引用错误:Oracle行级触发器中引用新旧行值必须加冒号前缀,应为:NEW、:OLD,原代码缺少冒号
  • 子查询逻辑漏洞:一个食谱可能关联多个食材,直接用=匹配子查询返回结果,当食谱有多个食材时会抛出TOO_MANY_ROWS异常,没有匹配的oil食材时会抛出NO_DATA_FOUND异常
  • 赋值语法错误:Oracle触发器中给:NEW字段赋值不需要SET关键字,且赋值运算符为:=而非=
修正后的触发器实现
CREATE OR REPLACE TRIGGER tr_oil BEFORE UPDATE OF vegetariana
ON Reteta
FOR EACH ROW 
DECLARE
    has_oil NUMBER(1);
BEGIN
    -- 检测当前食谱是否使用了oil食材
    SELECT COUNT(1) INTO has_oil
    FROM Set_ingrediente s
    JOIN Ingredient i ON s.ingred_id = i.ingred_id
    WHERE s.reteta_id = :NEW.reteta_id
    AND i.ingredient = 'oil'
    AND ROWNUM = 1; -- 找到1条匹配即停止查询,优化性能
    
    -- 如果使用了oil,强制vegetariana保持原值,不允许修改
    IF has_oil = 1 THEN
        :NEW.vegetariana := :OLD.vegetariana;
        -- 如果需要主动抛出错误提示用户,可以取消下行注释
        -- RAISE_APPLICATION_ERROR(-20001, '含油的食谱不允许修改素食标识');
    END IF;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        NULL; -- 没有匹配食材时不做处理
END;
/

说明:触发器添加了OF vegetariana限定,只有修改vegetariana字段时才会触发,可减少不必要的性能开销。如果希望修改任意字段时都强制校验vegetariana的值,去掉该限定即可。

内容的提问来源于stack exchange,提问作者Székely Reka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 10:15:03