Oracle中的函数与过程

时间:2014-08-21 06:32:21

标签: oracle stored-procedures plsql oracle11g stored-functions

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

  1. 如果我不能在sql语句中调用过程,那么,我会写一个函数来做同样的工作。
  2. 程序不返回值,好吧,在任何dml操作之后我只返回sql%rowcount或1(成功),0(异常)
  3. 程序和函数都可以通过OUT / IN OUT参数将变量传递给调用环境
  4. 我听说主要区别在于性能,'程序比功能更快'。但没有任何细节。

    提前致谢。

7 个答案:

答案 0 :(得分:44)

区别在于 - 函数必须按默认定义返回值(任何类型),而在过程中,您需要使用OUTIN OUT参数等参数来获取结果。您可以在普通SQL中使用函数,因为您无法在SQL语句中使用过程。

功能和程序之间的一些差异

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

  2. 函数可用于典型的SQL语句,如SELECTINSERTUPDATEDELETEMERGE,而程序不能

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

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

  5. 有关功能的更多信息。程序herehere

答案 1 :(得分:13)

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

在极少数情况下:

  • 当启用内联时,过程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;
/

<强>结果

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

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

为什么差异无关紧要

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

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

答案 2 :(得分:9)

国家变化与非国家变化

Romo Daneghyan's answer之上,我总是把差异视为他们在程序状态下的行为。也就是说,概念上

  • 程序可以改变某些状态,无论是参数还是环境(例如,表中的数据等)。
  • 函数不会更改状态,您可能希望调用特定函数不会修改任何数据/状态。 (即functional programming
  • 的概念

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

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

答案 3 :(得分:2)

  1. 程序可能会或可能不会返回值,但函数会返回值。

  2. 程序使用参数returnvalue目的但函数returnstatment提供。

  3. 程序使用数据操作,但函数使用数据计算。
  4. 过程执行时间不使用select语句而是使用select语句。这些是它的主要区别。

答案 4 :(得分:1)

这是一个很大的问题,据我所知,尚未真正得到回答。问题不是“函数和过程之间有什么区别?”相反,它是“当我可以使用函数执行相同的操作时,为什么要使用过程?”

我认为真正的答案是“这只是约定。” 并且按照约定,这是其他开发人员习惯并期望的,因此您应该遵循约定。但是没有功能上的原因将子程序作为函数编写为程序。一个例外可能是存在多个OUT参数时。

Steven Feuerstein在他的6th edition of Oracle PL/SQL Programming中建议您为过程保留OUTIN OUT参数,并且仅通过RETURN子句返回函数中的信息(第613页)。但同样,这样做的原因是惯例。开发人员不希望函数具有OUT参数。

我写了一个longish post here,主张您仅应在函数无法完成工作时使用过程。我个人更喜欢函数,并希望约定默认使用函数,但是我认为更好的做法是接受我无法更改的内容并屈服于实际约定,而不是我希望的约定

答案 5 :(得分:-2)

我认为主要区别在于:

函数不能包含DML Statemnt,而程序可以。 例如像Update和Insert。

如果我错了纠正我

答案 6 :(得分:-5)

据我所知,Store程序编译一次,可以一次又一次地调用,而无需再次编译。但每次调用时都会编译函数。因此,存储过程提高了性能而非功能。