DB2运行存储过程与触发器代码报SQLCODE -811、-723错误求助
错误根因
首先对应你拿到的错误码做基础解释:
- SQLCODE=-811, SQLSTATE=21000:DB2中这个错误的触发条件是,SQL语句里用了等值比较的标量子查询,但子查询返回结果超过1行,数据库无法完成单行值的比对。
- SQLCODE=-723, SQLSTATE=09000:这是触发器执行失败的外层通用错误,实际报错点就是触发器
test2里的DELETE语句。
你写的test2触发器存在两个逻辑错误,直接触发了上述报错:
- 子查询没有加任何筛选条件:
WHERE (SELECT testfirst.roger_value FROM testfirst) = (SELECT testall.roger_value FROM testall)这部分左右两边都是全表查询,只要testfirst、testall表中存在超过1条记录,子查询就会返回多行结果,完全不符合标量等值比对的要求。 - 行级触发器没有正确引用新插入的行数据:DB2的AFTER INSERT行级触发器中,要获取刚插入的那条记录的字段值,必须通过
NEW关联名引用,直接全表查testall不仅返回多行,也无法准确定位到本次插入的记录值。
另外你写的test1触发器也存在逻辑隐患:当前写法每次插入1条记录到testall,就会把testall全表所有记录的way_out、way_in字段都+1,绝大多数场景下这不是预期逻辑,还可能引发触发器递归触发的问题。
修复方案
- 重写
test2触发器,通过NEW关键字直接获取本次插入的roger_value,匹配删除testfirst表中对应值的记录,修正后的代码如下:
-- 先删除原有错误的触发器 DROP TRIGGER test2; -- 重建触发器,如果你的环境提示NEW未定义,就保留REFERENCING NEW AS NEW子句 CREATE TRIGGER test2 AFTER INSERT ON testall REFERENCING NEW AS NEW FOR EACH ROW MODE DB2SQL DELETE FROM testfirst WHERE roger_value = NEW.roger_value;
- 修正
test1触发器的全表更新问题,仅对本次新插入的记录做字段更新,参考代码如下:
DROP TRIGGER test1; CREATE TRIGGER test1 AFTER INSERT ON testall REFERENCING NEW AS NEW FOR EACH ROW MODE DB2SQL UPDATE testall SET way_out = way_out + 1, way_in = way_in + 1 WHERE testall表的主键字段 = NEW.testall表的主键字段; -- 比如testall主键是id,就写WHERE id = NEW.id,确保只更新刚插入的那一条记录
修改完成后重新执行CALL proc_test(999, 'testvalue', 8888);即可正常运行。
内容的提问来源于stack exchange,提问作者Learner91
相关产品推荐
相关产品推荐

