2017-12-18 224 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