我可以在 oracle 中使用用户定义的函数删除行吗?

Posted

技术标签:

【中文标题】我可以在 oracle 中使用用户定义的函数删除行吗?【英文标题】:Can I delete rows using user defined functions in oracle? 【发布时间】:2011-05-11 14:18:18 【问题描述】:

我创建了一个用户定义的函数来删除一些数据。它不适用于删除,但适用于选择。我是甲骨文 9i。

函数是这样的:

create or replace function UFN_PURGEDATA(INPUTID IN VarChar2) return number is
  Result number;
begin

  Result := 0;


   DELETE FROM MyTable WHERE MyTable.ID=INPID;

  COMMIT; 

   Result := 1;
 EXCEPTION WHEN OTHERS THEN    

  return(Result);
end UFN_PURGEDATA;

然后我使用select UFN_PURGEDATA('test') from dual 运行它,但得到了结果0

【问题讨论】:

【参考方案1】:

您的问题的答案是“否”。

如果您删除错误“处理”,您会发现删除失败,并出现如下异常:

ORA-14551: 无法执行 DML 查询内的操作

即您不能在 SELECT 语句中调用的函数中执行插入、更新或删除操作。

要在 IDE 或 SQL Plus 中执行此函数,请将其包装在更多的 PL/SQL 中,如下所示:

declare
  l_result number;
begin
  l_result := my_function(123);
end;

但是,您需要先在函数中添加 RETURN 语句,否则会失败。

(注意,我在上面用引号说“处理”是因为它确实是“处理不当”——它以一种非常无益的方式完全掩盖了实际问题。)

【讨论】:

非常感谢您的回答。那么我该如何执行这个功能呢?我的最终目标是在 java 程序中调用这个函数。 -1 此答案中明确的“否”是不正确的。可以使用自主事务(参见 jonearles 的回答)。这种方法存在问题,但仍有可能。【参考方案2】:

如果添加 PRAGMA AUTONOMOUS_TRANSACTION,则可以在 SELECT 中使用的函数内执行 DML。例如:

create or replace function UFN_PURGEDATA(INPUTID IN VarChar2) return number is
    pragma autonomous_transaction;
begin
  DELETE FROM MyTable WHERE MyTable.ID=INPUTID;
  COMMIT; 
  return 1;
  EXCEPTION WHEN OTHERS THEN    
  return 0;
end UFN_PURGEDATA;
/

但如果可能,您肯定希望避免这种方法。一般来说,如果一个函数在 SELECT 中使用,我们无法知道它会被执行多少次。

【讨论】:

【参考方案3】:

是的,您可以使用 Oracle 中的用户定义函数删除行,但不能从 SELECT 语句中删除。

您的代码有几个问题: - 如果您的函数没有引发异常,则不会返回值 - 不得在 SELECT 语句中使用执行 DML 的函数;如果你删除你的异常块,你会得到一个 ORA-14551

【讨论】:

也感谢您的帮助。请告诉我如何达到我的目标。我想从 java 程序中调用这个函数,但也想在 PL/SQL Developer 中测试它。 您应该能够从 Java 调用它,就像使用(匿名)PL/SQL 块的 PL/SQL 一样,使用绑定变量作为返回值 - 请参阅 Tony Andrews 的答案示例.【参考方案4】:

为什么不创建一个带有 OUT 参数返回数字的过程(而不是函数)?如果不使用自治事务技巧,Oracle 不希望您运行具有“副作用”的函数(用于选择)(可以理解为什么我们不希望选择导致 DML 更改)。

【讨论】:

以上是关于我可以在 oracle 中使用用户定义的函数删除行吗?的主要内容,如果未能解决你的问题,请参考以下文章

防止在 Oracle 中删除某些行

如何在 Oracle 的 where 子句中使用用户定义的函数?

是否可以将条件传递给 Oracle 用户定义函数?

oracle如何删除用户?

通过数据库链接在 oracle 中调用存储函数(返回用户定义类型的数组)

Oracle 的用户自定义聚合函数可以定义为与两列一起使用吗?