如果您正处于事务中途并执行DDL语句(例如截断表),则事务将提交。
我想知道这是否总是如此,按照定义,或者是否隐藏某个设置回滚事务而不是提交。
感谢。
编辑以澄清......
我不打算在截断后回滚。我只是想确认已经执行的语句绝对总是将在DDL之前提交。只是想确保在某个地方没有人可以设置破坏我的代码的系统属性。
我理解在DDL之前和之后需要提交,但从概念上讲,我认为在DDL和之后的提交之前使用回滚可以实现相同的一致性要求 。
答案 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 强>