如何在注销触发期间删除序列和程序?
How to delete sequences and procedures during logoff trigger?
在我所处的特殊情况下,您能否帮助我。在注销触发器期间删除序列和过程时,我收到“ORA-30511:系统触发器中无效的 DDL 操作”。
我需要在注销事件发生之前删除用户的 tables、序列和过程。我正在使用单独的触发器在 DB_OBJECTS table 中编写 table 详细信息。下面是我的注销触发器 - 你能帮我看看我做错了什么吗?删除 tables 在下面的代码中工作正常。仅删除序列和过程会出现“ORA-30511:系统触发器中无效的 DDL 操作”错误。
CREATE OR REPLACE TRIGGER DELETE_BEFORE_LOGOFF
BEFORE LOGOFF ON DATABASE
DECLARE
USER_ID NUMBER := SYS_CONTEXT('USERENV', 'SESSIONID');
BEGIN
FOR O IN (SELECT USER, OBJECT_NAME, OBJECT_TYPE
FROM DB_OBJECTS WHERE SID = USER_ID
AND USERNAME = USER AND SYSDATE > CREATED_DTTM) LOOP
IF O.OBJECT_TYPE = 'TABLE' THEN
EXECUTE IMMEDIATE 'DROP TABLE ' || O.USER || '.' || O.OBJECT_NAME || ' CASCADE CONSTRAINTS';
ELSIF O.OBJECT_TYPE = 'SEQUENCE' THEN
EXECUTE IMMEDIATE 'DROP SEQUENCE ' || O.USER || '.' || O.OBJECT_NAME;
ELSIF O.OBJECT_TYPE = 'PROCEDURE' THEN
EXECUTE IMMEDIATE 'DROP PROCEDURE ' || O.USER || '.' || O.OBJECT_NAME;
END IF;
END LOOP;
EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
END;
/
这很简单。
- 错误代码:ORA-30511
- 问题描述:系统触发器中无效的 DDL 操作
- 原因:试图在系统触发器中执行无效的 DDL 操作。系统触发器目前不支持大多数 DDL 操作。当前唯一支持的 DDL 操作是 table 操作 和 ALTER/COMPILE 操作。
- 操作:删除系统触发器中的无效 DDL 操作。
这就是为什么只有
Dropping tables is working fine
成功。
因此,您不能使用触发器来做到这一点。
然后你问(在评论中)如何删除这些对象。据我所知,手动。不过,这很不寻常 - 如果有人不小心注销怎么办?你会放弃他们创造的一切。如果您将该模式用于教育目的(例如,每个学生都有自己的模式),那么您可以创建一个“清理”脚本,一旦 class 结束,您就会 运行 。像这样:
SET SERVEROUTPUT ON;
DECLARE
l_user VARCHAR2 (30) := 'SCOTT';
l_str VARCHAR2 (200);
BEGIN
IF USER = l_user
THEN
FOR cur_r IN (SELECT object_name, object_type
FROM user_objects
WHERE object_name NOT IN ('EMP',
'DEPT',
'BONUS',
'SALGRADE'))
LOOP
BEGIN
l_str :=
'drop '
|| cur_r.object_type
|| ' "'
|| cur_r.object_name
|| '"';
DBMS_OUTPUT.put_line (l_str);
EXECUTE IMMEDIATE l_str;
EXCEPTION
WHEN OTHERS
THEN
NULL;
END;
END LOOP;
END IF;
END;
/
PURGE RECYCLEBIN;
它远非完美;我用它来清理我用来在各种网站上回答问题的 Scott
模式,所以 - 一旦它变得一团糟,我 运行 那个 PL/SQL 代码多次(因为可能的外键约束)。
其他选项是保留 create user
脚本(以及所有 grant
语句)并且 - 一旦 class 结束 - 删除现有用户并简单地重新创建它。
或者,如果该用户包含一些预建的 tables,保留导出文件(我的意思是数据泵导出的结果)并在删除用户后导入它。
有多种选择 - 我不知道我是否猜对了,但现在你有 一些东西 可以考虑了。
在我所处的特殊情况下,您能否帮助我。在注销触发器期间删除序列和过程时,我收到“ORA-30511:系统触发器中无效的 DDL 操作”。
我需要在注销事件发生之前删除用户的 tables、序列和过程。我正在使用单独的触发器在 DB_OBJECTS table 中编写 table 详细信息。下面是我的注销触发器 - 你能帮我看看我做错了什么吗?删除 tables 在下面的代码中工作正常。仅删除序列和过程会出现“ORA-30511:系统触发器中无效的 DDL 操作”错误。
CREATE OR REPLACE TRIGGER DELETE_BEFORE_LOGOFF
BEFORE LOGOFF ON DATABASE
DECLARE
USER_ID NUMBER := SYS_CONTEXT('USERENV', 'SESSIONID');
BEGIN
FOR O IN (SELECT USER, OBJECT_NAME, OBJECT_TYPE
FROM DB_OBJECTS WHERE SID = USER_ID
AND USERNAME = USER AND SYSDATE > CREATED_DTTM) LOOP
IF O.OBJECT_TYPE = 'TABLE' THEN
EXECUTE IMMEDIATE 'DROP TABLE ' || O.USER || '.' || O.OBJECT_NAME || ' CASCADE CONSTRAINTS';
ELSIF O.OBJECT_TYPE = 'SEQUENCE' THEN
EXECUTE IMMEDIATE 'DROP SEQUENCE ' || O.USER || '.' || O.OBJECT_NAME;
ELSIF O.OBJECT_TYPE = 'PROCEDURE' THEN
EXECUTE IMMEDIATE 'DROP PROCEDURE ' || O.USER || '.' || O.OBJECT_NAME;
END IF;
END LOOP;
EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
END;
/
这很简单。
- 错误代码:ORA-30511
- 问题描述:系统触发器中无效的 DDL 操作
- 原因:试图在系统触发器中执行无效的 DDL 操作。系统触发器目前不支持大多数 DDL 操作。当前唯一支持的 DDL 操作是 table 操作 和 ALTER/COMPILE 操作。
- 操作:删除系统触发器中的无效 DDL 操作。
这就是为什么只有
Dropping tables is working fine
成功。
因此,您不能使用触发器来做到这一点。
然后你问(在评论中)如何删除这些对象。据我所知,手动。不过,这很不寻常 - 如果有人不小心注销怎么办?你会放弃他们创造的一切。如果您将该模式用于教育目的(例如,每个学生都有自己的模式),那么您可以创建一个“清理”脚本,一旦 class 结束,您就会 运行 。像这样:
SET SERVEROUTPUT ON;
DECLARE
l_user VARCHAR2 (30) := 'SCOTT';
l_str VARCHAR2 (200);
BEGIN
IF USER = l_user
THEN
FOR cur_r IN (SELECT object_name, object_type
FROM user_objects
WHERE object_name NOT IN ('EMP',
'DEPT',
'BONUS',
'SALGRADE'))
LOOP
BEGIN
l_str :=
'drop '
|| cur_r.object_type
|| ' "'
|| cur_r.object_name
|| '"';
DBMS_OUTPUT.put_line (l_str);
EXECUTE IMMEDIATE l_str;
EXCEPTION
WHEN OTHERS
THEN
NULL;
END;
END LOOP;
END IF;
END;
/
PURGE RECYCLEBIN;
它远非完美;我用它来清理我用来在各种网站上回答问题的 Scott
模式,所以 - 一旦它变得一团糟,我 运行 那个 PL/SQL 代码多次(因为可能的外键约束)。
其他选项是保留 create user
脚本(以及所有 grant
语句)并且 - 一旦 class 结束 - 删除现有用户并简单地重新创建它。
或者,如果该用户包含一些预建的 tables,保留导出文件(我的意思是数据泵导出的结果)并在删除用户后导入它。
有多种选择 - 我不知道我是否猜对了,但现在你有 一些东西 可以考虑了。