oracle11g 表数据回滚,在Oracle数据库中创建表提交后如何回滚

在Oracle数据库中运行DDL时,它会发出两个隐式提交。语句之前一个,语句完成之后一个(成功!)。

上周,我在Twitter上提出了以下测验,违反了这一规则。

oracle11g 表数据回滚,在Oracle数据库中创建表提交后如何回滚_第1张图片

我运行以下命令:

建立表格

在其中插入一行

创建另一个表

回滚

现在第一个表是EMPTY!

怎么样?!

为了帮助您,以下是我使用一些代码删除的脚本:

create

table my_tab (

c1 int

)

/

insert into my_tab values ( 1 );

create

table ora$my_tab (

c1 int

)

/

rollback;

select count (*) from my_tab;

您需要添加什么代码,以便计数返回零?

以下是此挑战的规则:

所有代码在单个会话中运行

所有语句成功(没有错误)

没有其他物体在玩(没有触发器,工作或其他恶作剧)

在创建第一个表和最后一个查询之间没有其他语句

稍等片刻,考虑这是怎么可能的。至少有三种方式。

有解决方案吗?

这是三个:

创建一个临时表

我最初的解决方案是将第二个表设为私有临时表(PTT)。这些已在Oracle Database 18c中添加,不再具有隐式提交!

这意味着在创建PTT之前运行的任何DML都不会提交。因此,执行回滚时,它将撤消插入操作。

要使用PTT,其名称的开头必须与为private_temp_table_prefix参数设置的值匹配。

因此,要使脚本正常工作,必须事先将其更改为ora $ my_!

给出以下最终解决方案:

alter session set private_temp_table_prefix = ora$my_ deferred;

create

table my_tab (

c1 int

)

/

insert into my_tab values ( 1 );

create private temporary

table ora$my_tab (

c1 int

)

/

rollback;

select count (*) from my_tab;

如果运行此命令,请确保在完成后将private_temp_table_prefix设置回ora $ ptt_!

创建一个全局临时表

虽然PTT是我想要的解决方案,但Tobias Wirtz很快就分享了另一个解决方案。您可以通过将第一个表设为全局临时表(GTT)来获得这种效果!

这有一个默认子句on commit delete rows。

因此,当创建第二张表时隐式提交生效时,GTT会清空自身!

如果您想亲自尝试以下示例:

create global temporary

table my_tab (

c1 int

)

/

insert into my_tab values ( 1 );

create

table ora$my_tab (

c1 int

)

/

rollback;

select count (*) from my_tab;

使用自主交易

另一个巧妙的解决方案来自Hans Jakob Schelbeck-Pedersen。他指出,您可以将第二个create表包装在一个自治事务中。这将提交并回滚,而与父事务无关。

因此,即使第二个create表确实提交了,这也只剩下原始事务。因此,您仍然可以将其回滚。如果您需要在18c之前的事务中途创建表,则可以使用此方法。

如果您想尝试一下:

create

table my_tab (

c1 int

)

/

insert into my_tab values ( 1 );

DECLARE

PRAGMA AUTONOMOUS_TRANSACTION;

BEGIN

execute immediate '

create

table ora$my_tab (

c1 int

)

';

END;

/

rollback;

select count (*) from my_tab;

总结

专用临时表违反了Oracle数据库中“ DDL始终提交”的长期规则。您过去学到的东西可能不再是真的。

请记住:完成任务不止一种方法。您能想到其他方法来应对原始挑战吗?欢迎评论!

你可能感兴趣的:(oracle11g,表数据回滚)