• 存储过程和函数


    存储过程  函数
     用于在数据中完成特定的操作或者任务  用于特定的数据
     程序头部申明procedure  程序头部申明function
     程序头部申明时不需要描述返回类型  程序头部申明时需要描述返回类型,而且PL/SQL至少要包含一个有效的return语句
     可以使用in/out/ in out  可以使用in/out/in out
     可作为一个独立的PL/SQL语句来执行  不能立即执行,必须作为表达式的一部分
     可以通过out.int out  通过return语句返回一个值
     SQL语句中不得调用任何存储过程  SQL语句中可以调用函数

       

    存储过程和函数目的是为了 可重复地 执行操作数据库的sql语句的集合。

    区别是写法和调用上。

    写法上:存储过程的参数列表可以有输入参数、输出参数、可输入输出的参数;

                函数的参数列表只有输入参数,并且有return <返回值类型,无长度说明>。

    返回值上:

        存储过程的返回值,可以有多个值,

               函数的返回值,只有一个值。

    调用方式上:

        存储过程的调用方式有:

    1)、exec <过程名>;

    2)、execute <过程名>;

    3)、在PL/SQL语句块中直接调用。

                函数的调用方式有:

          在PL/SQL语句块中直接调用。

                     具体分为:

      ----调用FUNCTION add_three_numbers

      ----1. 位置表示法调用函数

      BEGIN

      dbms_output.put_line(add_three_numbers(2,4,5));

      END;

      ----2. 命名表示法调用函数

      BEGIN

      dbms_output.put_line(add_three_numbers(b=>3, a=>4,c=>2));

      END;

      ----3. 混合使用位置表示法和命名表示法调用函数

      BEGIN

      dbms_output.put_line(add_three_numbers(3, b=>4,c=>2));

      END;

      ----4. 排除表示法

      BEGIN

      dbms_output.put_line(add_three_numbers(12,c=>2));

      END;

      ----5. sql调用表示法 --混合表示法

      SELECT add_three_numbers(3, b=>4,c=>2) FROM DUAL;

     

    ----1. 该函数接受3个可选参数,返回3个数字的和

      CREATE OR REPLACE FUNCTION add_three_numbers

      (

      a NUMBER:=0, b NUMBER:=0, c NUMBER:=0

      )

      RETURN NUMBER IS

      BEGIN

      RETURN a+b+c;

      END;

          

    存储过程:

    基本语法:

    create procedure <过程名>(<参数列表,无参时忽略>)

    as|is

    变量声明、初始化

    begin

    业务处理、逻辑代码

    exception

    异常捕获、容错处理

    end <过程名>;

    参数:<参数名> in|out|in out <参数类型,无长度说明> ,如:v_name varchar2

    in:入参

    out:出参

    in out:出入参

    注:as|is表示as或is

    调用语法:

    1)、exec <过程名>;

    2)、execute <过程名>;

    3)、在PL/SQL语句块中直接调用。

    例:

    create or replace procedure up_wap(v_param1 in out varchar2,v_param2 in out varchar2)

    is

    v_temp varchar2(20);

    begin

    dbms_output.put_line('交换前参数1:'||v_param1||' 参数2:'||v_param2);

    v_temp:=v_param1;

    v_param1:=v_param2;

    v_param2:=v_temp;

    dbms_output.put_line('交换后参数1:'||v_param1||' 参数2:'||v_param2);

    exception

    when others then dbms_output.put_line('There is a error when the procedure up_wap executing!');

    end up_wap;

    /

    -- 调用存储过程

    declare

    v_param1 varchar2(20):='param1';

    v_param2 varchar2(20):='param2';

    begin

    up_wap(v_param1 => v_param1,v_param2 => v_param2);

    end;

    /

     自定义函数(function)

    基本语法:

    create function <函数名>(<参数列表,无参时忽略>)

    return <返回值类型,无长度说明>

    as|is

    变量声明、初始化

    begin

    业务处理、逻辑代码

    return <返回的值>;

    exception

    异常捕获、容错处理

    end <函数名>;

    参数:in 入参

    注:只有入参的类型。

    在存储过程和自定义函数中的参数的传递(入参和出参)不能使用%type或%rowtype匹配,不能使用空值null,但是存储过程可以返回空值。

    例:

    create function uf_select_name_by_id_test(v_id in number)

    return varchar2

    is

    v_name t_test.t_name%type;

    begin

    select t_name into v_name from t_test where t_id=v_id;

    return v_name;

    exception

    when others then dbms_output.put_line('error');

    end uf_select_name_by_id_test;

    /

    select uf_select_name_by_id_test(1) 姓名 from dual;-- select调用

    declare --pl/sql语句块调用

    v_name varchar2(20);

    begin

    v_name:=uf_select_name_by_id_test(1);

    dbms_output.put_line('name = '||v_name);

    end;   

    SQL SERVER中: 本质上没区别。只是函数有如:只能返回一个变量的限制。而存储过程可以返回多个。而函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行。执行的本质都一样。      函数限制比较多,比如不能用临时表,只能用表变量.还有一些函数都不可用等等.而存储过程的限制相对就比较少      1. 一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。

        2. 对于存储过程来说可以返回参数,而函数只能返回值或者表对象。

        3. 存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用,由于函数

           可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。

        4. 当存储过程和函数被执行的时候,SQL Manager会到procedure cache中去取相应的查询语句,如果在

           procedure cache里没有相应的查询语句,SQL Manager就会对存储过程和函数进行编译。

        Procedure cache:中保存的是执行计划,当编译好之后就执行procedure cache中的execution plan,之后SQL SERVER会根据每个execution plan的实际情况来考虑是否要在cache中保存这个plan,评判的标准一个是这个execution plan可能被使用的频率;其次是生成这个plan的代价,也就是编译的耗时。保存在cache中的plan在下次执行时就不用再编译了。

    存储过程和函数具体的区别:

        存储过程:可以使得对的管理、以及显示关于及其用户信息的工作容易得多。存储过程是 SQL 语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理。存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量、有条件执行以及其它强大的编程功能。存储过程可包含程序流、逻辑以及对数据库的查询。它们可以接受参数、输出参数、返回单个或多个结果集以及返回值。

        可以出于任何使用 SQL 语句的目的来使用存储过程,它具有以下优点:

        (1)功能强大,限制少。

        (2)可以在单个存储过程中执行一系列 SQL 语句。

        (3)可以从自己的存储过程内引用其它存储过程,这可以简化一系列复杂语句。

        (4)存储过程在创建时即在上进行编译,所以执行起来比单个 SQL 语句快。

        (5)可以有多个返回值,即多个输出参数,并且可以使用SELECT返回结果集。

        函数:是由一个或多个 SQL 语句组成的子程序,可用于封装代码以便重新使用。自定义函数诸多限制,有许多语句不能使用,许多功能不能实现。函数可以直接引用返回值,用表变量返回记录集。但是,用户定义函数不能用于执行一组修改全局数据库状态的操作。

    补充:

        前面有一句,“可以处于任何使用SQL语句的目的来使用存储过程”。这里想说的是,有些时候有些地方使用函数或许会更方便些。例如,存在这样一个表:Temperature(Year, Month, Day, T02, T08, T14, T20),其中Year,Month,Day是时间字段,T02, T08, T14, T20是指2时、8时、14时、20时四个时刻对应的温度值,这些温度值可为空。现在,要求统计2008年5月份的平均温度。

        或许大家会这样写:

        SELECT (AVG(T02)+AVG(T08)+AVG(T14)+AVG(T20))/4 FROM Temperature WHERE Year=2008 AND Month=5

        如果不考虑空值的话,这样完全正确,但是考虑空值的话,如果根本没有统计02时的温度,那么AVG(T02)将为NULL,然后进行所有运算的结果都将为 NULL。这显然是不正确的。

        这里可以创建一个自定义函数,然后使用一个SELECT语句即可查询:

        SELECT AVG(user.Average(T02,T08,T14,T20)) FROM Temperature WHERE Year=2008 AND Month=5

    总结:

        用户自定义函数在处理同一数据行中的各个字段时,特别方便有用。虽然这里使用存储过程也能达到查询目的,但是显然没有使用函数方便。而且,即使使用存储过程也无法处理SELECT查询中的同一数据行中的各个字段的运算。因为存储过程不返回值,使用时只能单独调用;而函数却能出现在能放置表达式的任何位置。

    CREATE FUNCTION user.Average

    (

        @T02 float,

        @T08 float,

        @T14 float,

        @T20 float

    ) RETURNS float AS BEGIN

    DECLARE @sum float DECLARE @num int DECLARE @Ret float

    SET @sum=0 SET @num=0

    IF @T02 IS NOT NULL BEGIN     SET @sum = @sum + @T02     SET @num = @num + 1 END

    IF @T08 IS NOT NULL BEGIN     SET @sum = @sum + @T08     SET @num = @num + 1 END

    IF @T14 IS NOT NULL BEGIN     SET @sum = @sum + @T14     SET @num = @num + 1 END

    IF @T20 IS NOT NULL BEGIN     SET @sum = @sum + @T20     SET @num = @num + 1 END

    IF @num>0   SET @Ret = @sum / @num

    Return @Ret

    END

    GO

  • 相关阅读:
    Java集合和数组的区别
    二分法查找
    功能模块划分的原则及方法
    CentOS 6.5 开机启动指定服务
    CentOS 6.5配置mysql
    CentOS 6.5安装Tcpreplay
    CentOS6.5 常用命令
    CentOS6.5 安装ntopng-1.2.0
    【转】CentOS安装PF_RING(虚拟机)
    CentOS查询 杀死进程
  • 原文地址:https://www.cnblogs.com/anyun/p/3558919.html
Copyright © 2020-2023  润新知