Oracle中的函数与过程

0bj*_*3ct 49 oracle plsql stored-procedures stored-functions oracle11g

任何人都能解释一下Oracle中函数和过程之间的主要区别是什么?如果我能用功能做所有事情,为什么我必须使用程序?

  1. 如果我不能在sql语句中调用过程,那么,我会写一个函数来做同样的工作.
  2. 程序不返回值,好吧,我会在任何dml操作后只返回sql%rowcount或1(成功),0(异常)
  3. 程序和函数都可以通过OUT/IN OUT参数将变量传递给调用环境

我听说主要区别在于性能,"程序比功能更快".但没有任何细节.

提前致谢.

Rom*_*yan 51

不同之处在于 - 函数必须通过默认定义返回值(任何类型),而在过程中,您需要使用参数(如OUTIN OUT参数)来获取结果.您可以在正常情况SQL下使用函数,因为您无法在SQL语句中使用过程.

功能与程序的区别

  1. 函数总是使用return语句返回一个值,而一个过程可能会通过参数返回一个或多个值,或者根本不能返回.虽然OUT参数仍然可以在函数中使用,但它们是不可取的,也不存在可能找到的情况需要这样做.使用OUT参数限制函数在SQL语句中使用.

  2. 功能可以像典型的SQL语句中使用SELECT,INSERT,UPDATE,DELETE,MERGE,而过程不能.

  3. 函数通常用于计算,其中过程通常用于执行业务逻辑.

  4. Oracle提供了创建" 基于函数的索引 "的功能,以提高后续SQL语句的性能.这适用于在查询的where子句中对索引列执行函数时.

有关功能的更多信息.程序在这里这里.

  • 对不起,我必须在那里纠正你.函数可能只返回一个值,但您也可以使用OUT参数从函数返回多个值,尽管您将无法在SQL语句中使用该函数.还不确定你的意思是"存储过程是预编译的执行计划,其中函数不是",程序和函数的编译操作方式相同.另外,您是否知道可以创建基于函数的索引但是无法创建基于过程的索引?你说"没有差别"然后"有差异"这不是矛盾吗? (3认同)
  • 好的。如果函数可以做程序可以做的所有事情,为什么我需要函数?:) btw 函数还可以通过 OUT 参数返回多个值。 (2认同)
  • 我已经在答案中提到过:)您可以在普通SQL中使用函数,因为您不能在SQL语句中使用过程。因此,在普通的SQL中,您需要使用函数。函数可以在select或update或delete语句中使用,而过程则不能。 (2认同)
  • 抱歉,我想说,为什么我需要手续?:) (2认同)

Jon*_*ler 14

程序和功能之间几乎没有性能差异.

在一些非常罕见的情况下:

  • IN OUT启用内联时,过程参数比函数返回更快.
  • IN OUT当禁用内联时,过程参数比函数返回慢.

测试代码

--Run one of these to set optimization level:
--alter session set plsql_optimize_level=0;
--alter session set plsql_optimize_level=1;
--alter session set plsql_optimize_level=2;
--alter session set plsql_optimize_level=3;

--Run this to compare times.  Move the comment to enable the procedure or the function.
declare
    v_result varchar2(4000);

    procedure test_procedure(p_result in out varchar2) is
    begin
        p_result := '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789';
    end;

    function test_function return varchar2 is
    begin
        return '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789';
    end;
begin
    for i in 1 .. 10000000 loop
        --Comment out one of these lines to change the test.
        --test_procedure(v_result);
        v_result := test_function;
    end loop;
end;
/
Run Code Online (Sandbox Code Playgroud)

结果

Inlining enabled:  PLSQL_OPTIMIZE_LEVEL = 2 (default) or 3
Function  run time in seconds: 2.839, 2.933, 2.979
Procedure run time in seconds: 1.685, 1.700, 1.762

Inlining disabled: PLSQL_OPTIMIZE_LEVEL = 0 or 1
Function  run time in seconds:  5.164, 4.967, 5.632
Procedure run time in seconds: 6.1, 6.006, 6.037
Run Code Online (Sandbox Code Playgroud)

上面的代码很简单,可能还需要进行其他优化.但是我在生产代码中看到了类似的结果.

为什么差别无关紧要

不要看上面的测试,并认为"程序的运行速度是函数的两倍!".是的,函数的开销几乎是过程开销的两倍.但无论哪种方式,开销都是无关紧要的.

数据库性能的关键是在SQL语句中批量执行尽可能多的工作.如果程序每秒调用一次函数或过程一千万次,那么该程序就会出现严重的设计问题.


typ*_*rpr 12

国家改变与非国家改变

除了Romo Daneghyan的回答之外,我一直认为差异是他们在程序状态下的行为.也就是说,从概念上讲,

  • 程序可以改变某些状态,参数或环境(例如,表格中的数据等).
  • 函数不会改变状态,您可能希望调用特定函数不会修改任何数据/状态.(即功能编程的基础概念)

也就是说,如果你调用了一个名为的函数generateId(...),你会期望它只进行一些计算并返回一个值.但是调用一个过程generateId ...,您可能希望它在某些表中更改值.

当然,它似乎在Oracle以及许多语言中,这不适用,也没有强制执行,所以也许只是我.