存儲過程定義儲存在資料字典(`DBA_SOURCE`/`USER_SOURCE`)中。修改或刪除過程本質上是對字典表的 DML 操作,Oracle 會在 Undo 段保留修改前的映像。利用 閃回查詢(`AS OF TIMESTAMP`)即可在 Undo 保留期內找回舊版本程式碼。
關鍵:必須盡快操作,Undo 空間被覆寫後將無法恢復。
| 時間 | 操作 | 用戶 |
|---|---|---|
| 14:31 | 建立程序 GG_TEST | TEST |
| 14:33 | 刪除程序 GG_TEST | TEST |
| 14:35 | 以 SYS 執行閃回查詢恢復 | SYS |
CONN test/test
CREATE OR REPLACE PROCEDURE GG_TEST AS
l_cnt NUMBER;
BEGIN
FOR i IN 1 .. 10000 LOOP
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM t WHERE x = ' || i INTO l_cnt;
END LOOP;
END;
/
SHOW ERRORS
DROP PROCEDURE GG_TEST;
CONN / AS SYSDBA
-- 1. 將閃回時間點設為刪除前 (14:33) 的資料字典快照建立臨時表
CREATE TABLE p_temp AS
SELECT *
FROM dba_source AS OF TIMESTAMP TO_TIMESTAMP('2014-05-04 14:33:00', 'YYYY-MM-DD HH24:MI:SS')
WHERE type = 'PROCEDURE'
AND owner = 'TEST'
AND name = 'GG_TEST';
-- 2. 按行號順序提取程式碼文本
SELECT text
FROM p_temp
WHERE name LIKE UPPER('%GG_TEST%')
AND owner = 'TEST'
ORDER BY line;
TEXT
---------------------------------------------------------------------------
PROCEDURE GG_TEST
AS l_cnt NUMBER;
BEGIN
FOR i IN 1 .. 10000 LOOP
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM t WHERE x = ' || i INTO l_cnt;
END LOOP;
END;
為預防未來誤刪,可建立 DDL 觸發器記錄所有 `DROP/CREATE/ALTER` 操作:
CREATE OR REPLACE TRIGGER audit_ddl_trg
AFTER DDL ON DATABASE
BEGIN
INSERT INTO ddl_audit_log (osuser, current_user, ddl_type, object_name, sql_text, created)
VALUES (SYS_CONTEXT('USERENV','OS_USER'), SYS_CONTEXT('USERENV','CURRENT_USER'),
ORA_DICT_OBJ_TYPE, ORA_DICT_OBJ_NAME, ORA_SQL_TXT, SYSDATE);
END;
/
-- 需先建立 ddl_audit_log 表