[20150918]禁止用户truncate以及drop表.txt

简介: [20150918]禁止用户truncate以及drop表.txt --一个需求要求禁止用户truncate以及drop表,实际上很简单仅仅建立一个触发器就ok了.

[20150918]禁止用户truncate以及drop表.txt

--一个需求要求禁止用户truncate以及drop表,实际上很简单仅仅建立一个触发器就ok了.

CREATE OR REPLACE TRIGGER SYS.tri_prevent_drop_truncate
   BEFORE TRUNCATE OR DROP ON DATABASE
BEGIN
   IF ora_dict_obj_type = 'TABLE' AND ora_dict_obj_owner = 'SCOTT'
   THEN
      raise_application_error (-20000, 'YOU CAN NOT TRUNCATE or DROP ' || ora_dict_obj_name || ' TABLE!');
   END IF;
END;
/

--仔细想想存在什么问题吗?我首先想到的物化视图的刷新,有时候要执行truncate.当然看刷新的方式:

1.建立测试环境:

SCOTT@test> @ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.3.0     Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

--建立触发器,脚本见上.


2.建立测试信息:

create table t (id number, name varchar2(30));
alter table t add constraint pk_t primary key (id);
create materialized view log on t;
--drop materialized view log on t;
create materialized view mv_t refresh complete as select count(*) from t;
insert into t select rownum, tname from tab;
commit;

SCOTT@test> exec dbms_mview.refresh('mv_t')
PL/SQL procedure successfully completed.
--可以发现这样没有问题.

SCOTT@test> select * from mv_t;
  COUNT(*)
----------
        49

--但是如果执行如下呢?
--11G物化视图刷新有1个参数atomic_refresh.
--如果为false,采用的方式是truncate,再使用/*+ append */ 提示insert。这样redo最少,但是刷新期间无法访问。
--如果为true,采用的方式是delete,再insert。这样产生许多redo与undo。这样在刷新期间访问没问题,最多有点慢。

--12c在这个基础上引入1个参数Out of place,刷新时先建立表在外部,刷新后通过类似分区交换的技术与之交换,这个刷新很形象的命名
--为out-of-place refresh.

SCOTT@test> exec dbms_mview.refresh('mv_t', atomic_refresh => false)
BEGIN dbms_mview.refresh('mv_t', atomic_refresh => false); END;

*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-20000: YOU CAN NOT TRUNCATE or DROP MV_T TABLE!
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2563
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2776
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2745
ORA-06512: at line 1

--因为是11g的缘故,无法测试out-of-place参数.不过应该不行.

3.还会有什么情况呢?
--重建索引.
SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD;
Index altered.

--再线重建索引呢?
SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
ALTER INDEX SCOTT.PK_T REBUILD online
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 2
ORA-20000: YOU CAN NOT TRUNCATE or DROP SYS_JOURNAL_315614 TABLE!
ORA-06512: at line 4
ORA-00604: error occurred at recursive SQL level 2
ORA-20000: YOU CAN NOT TRUNCATE or DROP SYS_JOURNAL_315614 TABLE!
ORA-06512: at line 4

--再次执行会出现如下错误.
SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
ALTER INDEX SCOTT.PK_T REBUILD online
*
ERROR at line 1:
ORA-08104: this index object 315614 is being online built or rebuilt

--可以发现使用online参数建立索引要建立一张SYS_JOURNAL_315614 IOT表(后面的数字对应PK_T索引的object_id),完成后再删除时
--由于触发器的限制报错!!也就是以上的脚本存在问题,必须排除这样情况.
--报ORA-08104错误处理可以参考许多网上的做法.删除SYS_JOURNAL_315614(关闭触发器先),执行如下:

DECLARE
   ret   BOOLEAN;
BEGIN
   ret := DBMS_REPAIR.ONLINE_INDEX_CLEAN (315614);
END;
/

--以sys用执行ok.

CREATE OR REPLACE TRIGGER SYS.tri_prevent_drop_truncate
   BEFORE TRUNCATE OR DROP ON DATABASE
BEGIN
   IF ora_dict_obj_type = 'TABLE' AND ora_dict_obj_owner = 'SCOTT' and ORA_DICT_OBJ_NAME like 'SYS_JOURNAL_%'
   THEN
      raise_application_error (-20000, 'YOU CAN NOT TRUNCATE or DROP ' || ora_dict_obj_name || ' TABLE!');
   END IF;
