如果您在事务的中途执行 DDL 语句,例如截断表,则事务提交。
我想知道这是否总是如此,根据定义,还是有一个隐藏的设置会 rollback 事务而不是提交。
谢谢。
编辑澄清...
我不想在截断后回滚。我只是想确认已经执行的语句 绝对总是 将在 DDL 之前提交。只是想确保没有某个系统属性可以设置为破坏我的代码。
我理解在 DDL 之前和之后提交的必要性,但从概念上讲,我认为相同的一致性要求可以通过在 DDL 之前回滚和之后提交来实现。
如果你想回滚,你必须在 DDL 之前做。
如果您想将 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
所以如果你想防止隐式提交,有一个带有延迟约束的虚拟表。在其中插入一个违规行,您可以确保在解决违规(例如删除行)之前无法提交事务。
truncate table 或 alter table 或 create table 总是会导致提交。
做truncate table为什么要回滚?
你能澄清一下吗?
跟进 2003 年 6 月 24 日 - 美国东部时间早上 7 点:
那会和不那样做一样“令人困惑”。不管怎样,你有反式翻译,所以如果你想,你可以。 “
所以,如果你真的需要,你可以把你的 DDL 放在一个自治事务中,然后做你想做的事。
编辑: 底线是,除非您竭尽全力“颠覆”Oracle,否则 DDL 将执行提交。就是说,如果您绝对需要在某个时间点执行提交,为什么不明确地执行它呢?
如果你想让它在失败的情况下回滚(在服务器端),那么你可以设置某些标志来指示失败并采取适当的行动。
例如: 如果您已经创建了一个表 table1。 同时你在其他表中插入一条记录。
但是由于某些原因插入失败(设置标志=真)。那么在那种情况下 你不能回滚,因为 create 语句是一个 ddl 语句,所以你可以通过 Drop 语句根据标志的值删除表(table1)来撤消数据库中的更改。
示例伪代码:
Do some DML
Call autonomous function, that performs DDL
Do some more DML
rollback or commit all the DML - your choice
虽然我不认为这很有用。如果初始 DML 和 DDL 涉及同一个表/对象,它将无法工作。当您尝试执行 DDL 时,您会遇到争用。就像任何两个相互阻塞的事务一样。如果它们是独立的对象,我想我不明白为什么执行顺序很重要。
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