Sql 函数调用中的DML

Sql 函数调用中的DML,sql,oracle,plsql,stored-functions,Sql,Oracle,Plsql,Stored Functions,我有一个旧的客户端软件,它有一个连接的oracle数据库用于持久性。作为接口,客户端软件只允许调用函数和过程。我几乎可以完全访问数据库,也就是说,我可以定义函数和过程。由于接口的原因,只有函数才能返回值,我不能使用过程的OUT参数选项 现在我只想从表中读取一个值: SELECT value FROM myTable WHERE id = 42; 然后增加值: UPDATE myTable SET value = value + 1 WHERE id = 42; 我可以为select语句使用一

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

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

SELECT value FROM myTable WHERE id = 42;
然后增加值:

UPDATE myTable SET value = value + 1 WHERE id = 42;
我可以为select语句使用一个函数,为update和call分别使用一个过程。这里的问题是客户端不存在事务。因此,在select和update之间,另一个线程可能会得到错误的值

所以我的问题是,如何在不使用事务的情况下在事务中使用这两个调用

尝试过的方法:

使用匿名PL/SQL块->客户端不支持该语法。 将两个调用放在一个函数中->select语句中不允许使用DML。 PRAGMA autonomy_TRANSACTION->我听说这是件坏事,不应该使用。 您可以在函数内执行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.

功能旨在不产生副作用。如果你想改变数据库的状态,那么你需要使用一个过程。如果你想要一个简单的计数器,并且在这个场景中没有别的事情发生,你可以考虑创建序列吗?如果我使用这个过程,并且不能使用,我需要两个不是线程保存的数据库调用。然后,如果您只有一个计数器,而不是一个充满计数器的表,或者需要有人修复您的软件体系结构,则需要类似于序列的东西。您已经列出了所有不能使用事务、过程等的内容,因此切断了数据库做您想做的事情的能力。如果您不能使用您应该使用的工具,请修复阻止您使用正确工具的问题。没有选择后触发器。谢谢您的回答。我知道你提出的解决方案,以及其中的问题。因此,我很可能会放弃一致性,执行读取函数和更新过程。两个线程交叉执行此工作流的可能性非常低,我可能会冒这个风险。