如何通过SQL触发器跨表比较值?编写价格校验触发器遇PL/SQL报错
原报错中文翻译
- 错误(2,3):PL/SQL:SQL 语句被忽略
- 错误(2,69):PL/SQL:ORA-00904 错误:
LIEN_FABRICANT_PRODUIT表的PRIXFABRICANT为无效标识符 - 错误(2,92):PLS-00302 错误:必须声明组件
PRIXFABRICANT - 错误(5,3):PL/SQL:语句被忽略
- 错误(5,10):PLS-00201 错误:必须声明标识符
NEW.PRIXVENTE
错误原因拆解
- ORA-00904 无效标识符:优先检查
LIEN_FABRICANT_PRODUIT表的出厂价字段实际命名,可执行DESC LIEN_FABRICANT_PRODUIT查看字段列表,常见错误包括拼写偏差、漏写下划线、建表时使用大小写敏感引号导致字段名实际为小写等。 - PLS-00302 未声明
PRIXFABRICANT:你编写的关联查询没有将结果赋值给PL/SQL变量,直接在IF判断中引用该字段,编译器无法识别变量来源。 - PLS-00201 未声明
NEW.PRIXVENTE:行级触发器的内置绑定变量NEW、OLD在PL/SQL块中引用时必须加冒号前缀,不加冒号会被编译器识别为未声明的普通标识符;同时前面的SQL语句语法错误导致编译器上下文异常,也会触发该报错。 - 逻辑漏洞:原SELECT语句全表关联
ARTICLE和出厂价关联表,没有用当前正在更新的商品行的产品、厂商ID做匹配,就算查询到值也不是当前行对应的出厂价。
修正后的触发器代码
请先确认LIEN_FABRICANT_PRODUIT的实际出厂价字段名,替换下方代码中对应字段后执行:
CREATE OR REPLACE TRIGGER Comparer_Prix BEFORE UPDATE ON ARTICLE FOR EACH ROW DECLARE -- 锚定表字段类型定义变量,避免类型不匹配问题 v_prix_fab LIEN_FABRICANT_PRODUIT.PRIXFABRICANT%TYPE; BEGIN -- 用当前更新行的产品、厂商ID匹配对应的出厂价,赋值给变量 SELECT PRIXFABRICANT INTO v_prix_fab FROM LIEN_FABRICANT_PRODUIT WHERE N_PRODUIT = :NEW.N_PRODUIT AND N_FABRICANT = :NEW.N_FABRICANT; -- 执行业务规则校验 IF :NEW.PRIXVENTE < v_prix_fab THEN RAISE_APPLICATION_ERROR(-20001, 'Refusé : 销售价格不能低于出厂价格'); END IF; EXCEPTION -- 处理无匹配出厂价记录的情况,避免触发隐式错误 WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(-20002, 'Refusé : 未找到对应产品的出厂价记录'); END;
补充说明
- 如果新增商品(INSERT操作)时也需要校验该规则,可将触发条件修改为
BEFORE INSERT OR UPDATE ON ARTICLE,同时支持两种操作的校验。 - 如果
N_PRODUIT + N_FABRICANT不是LIEN_FABRICANT_PRODUIT表的唯一主键,可能存在多条匹配的情况,需要先补充该联合字段的唯一性约束,否则SELECT INTO会报单行子查询返回多行的错误。
内容的提问来源于stack exchange,提问作者Thomas Aspa
相关产品推荐
相关产品推荐

