批次排程、ETL 作業常需在執行前確認目標表存在,避免報錯中斷。本文提供可直接部署的檢查過程,支援「Schema.表名」或「表名」(全庫搜尋),不存在時拋出自定義異常 -20010,供上層捕捉處理(如等待重試、發送告警)。
CREATE OR REPLACE PROCEDURE p_check_table (
p_table_name IN VARCHAR2 -- 格式: 'SCHEMA.TABLE' 或 'TABLE'
) AS
v_cnt NUMBER;
v_full_name VARCHAR2(200) := UPPER(p_table_name);
v_owner VARCHAR2(100);
v_table VARCHAR2(200);
v_pos NUMBER;
BEGIN
-- 解析 Schema 與表名
v_pos := INSTR(v_full_name, '.', 1, 1);
IF v_pos > 0 THEN
v_owner := SUBSTR(v_full_name, 1, v_pos - 1);
v_table := SUBSTR(v_full_name, v_pos + 1);
ELSE
v_owner := NULL;
v_table := v_full_name;
END IF;
-- 查詢 ALL_TABLES (當前使用者可見的所有表)
IF v_owner IS NULL THEN
SELECT COUNT(*) INTO v_cnt FROM all_tables WHERE table_name = v_table;
ELSE
SELECT COUNT(*) INTO v_cnt
FROM all_tables
WHERE table_name = v_table AND owner = v_owner;
END IF;
-- 不存在則拋出自定義異常
IF v_cnt = 0 THEN
RAISE_APPLICATION_ERROR(-20010, p_table_name || ' does not exist, please wait...');
END IF;
EXCEPTION
WHEN OTHERS THEN
-- 可選:記錄日誌後再拋出
RAISE;
END p_check_table;
/
-- 指定 Schema
BEGIN
p_check_table('SCOTT.EMP');
DBMS_OUTPUT.PUT_LINE('Table exists, proceed...');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
-- 這裡可加入 DBMS_LOCK.SLEEP(60) 等待重試邏輯
END;
/
-- 僅表名 (跨 Schema 搜尋)
BEGIN
p_check_table('EMP');
END;
/
| 項目 | 說明 |
|---|---|
| 查詢視圖 | ALL_TABLES:含當前使用者擁有 + 被授權的表。若需全庫(含無權限),改用 DBA_TABLES (需 DBA 權限)。 |
| 大小寫 | Oracle 資料字典儲存大寫,輸入參數統一 UPPER()。 |
| 異常代碼 | -20000 ~ -20999 為使用者自定義保留區,避免衝突系統錯誤碼。 |
| 效能 | 資料字典查詢極快,可放心放在高頻排程前。 |
| 擴充 | 可加入檢查表狀態 (VALID/INVALID)、分區表、暫存表等細項。 |
CREATE OR REPLACE PROCEDURE p_wait_table (
p_table_name IN VARCHAR2,
p_max_wait_sec IN NUMBER DEFAULT 300,
p_interval_sec IN NUMBER DEFAULT 10
) AS
v_elapsed NUMBER := 0;
BEGIN
LOOP
BEGIN
p_check_table(p_table_name);
RETURN; -- 存在則直接返回
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -20010 THEN
IF v_elapsed >= p_max_wait_sec THEN
RAISE_APPLICATION_ERROR(-20011, 'Timeout waiting for table ' || p_table_name);
END IF;
DBMS_LOCK.SLEEP(p_interval_sec);
v_elapsed := v_elapsed + p_interval_sec;
ELSE
RAISE; -- 非預期錯誤向上拋出
END IF;
END;
END LOOP;
END p_wait_table;
/
排程開頭呼叫 p_wait_table('STG.ORDER_DAILY', 600, 30); 即可優雅等待上游建表完成。
以 ALL_TABLES + RAISE_APPLICATION_ERROR 建立可重用的表存在性檢查元件,再封裝重試等待邏輯,讓批次作業具備自愈與可觀測能力,是穩健 ETL 架構的基石之一。