トランザクションの途中で、テーブルの切り捨てなどのDDLステートメントを実行すると、トランザクションがコミットされます。
これが常に当てはまり、定義上、トランザクションをコミットする代わりにロールバックする設定がどこかに隠されているのかどうか疑問に思いました。
ありがとう。
明確にするために編集...
切り捨て後にロールバックするつもりはありません。すでに実行されたステートメントが絶対に常にDDLの前にコミットされることを確認したいだけです。誰かが私のコードを破壊するように設定できるシステムプロパティがどこかにないことを確認したいだけです。
DDLの前後にコミットする必要があることは理解していますが、概念的には、DDLの前にロールバックすることで同じ整合性要件を達成できると考えていましたそしてその後のコミット。
いいえ、常にコミットします。
ロールバックする場合は、DDLの前に行う必要があります。
DDLを既存のトランザクションから分離する場合は、独自の個別のトランザクションで実行する必要があります。
技術的には [〜#〜] ddl [〜#〜] 実行前と実行後にコミットを実行します。
はい、Cookieからの同じリンクですが、これは同じ問題の別の側面です。コミットは1つだけではなく、2つあり、その直前と直後に発生することを理解することが重要です。
実際には、可能であればコミットします。正常にコミットできない場合、DDLは失敗します。コミットを停止する1つの方法は、遅延制約に違反することです。
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
したがって、暗黙的なコミットを防止したい場合は、遅延制約のあるダミーテーブルを用意してください。違反している行を挿入すると、その違反が解決されるまで(たとえば、行が削除されるまで)トランザクションをコミットできないようにすることができます。
テーブルの切り捨てまたはテーブルの変更またはテーブルの作成は常にコミットを引き起こします。
テーブルを切り捨てるときに、なぜロールバックしたいのですか?
ここ は役立つかもしれないAskTomの記事です。記事から:
「なぜDDLステートメントが自律型トランザクション内で実行されないのか(シーケンスのように)、保留中のユーザートランザクションに影響を与えないのか疑問に思いました...
明確にできますか?
フォローアップ2003年6月24日-米国/東部標準時午前7時:
それは、そのようにしないのと同じくらい「混乱」するでしょう。とにかく、あなたはatransを持っているので、あなたが望むなら、あなたはそうすることができます。 「」
したがって、本当に必要な場合は、DDLを自律トランザクション内に固定して、必要なことを実行できます。
編集:要点は、Oracleを「破壊」するために明示的な長さに行かない限り、DDLはコミットを実行するということです。とはいえ、特定の時点でコミットを実行する必要がある場合は、明示的に実行しないのはなぜですか?
DDLステートメントは、実行後に常に自動コミットを実行します。
(サーバー側で)障害が発生した場合にロールバックする場合は、特定のフラグを設定して障害を示し、適切なアクションを実行できます。
例:テーブルtable1を作成した場合。同時に、他のテーブルにレコードを挿入しています。
しかし、特定の理由(set flag = true)のために挿入が失敗しました。その場合、createステートメントはddlステートメントであるためロールバックできません。したがって、テーブル(table1)を削除することで、データベース内の変更を元に戻すことができます。 Dropステートメントによるフラグの値。
自律型トランザクションについては、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を実行しようとすると、競合が発生します。 2つのトランザクションが互いにブロックしているのと同じように。そして、それらが独立したオブジェクトである場合、実行順序が重要である理由がわかりません。
「常に/決して」は強すぎる。たとえば、Oracle18cの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