2017-10-12 189 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包含數據庫中的所有表和視圖。 –

相關問題