2017-12-18 19 views
0

我有一箇舊的客戶端軟件,它有一個連接的oracle數據庫用於持久化。作爲接口,客戶端軟件只允許調用函數和過程。我幾乎可以完全訪問數據庫,即我可以定義函數和過程。由於接口,只有函數可以返回值,我不能使用過程的參數選項OUT函數調用中的DML

現在我只是想讀從表中的值:

SELECT value FROM myTable WHERE id = 42; 

,又重新增加值:

UPDATE myTable SET value = value + 1 WHERE id = 42; 

我可以用一個函數的SELECT語句,併爲一個程序更新並連續呼叫。這裏的問題是客戶端不存在交易。因此,在select和update之間另一個線程可能會得到錯誤的值。

所以我的問題是,我該如何使用在交易雙方通話,而無需使用交易...

嘗試的途徑:

  • 使用匿名PL/SQL塊 - >語法不受客戶支持。
  • 將兩個調用放在一個函數中 - >在select語句中不允許DML。
  • PRAGMA AUTONOMOUS_TRANSACTION - >我聽說這是一件壞事,不應該使用。
+2

'Functions'旨在*** ***不是有副作用。如果你想要改變數據庫的狀態,那麼你需要使用'Procedure'。 – MatBailie

+1

如果你想要一個簡單的'計數器',並且在這種情況下沒有其他事情發生,你可以考慮'CREATE SEQUENCE'? – MatBailie

+0

如果我使用過程(並且不能使用'OUT'),我需要兩個不是線程保存的數據庫調用 – Thanthla

回答

1

可以做DML,如下面所示的函數裏面,但我要強調 - 採取的其他意見留意。看看使用一個序列(甚至是多個序列),因爲在函數內部做DML通常是一個壞主意,因爲函數調用的執行次數(如果從SQL調用的話)不是確定性的。另外,如果大量使用,還有可擴展性問題。並且在多用戶環境中,您需要處理鎖定/序列化,否則您將需要多個會話才能返回相同的整數值。

所以......在這一切之後,你仍然頭這條道路:-(

SQL> create table t (x int); 

Table created. 

SQL> insert into t values (0); 

1 row created. 

SQL> 
SQL> create or replace 
    2 function f return int is 
    3 pragma autonomous_transaction; 
    4 retval int; 
    5 begin 
    6 update t 
    7 set x = x + 1 
    8 returning x into retval; 
    9 commit; 
10 return retval; 
11 end; 
12/

Function created. 

SQL> 
SQL> select f from dual; 

     F 
---------- 
     1 

1 row selected. 

SQL> select * from t; 

     X 
---------- 
     1 

1 row selected. 

SQL> select f from dual; 

     F 
---------- 
     2 

1 row selected. 

SQL> select * from t; 

     X 
---------- 
     2 

1 row selected. 

SQL> select f from dual; 

     F 
---------- 
     3 

1 row selected. 

SQL> select * from t; 

     X 
---------- 
     3 

1 row selected. 
+0

謝謝你的回答。我知道你提出的解決方案,以及它的問題。因此,我很可能會降低一致性並執行閱讀和更新程序的功能。執行此工作流程的兩個線程交錯的機會非常低,我可能會冒這個風險。 – Thanthla