END;
/

4.顺便做一个测试看看,如果存在SYS_JOURNAL_315614表会出现什么情况?

SCOTT@test> create table SYS_JOURNAL_315614 as select * from t where 1=0;
Table created.

SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
ALTER INDEX SCOTT.PK_T REBUILD online
*
ERROR at line 1:
ORA-08106: cannot create journal table SCOTT.SYS_JOURNAL_315614

SCOTT@test> host oerr ora 8106
08106, 00000, "cannot create journal table %s.%s"
// *Cause:  The online index builder could not create its journal table
// *Action: Rename the conflicting table or rerun the SQL statement. There
// *        may be a concurrent online index rebuild on the same object.
// *Action: rename your table in conflict or rerun the SQL statement
// *        there may be a concurrent online index rebuild on the same object.

--报ORA-08106错误,改名即可.

SCOTT@test> rename SYS_JOURNAL_315614 to txx;
Table renamed.

SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
Index altered.

--实际上上面的写法还存在问题,主要_的解析为任何字符,如果存在SYSaJOURNALa315614这样的对象一样能删除.
SCOTT@test> rename txx to SYSaJOURNALa315614;
Table renamed.

SCOTT@test> drop table SYSaJOURNALa315614 purge ;
Table dropped.

--如果写正则表达式还复杂1点,修改如下:

CREATE OR REPLACE TRIGGER SYS.TRI_PREVENT_DROP_TRUNCATE
   BEFORE TRUNCATE OR DROP ON DATABASE
BEGIN
   IF ora_dict_obj_type = 'TABLE' AND ora_dict_obj_owner = 'SCOTT' and ORA_DICT_OBJ_NAME not like 'SYS\_JOURNAL\_%' escape '\'
   THEN
      raise_application_error (-20000, 'YOU CAN NOT TRUNCATE or DROP ' || ora_dict_obj_name || ' TABLE!');
   END IF;
END;
/

5.其它还有什么情况呢?自己也想象不出来.只能等问题出现了.

目录
相关文章
|
2月前
|
算法 关系型数据库 MySQL
drop、truncate 和 delete 的区别
drop、truncate 和 delete 的区别
|
7月前
|
SQL 存储 数据库
sql数据库中的 delete 与drop的区别
sql数据库中的 delete 与drop的区别
167 1
|
10天前
|
存储 关系型数据库 MySQL
Mysql数据库清空表 truncate和delete
Mysql数据库清空表 truncate和delete
16 0
|
SQL 存储 数据库
Drop、Truncate和Delete究竟怎么删除
在数据库种有三个对表中数据进行删除的语法,分别是Drop、Truncate和Delete。关于它们的区别和相同的地方也是在面试的过程中经常遇到的。平时也是用了就用了,哪个用的习惯就用哪个。不过既然都是删除为什么还要有三个不同的语句呢?说明它们之间肯定有着不一样的地方。邓爷爷说过实践是检验真理的唯一标准。这里就通过实际的例子总结一下它们之间的一些异同点,也加深一下自己的印象。
189 0
Drop、Truncate和Delete究竟怎么删除
|
SQL 存储 关系型数据库
delete、truncate、drop,千万别用错了。。
MySQL删除数据的方式都有哪些? 咱们常用的三种删除方式:通过 delete、truncate、drop 关键字进行删除;这三种都可以用来删除数据,但场景不同。 一、从执行速度上来说 drop > truncate >> DELETE
150 0
delete、truncate、drop,千万别用错了。。
|
Web App开发 关系型数据库
Truncate/Delete/Drop table的特点和区别
之前一直对Truncate/Delete/Drop认识的不是很清晰,所以特意的翻了一下MySQL5.7 Reference Manual,准备系统的了解一下,这里是一些翻译,外加一点自己的认知。
1114 0
|
SQL 机器学习/深度学习 Oracle
[20180630]truncate table的另类恢复2.txt
[20180630]truncate table的另类恢复2.txt --//上个星期做了truncate table的另类恢复,通过修改数据块的段号,再通过rowid定位收集数据,达到修复的目的.
1533 0
|
数据库管理
[20180627]truncate table的另类恢复.txt
[20180627]truncate table的另类恢复.txt --//前几天看链接http://www.xifenfei.com/2018/06/truncate-table-recovery.
1338 0