创建一个自治程序来记录事件:
CREATE PROCEDURE log_system_event(
p_user_name IN COLUMN_DEL_ATTEMPT.USER_NAME%TYPE,
p_object_name IN COLUMN_DEL_ATTEMPT.OBJECT_NAME%TYPE,
p_object_type IN COLUMN_DEL_ATTEMPT.OBJECT_TYPE%TYPE
)
AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO column_del_attempt (
user_name,
datetime,
object_name,
object_type
) VALUES (
p_user_name,
SYSDATE,
p_object_name,
p_object_type
);
COMMIT;
END log_system_event;
/
然后您可以从触发器中调用它(在 ALTER 事件上,而不是在 DROP 事件上):
CREATE TRIGGER DLL_No_Column_Del
BEFORE ALTER ON SCHEMA
BEGIN
IF ora_dict_obj_name = 'EMP_COPY' AND ORA_DICT_OBJ_TYPE = 'TABLE' THEN
log_system_event( login_user, ora_dict_obj_name, ORA_DICT_OBJ_TYPE );
RAISE_APPLICATION_ERROR(-20100, 'No column deletion allowed on table ' || ORA_DICT_OBJ_NAME);
END IF;
END;
/
那么,如果你这样做:
ALTER TABLE emp_copy DROP COLUMN employee_id;
它会引发异常:
ORA-04088: error during execution of trigger 'FIDDLE_SPRKWOBAQONFKBBYMKLX.DLL_NO_COLUMN_DEL'
ORA-00604: error occurred at recursive SQL level 1
ORA-20100: No column deletion allowed on table EMP_COPY
ORA-06512: at line 5
然后:
SELECT * FROM column_del_attempt;
输出:
用户名 |日期时间 |对象名 | OBJECT_TYPE
:---------------------------- | :-------- | :------------ | :----------
FIDDLE_SPRKWOBAQONFKBBYMKLX | 20 年 12 月 18 日 | EMP_COPY |桌子
db小提琴here
更新
要获取ALTER DDL 语句的文本according to AskTom,您可以使用V$OPEN_CURSOR 动态性能视图来获取DDL 语句的文本,然后您可以对其进行过滤:
CREATE PROCEDURE log_system_event(
p_user_name IN COLUMN_DEL_ATTEMPT.USER_NAME%TYPE,
p_object_name IN COLUMN_DEL_ATTEMPT.OBJECT_NAME%TYPE,
p_object_type IN COLUMN_DEL_ATTEMPT.OBJECT_TYPE%TYPE,
p_text IN COLUMN_DEL_ATTEMPT.TEXT%TYPE
)
AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO column_del_attempt (
user_name,
datetime,
object_name,
object_type,
text
) VALUES (
p_user_name,
SYSDATE,
p_object_name,
p_object_type,
p_text
);
COMMIT;
END log_system_event;
/
然后:
CREATE TRIGGER DLL_No_Column_Del
BEFORE ALTER ON SCHEMA
DECLARE
v_text VARCHAR2(4000);
BEGIN
SELECT SQL_TEXT
INTO v_text
FROM V$OPEN_CURSOR;
IF REGEXP_LIKE( v_text, '^ALTER\s+TABLE\s+("?)EMP_COPY\1\s+DROP\s+', 'i') THEN
log_system_event( login_user, ora_dict_obj_name, ORA_DICT_OBJ_TYPE, v_text );
RAISE_APPLICATION_ERROR(-20100, 'No column deletion allowed on table ' || ORA_DICT_OBJ_NAME);
END IF;
END;
/
(但是,db<>fiddle、SQLFiddle 和 Oracle 的 LiveSQL 都没有授予使用 V$OPEN_CURSOR dynamic performance view 的权限,所以我无法对此进行测试。)