2017-10-12 191 views
0

我需要执行一个查询,在执行查询之前,我需要检查以下两个条件, 1)表行数为0 2)存在表列中的一列。如何检查在PL/SQL中运行查询之前列是否存在并且表行数是否收集?

所以基础上我的要求我写的程序如下,

DECLARE 
    rowCount INT; 
    column_not_exists exception; 
    pragma exception_init (column_not_exists , -00904); 
BEGIN 
SELECT count(*) INTO rowCount FROM Settings; 
IF (rowCount = 0) THEN 
Insert into Settings (ID,PROCESSID,AREA) select ID,PROCESSID,AREA from POINT WHERE CLASSNAME = 'ENDPOINT' and PROCESSID IS NOT NULL; 
END IF; 
exception WHEN column_not_exists THEN NULL; 
END; 
/

但不知何故异常没有被处理,我仍然可以在日志中

PL/SQL: ORA-00904: "PROCESSID": invalid identifier 
ORA-06550: line 8, column 1: 
PL/SQL: SQL Statement ignored 

有人可以看到错误消息帮助我在这里验证两种情况。

+0

关于行计数,您可以使用dba_tab_statistics(它显示关于来自上次数据库收集统计信息的表的统计信息,如果关闭的行数很重要,则不适合)。关于列,您可以从dba_tab_columns查询表的列并检查列的存在。 –

+0

你可以从你的数据库扩展你的Point(表)结构! –

+1

ora-00904是编译时异常。异常部分陷阱运行时异常。简而言之,ora-00904不能被捕获为静态SQL-它可以被困在动态SQL中。无论如何,处理静态SQL的异常没有任何意义。您应该知道要插入/从中选择数据的表的结构。 –

回答

0

你最好使用系统视图ALL_TAB_COLUMNS(当然,你需要有权限访问它)。此外,您还需要使用Oracle动态SQL语句“EXECUTE IMMEDIATE”,否则您的代码将无法编译。

我在这里改变你的代码,请相应的更换这些地方: 较低(t.OWNER)= '主人', 较低(t.TABLE_NAME)= '点'

代码:

declare 
    rowcount int; 
    l_cnt number; 
begin 
    select count(*) into rowcount from settings; 
    if (rowcount = 0) then 
    select count(*) into l_cnt from ALL_TAB_COLUMNS t 
      where lower(t.OWNER)='owner' and lower(t.TABLE_NAME)='point' 
      and lower(t.COLUMN_NAME) in ('processid','area'); 
    if l_cnt = 2 then 
     execute immediate 'insert into settings 
     (id, processid, area) 
     select id, processid, area 
      from point 
     where classname = ''ENDPOINT'' 
      and processid is not null'; 
    end if; 
    end if; 

end; 
+1

只需注意:ALL_TAB_COLS不需要任何权限。您自动有权访问它,它是您需要权限的DBA_TAB_COLS。 USER_TAB_COLS包含您拥有的所有表格和视图,没有OWNER列。 ALL_TAB_COLS包含您有权访问的所有表和视图,包括其他模式中的表。因此,有一个OWNER列。 DBA_TAB_COLS包含数据库中的所有表和视图。 –

相关问题