2017-08-04 26 views
1

我在主 - 細節組合中有兩個表,User和Employee(這是因爲Employee是一種用戶類型,還有其他類型的用戶)。當用戶被添加到系統中時,在很多情況下,我還必須向Employee添加詳細信息,更新這些表時也會發生同樣的情況。這意味着我必須保證這兩個操作的原子性(插入和更新)。調用過程時的PL/SQL事務

一個要求是使用存儲的包和過程來執行CRUD(表從不直接使用)。

我寫在PL/SQL下面這個簡單的例子,試圖瞭解交易在這方面是如何工作的:

CREATE TABLE test_a 
(
    campo_1 VARCHAR2(10) NOT NULL 
); 
CREATE TABLE test_b 
(
    campo_2 VARCHAR2(10) NOT NULL 
); 
/
CREATE PROCEDURE ins_a 
(
    texto_1 IN VARCHAR2 
) 
IS 
BEGIN 
    INSERT INTO test_a (campo_1) 
    VALUES (texto_1); 
END; 
/
CREATE PROCEDURE ins_b 
(
    texto_2 IN VARCHAR2 
) 
IS 
BEGIN 
    INSERT INTO test_b (campo_2) 
    VALUES (texto_2); 
END; 
/
CREATE PROCEDURE ins_todos 
(
    texto_1 IN VARCHAR2, 
    texto_2 IN VARCHAR2 
) 
IS 
BEGIN 
    ins_a(texto_1); 
    ins_b(texto_2); 
END; 
/

如果我運行

begin 
ins_todos('alfa', '1234567846513216549'); 
end; 
/

過程明顯失敗,因爲長度的第二個參數,但第一個過程不插入第一個參數,這讓我感到意外,因爲我預計第一個過程無論如何都會成功。

我的問題是:

  • 這是因爲某處運行的隱性事務的?
  • 如果是這樣,這是否讓我免於在我的PL/SQL代碼中顯式管理事務? (我仍然認爲我應該明確地使用代碼中的交易。)
  • 如何確保在另一個過程中調用多個過程將尊重回滾和提交?我的目的是如果其中一個引發異常,所有內部過程必須回滾。
  • 最後,我可以在PL/SQL中執行所有這些操作,還是需要在C#數據訪問層中對其進行管理?
+1

'這是因爲隱式事務在某處運行,當你執行過程開始事務時。如果錯誤 - 數據庫回滾所有更改 – are

回答

2

「我預計第一個程序無論如何都會成功。」

它確實成功了,在它自己的範圍內。但它從另一個程序ins_todos()調用,因爲ins_b()失敗而失敗。

「這是因爲隱式事務在某處運行嗎?「

事務是執行到發行COMMIT或ROLLBACK。您的代碼不包含明確的COMMIT,所以是的,它是一個隱式事務工作。

的所有操作的總和

「如果是這樣,這是否讓我免於在我的PL/SQL代碼中顯式管理事務? (我仍然認爲我應該明確地使用代碼中的交易)。「

自由是一個棘手的概念,您需要清楚地瞭解哪些操作構成交易,即什麼是工作單元。以確保數據庫保持有效狀態,這意味着您需要清楚何時發出COMMIT語句以及如何處理錯誤。

「如何確保調用多個另一個程序中的程序將尊重回滾和提交?我的目的是,如果其中之一拋出異常的所有內部程序必須回滾。「

您的測試代碼演示,這是默認的行爲。因此,所有你需要做的是什麼。

」我能做到這一切在PL/SQL或者我需要在我的C#數據訪問層來管理呢?」

這是一個建築的決定。通常它是在這是調用堆棧的頂部代碼負責完成交易,所以這取決於你如何編寫你的應用程序on:使用你的例子,也許COMMIT應該在ins_todos()過程中,或者它應該屬於調用它的C#。

所有的PL/SQL程序都應該有異常處理,包括日誌記錄。是否包含ROLLBACK是一個類似的架構決策。較低級別的PL/SQL程序通常僅用於在調用堆棧中引發或重新引發異常。通常避免使用pragma autonomous_transaction。這會創建嵌套的事務,這會使數據庫處於不一致的狀態,除非您知道自己在做什麼。對於自治事務來說,真正的用例非常少:登錄到一個表是最常見的用例。

+1

自由是通往高速公路的塵土飛揚的道路。 –

0

當您執行ins_todos過程時,由於varchar2長度限制爲10個字符,因此您希望調用ins_b失敗。此失敗回滾當前事務中的所有sql語句。事務首先插入到test_a表中。

如果您確實希望第一次插入sql獨立於第二次提交,那麼您將使用pragma autonomous_transaction。

例如:

CREATE or replace PROCEDURE ins_a 
(
    texto_1 IN VARCHAR2 
) 
IS 
    pragma autonomous_transaction; 
BEGIN 
    INSERT INTO test_a (campo_1) 
    VALUES (texto_1); 
    commit; 
END; 
/

這將提交插入到test_a不管二次插入成功或失敗。

這裏需要了解的重要信息是,除非被自動事務處理,否則任何異常除非被捕獲並處理,否則將導致事務回滾所有工作。

+1

OP說:「我的目的是所有內部過程必須回滾,如果其中一個引發異常」,所以'pragma autonomous_transaction'正是他們不想要的。 – APC