DDL语句是否总是为您提供隐式提交,或者您是否可以获得隐式回滚?

时间:2009-04-08 15:49:22

标签: sql oracle transactions ddl

如果您正处于事务中途并执行DDL语句(例如截断表),则事务将提交。

我想知道这是否总是如此,按照定义,或者是否隐藏某个设置回滚事务而不是提交。

感谢。

编辑以澄清......

我不打算在截断后回滚。我只是想确认已经执行的语句绝对总是将在DDL之前提交。只是想确保在某个地方没有人可以设置破坏我的代码的系统属性。

我理解在DDL之前和之后需要提交,但从概念上讲,我认为在DDL和之后的提交之前使用回滚可以实现相同的一致性要求

8 个答案:

答案 0 :(得分:15)

不,它会一直提交。

如果要回滚,则必须在DDL之前执行此操作。

如果要将DDL与现有事务隔离开来,则必须在其自己的单独事务中执行它。

答案 1 :(得分:15)

技术上DDL在执行之前执行提交,并在执行之后执行。

是Cookie中的相同链接,但这是同一问题的不同方面。理解它不仅仅是一次提交至关重要,有两种提交,它们发生在之前和之后。

答案 2 :(得分:5)

实际上它会提交。如果无法成功提交,则DDL将失败。 阻止它提交的一种方法是违反延迟约束。

create table fred (id number);
alter table fred add constraint id_ck check (id >0) initially deferred;
insert into fred values (-1);
SQL> create table junk(val number);
create table junk(val number)
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02290: check constraint (GC_REF.ID_CK) violated
SQL> desc junk
ERROR:
ORA-04043: object junk does not exist

因此,如果要阻止隐式提交,请使用具有延迟约束的虚表。在其中插入违规行,您可以确保在解决该违规(例如删除行)之前无法提交事务。

答案 3 :(得分:3)

truncate table alter table create table 始终会导致提交。

为什么要在执行截断表时回滚?

答案 4 :(得分:3)

Here是一篇可能有用的AskTom文章。来自文章:

“我想知道为什么DDL语句不会在自治事务中执行(如序列那样),因此它们不会影响任何挂起的用户事务......

你能澄清一下吗?

跟进2003年6月24日 - 美国东部时间早上7点:

这样做会让人感到“困惑”。无论如何,你有atrans所以如果你愿意,你可以。 “

所以,如果你真的需要,你可以将你的DDL放在自治交易中并做你想做的事。

编辑: 最重要的是,除非你明确指出“颠覆”Oracle,否则DDL将执行提交。也就是说,如果你绝对要求在某一点执行提交,为什么不直接执行呢?

答案 5 :(得分:1)

DDL语句总是在执行后执行自动提交。

如果您希望在发生故障时(在服务器端)回滚,则可以设置某些标志以指示失败并采取相应的措施。

例如: 如果你已经创建了一个表table1。 同时你在其他表格中插入一条记录。

但由于某些原因导致插入失败(set flag = true)。然后就此而言 您无法回滚,因为create语句是一个ddl语句,因此您可以通过Drop语句删除表(table1)取决于flag的值来撤消数据库中的更改。

答案 6 :(得分:0)

我同意DCookie和Tom的自主交易。我也要说明这一点。

伪代码示例:

Do some DML
Call autonomous function, that performs DDL
Do some more DML
rollback or commit all the DML - your choice

我不认为这是非常有用的。如果初始DML和DDL触摸相同的表/对象,则它不起作用。当您尝试执行DDL时,您将收到争用。就像任何阻止对方的两个交易一样。如果他们是独立的对象,我想我不明白为什么执行顺序很重要。

答案 7 :(得分:0)

“永远/永远”太强大了。例如,来自Oracle 18c的CREATE PRIVATE TEMPORARY TABLE之类的DDL不会COMMIT您的交易。

正常情景:

CREATE TABLE t(i INT);
INSERT INTO t(i) VALUES(21);

CREATE TABLE x(i INT);   -- same for CREATE GLOBAL TEMPORARY TABLE y(i INT); 
ROLLBACK;

SELECT * FROM t;
-- Output:
-- 21

但是如果你创建私人表:

CREATE TABLE t(i INT);
INSERT INTO t(i) VALUES(21);

CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp(i INT);  
-- or
CREATE PRIVATE TEMPORARY TABLE ORA$PTT_tab
AS
SELECT 1 AS c FROM dual;

ROLLBACK;
SELECT * FROM t;
-- Output:
-- no data found

<强> db<>fiddle demo