函数调用里面的DML

时间:2017-12-18 10:17:41

标签: sql oracle plsql stored-functions

我有一个旧的客户端软件,它有一个连接的oracle数据库用于持久化。作为接口,客户端软件仅允许调用函数和过程。我几乎可以完全访问数据库,即我可以定义函数和过程。由于接口,只有函数可以返回值,我不能使用过程的OUT参数选项。

现在我只想从表中读取一个值:

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 - >我听说这是件坏事,不应该使用。

1 个答案:

答案 0 :(得分: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.