-- 錯誤:表名變數 tpg_gzfspbnum 直接寫在字串常數中,不會被解析
execute immediate ' create table tpg_gzfspbnum as select ... where ywslid = L_YWSLID;';
字串常數內的識別符不會自動替換為變數值,需用拼接運算子 `||`。
CREATE OR REPLACE PROCEDURE prc_gzf_bz_ywslid (p_ywslid IN VARCHAR2) IS
v_table_name VARCHAR2(30) := 'tpg_gzfspb' || p_ywslid;
v_sql VARCHAR2(4000);
BEGIN
-- 1. 動態建表 (CTAS)
v_sql := 'CREATE TABLE ' || v_table_name ||
' AS SELECT * FROM gzf_zfbz.tpg_gzfspb@gzf_zfbz WHERE ywslid = :b1';
EXECUTE IMMEDIATE v_sql USING p_ywslid; -- 使用繫結變數防注入
-- 2. 若需建立索引/約束,同理拼接
EXECUTE IMMEDIATE 'CREATE INDEX idx_' || v_table_name || '_ywslid ON ' || v_table_name || '(ywslid)';
EXCEPTION
WHEN OTHERS THEN
-- 記錄錯誤日誌
RAISE;
END;
/
DECLARE
v_cnt INTEGER;
BEGIN
SELECT COUNT(*) INTO v_cnt FROM user_tables WHERE table_name = UPPER(v_table_name);
IF v_cnt = 0 THEN
EXECUTE IMMEDIATE v_sql USING p_ywslid;
END IF;
END;
| 錯誤代碼 | 原因 | 修正 |
|---|---|---|
| ORA-00903: invalid table name | 拼接後表名含空格、特殊字元或過長 | 打印 `v_sql` 檢查,使用 `DBMS_ASSERT.ENQUOTE_NAME` |
| ORA-01031: insufficient privileges | 無 CREATE TABLE 權限 | 授權 `GRANT CREATE TABLE TO user` |
| ORA-00955: name is already used | 表已存在 | 先 `DROP TABLE` 或用上述檢查邏輯 |