问题描述
我正在尝试编写一个PL / sql脚本,如果某个表存在/不存在,该脚本将执行一些sql语句。
例如:
SET SERVEROUTPUT ON;
DECLARE
cnt NUMBER := 0;
cnt_2 NUMBER := 0;
BEGIN
SELECT count(*) INTO cnt FROM all_tables where TABLE_NAME='DOES_NOT_EXIST';
IF cnt = 0 THEN
dbms_output.put_line('Table does not exist');
ELSE
dbms_output.put_line('Table exists ' || cnt);
SELECT COUNT(*) INTO cnt_2 from DOES_NOT_EXIST;
END IF;
END;
/
执行此操作时,出现错误
SELECT COUNT(*) INTO cnt_2 from DOES_NOT_EXIST;
*
ERROR at line 10:
ORA-06550: line 10,column 37:
PL/sql: ORA-00942: table or view does not exist
ORA-06550: line 10,column 5:
PL/sql: sql Statement ignored
但是,如果我在第11行中添加EXECUTE IMMEDIATE
,那么它将正常工作。
SET SERVEROUTPUT ON;
DECLARE
cnt NUMBER := 0;
cnt_2 NUMBER := 0;
BEGIN
SELECT count(*) INTO cnt FROM all_tables where TABLE_NAME='DOES_NOT_EXIST';
IF cnt = 0 THEN
dbms_output.put_line('Table does not exist');
ELSE
dbms_output.put_line('Table exists ' || cnt);
EXECUTE IMMEDIATE 'SELECT COUNT(*) INTO cnt_2 from DOES_NOT_EXIST';
END IF;
END;
/
现在可以了
Table does not exist
PL/sql procedure successfully completed.
-
能否请您帮助我理解为什么无法在逻辑上到达
ELSE
块时报告错误的原因?cnt
变量将始终为0
,那么,我认为永远不会到达ELSE
块。 -
这是否意味着我应该在
EXECUTE IMMEDIATE
块中为所有此类语句添加ELSE
?
我在SO和其他地方进行了搜索,但找不到答案。老实说,我不知道还要使用哪些其他搜索词。所有搜索命中都会导致一般性错误。所以,我在问这个问题。如果已经回答了,请指向我并关闭它。
谢谢。
解决方法
您缺少的是语句分两个步骤处理;在执行 之前先对其进行编译。
在编译阶段,将识别并查找标识符(表和列等)。如果找不到表名(或列名或其他名称),则会出现编译错误。
使用execute immediate
可使此过程短路。与其说“立即执行”,不如说是“延迟编译”。该语句在运行时同时编译和执行。这就是execute immediate
防止错误发生的原因。
看起来您需要这样的东西:
select
owner,table_name,xmlcast(
xmlquery(
'/ROWSET/ROW/CNT'
passing xmltype(dbms_xmlgen.getXML('select count(*) cnt from "'||owner||'"."'||table_name||'"'))
returning content null on empty
)
as int
) as cnt
from all_tables
where owner in ('XTENDER',user);
此查询从通过谓词过滤的all_tables中返回每个表的行数