Oracle ROLLBACK与TRUNCATE TABLE

问题描述 投票:0回答:4

我有两个临时表,一个跨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系统,因此所涉及的每个人都对权限和角色过于敏感

oracle rollback truncate dml
4个回答
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,然后重复回滚并插入第二个:

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中的数据,而不会触及第一个GTT中的数据。


至于特权,from the documentation for truncate

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

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


0
投票

DBA是不是授予您TRUNCATE权限。原因?虽然您使用的方法可能并不适合您,但它确实允许您在不授予不必要权限的情况下完成任务。许多组织都遵守Principle of Least Privilege,如果您的组织是众多组织中的一员,那么DBA只是在做自己的工作。

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

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


0
投票

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

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


0
投票

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

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

myConnection.BeginTrans:

myConnection.CommitTrans:

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

© www.soinside.com 2019 - 2024. All rights reserved.