Oracle ROLLBACK与TRUNCATE TABLE

时间:2017-12-28 15:55:29

标签: oracle rollback truncate dml

我有两个临时表,一个跨5个表的第一级JOIN和几十万行到一个有6列和少于10k行的表。由于一个会话中的用户使用过滤器,我有一个包含过滤结果的第二个临时表,这些过滤器会根据最终用户的心血来潮而改变。

每次过滤器更改时,我都需要对已过滤的表进行TRUNCATE并从第一个表中重新创建它。

从本质上讲,我受权限约束,DBA不想在TEMPORARY TABLE上给我TRUNCATE权限。

DELETE FROM table WHERE 1=1;

只是错误的方法(虽然有效,但不可否认)。关闭并打开一个新会话让我失去了第一个表,为第二个表打开第二个会话使我无法访问第一个表。

使用SQL Developer,它看起来像DELETE和ROLLBACK大致相同的时间,可能对ROLLBACK略有优势。

一般问题是,

  

你推荐什么?我对其中的一些理解是错误的吗?

具体问题:

  

哪个更好,ROLLBACK或DELETE(在临时表上)?

     

在Oracle中如此狭窄地控制/定义角色是否需要在临时表上限制TRUNCATE?

BTW:这是一个PeopleSoft系统,因此所涉及的每个人都对权限和角色过于敏感

4 个答案:

答案 0 :(得分:3)

11.2.0.4测试:

create global temporary table gtt (id number) on commit preserve rows;

insert into gtt42 select level from dual connect by level <= 100000;

prompt rollback
set timing on
rollback;
set timing off;

insert into gtt select level from dual connect by level <= 100000;

prompt delete
set timing on
delete from gtt;
set timing off;

insert into gtt select level from dual connect by level <= 100000;

prompt truncate
set timing on
truncate table gtt;
set timing off;

rollback
Elapsed: 00:00:00.049
delete
Elapsed: 00:00:01.036
truncate
Elapsed: 00:00:00.052

回滚与truncate大致相同,两者都比删除快得多。逻辑截断和回滚几乎完全相同。

对于您的场景,您似乎只需要将插入提交到第一个GTT中,然后重复回滚并插入到第二个GTT中:

create global temporary table gtt1 (id number) on commit preserve rows;
create global temporary table gtt2 (id number) on commit preserve rows;

insert into gtt1 (id) select level from dual connect by level <= 100;
commit;

insert into gtt2 (id) select id from gtt1 where mod(id, 2) = 0;

select count(*), min(id), max(id) from gtt2;

  COUNT(*)    MIN(ID)    MAX(ID)
---------- ---------- ----------
        50          2        100

rollback;

insert into gtt2 (id) select id from gtt1 where mod(id, 3) = 0;

select count(*), min(id), max(id) from gtt2;

  COUNT(*)    MIN(ID)    MAX(ID)
---------- ---------- ----------
        33          3         99

commit保留第一个GTT中的行; rollback然后只影响第二个GTT中的数据而不触及第一个。

至于特权,from the documentation for truncate

  

要截断表,该表必须位于您的模式中,或者您必须具有DROP ANY TABLE系统特权。

因为你不能截断表格,可能不在你的架构中;并且您可以希望了解为什么您的DBA不希望为您提供非常强大且危险的drop any table权限。您无权授予仅允许截断另一个模式中的特定表的权限。

答案 1 :(得分:0)

DBA是不是授予您TRUNCATE权限。原因?虽然您使用的方法可能不是 ,但它确实允许您完成任务而不授予您不必要的权限。许多组织都遵守Principle of Least Privilege,如果您的组织是众多组织中的一员,那么DBA就是在干什么。

此外,截断,回滚和删除是数据库的不同操作。例如,删除记录时,数据库会从相关表中删除该记录,并生成回滚段。截断表时,不再生成该回滚,这可能会阻止您在发生故障时恢复数据,这可能违反组织的保留策略。同样,执行回滚不仅会更改临时表中的数据 - it also generates redo information。如果您无法确定这些差异,为什么DBA会授予您这些权限?

一般来说,最好的方法会因很多变量而异 - 您的恢复保留政策是什么?您的组织是否在磁盘空间不足,使DBA厌倦了生成过多的日志信息?是否需要满足绩效目标?有许多因素可能产生影响。

答案 2 :(得分:0)

定义第一个临时表时,可以添加ON COMMIT子句并指示应在整个会话期间维护数据。对于第二个临时表,默认(即DELETE ROWS子句)应该在每个事务提交时截断。

因此,当用户更改搜索条件时,提交先前的搜索事务以截断数据。我相当肯定Oracle截断数据而不是删除各行。

答案 3 :(得分:0)

这是使用VBA时解决方案的一个警告。 ADO对象自动COMMIT所有事务,这会使此处显示的所有逻辑无效。

作为一种解决方法,我们需要.BeginTrans和.CommitTrans

myConnection.CommitTrans:

{{1}}

在我们打算ROLLBACK的事务之前和之后(分别)。