Oracle中IF语句内引用不存在的表报ORA-00942,求解决方案
问题:Oracle中安全校验可能不存在的表数据
需求:在Oracle中需先判断Folder表是否存在,若存在则检查该表中id=3的数据是否存在,不存在则提示错误。
当前编写的PL/SQL代码在Folder表不存在时触发PL/SQL: ORA-00942: table or view does not exist错误(第14行),代码如下:
DECLARE own VARCHAR2(200); l_cnt INTEGER; BEGIN SELECT sys_context( 'userenv', 'current_schema' ) INTO own FROM dual; SELECT count(*) INTO l_cnt FROM ALL_TABLES WHERE Table_name = upper('Folder') AND OWNER = own; IF( l_cnt > 0) THEN SELECT count(*) INTO l_cnt FROM Folder Where id = 3; IF( l_cnt > 0) THEN DBMS_OUTPUT.PUT_LINE ('Value exists'); ELSE DBMS_OUTPUT.PUT_LINE ('Value does not exist'); END IF; ELSE DBMS_OUTPUT.PUT_LINE ('Folder does not exist'); END IF; END;
请问如何在IF语句中安全使用可能不存在的表进行数据校验?
原因分析
Oracle的静态SQL会在编译阶段就检查引用的对象(如表、视图)是否存在,所以即使你在代码里加了表存在性判断,编译时还是会因为找不到Folder表而抛出错误。
解决方法:使用动态SQL
把查询Folder表的逻辑改成动态SQL,动态SQL是在运行时才解析执行的,编译阶段不会校验该表的存在性,只有当表确实存在时才会执行查询逻辑。
修改后的代码如下:
DECLARE own VARCHAR2(200); l_cnt INTEGER; BEGIN SELECT sys_context('userenv', 'current_schema') INTO own FROM dual; SELECT count(*) INTO l_cnt FROM ALL_TABLES WHERE Table_name = upper('Folder') AND OWNER = own; IF l_cnt > 0 THEN -- 用动态SQL执行表数据查询 EXECUTE IMMEDIATE 'SELECT count(*) FROM Folder WHERE id = 3' INTO l_cnt; IF l_cnt > 0 THEN DBMS_OUTPUT.PUT_LINE('Value exists'); ELSE DBMS_OUTPUT.PUT_LINE('Value does not exist'); END IF; ELSE DBMS_OUTPUT.PUT_LINE('Folder does not exist'); END IF; END;
补充优化
如果需要处理带参数的动态SQL,建议使用绑定变量来提升性能并避免SQL注入风险,示例如下:
EXECUTE IMMEDIATE 'SELECT count(*) FROM Folder WHERE id = :1' INTO l_cnt USING 3;
内容的提问来源于stack exchange,提问作者Suwaid Akbar
相关产品推荐
相关产品推荐

