Oracle 存储过程(procedure)和函数(Function)小结

1、Oracle 存储过程(procedure)和函数(Function)的区别

  • 返回值的区别:函数有1个返回值,一般情况下是用来计算并返回一个计算结果;

    ​ 而存储过程是通过参数返回的,可以有多个或者没有

  • 调用的区别 :函数可以在Sql查询语句中直接调用;

    ​ 而存储过程必须单独调用,一般是用来完成特定的数据操作

    ​ (比如修改、插入数据库表或执行某些DDL语句等等)

    在这里插入图片描述

  • 存储过程一般是作为一个独立的部分来执行( EXECUTE 语句执行);

    而函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象

    因此它可以在查询语句中位于FROM关键字的后面。 SQL语句中不可用存储过程,而可以使用函数。

2、在Oracle的函数中,返回表对象

2.1、创建表对象类型

在Oracle中想要返回表对象,必须自定义一个表类型,如下所示:

create or replace type t_table is table of number;

上面的类型定义好后,在function使用可用返回一列的表,如果需要多列的话,需要先定义一个对象类型。

然后把对象类型替换上面语句中的number;

定义对象类型:

create or replace type obj_table as object
(
  id int,
  name varchar2(50)
);

修改表对象类型的定义语句如下:

create or replace type t_table is table of obj_table;
2.2、创建演示函数

在函数的定义中,可以使用管道化表函数和普通的方式,下面提供两种使用方式的代码:

2.2.1、管道化表函数方式
create or replace function f_pipe(s number)
return t_table pipelined
as
    v_obj_table obj_table;   
begin    
for i in 1..s loop 
    v_obj_table :=  obj_table(i,to_char(i*i));
    pipe   row(v_obj_table);   
end loop;
return;
end f_pipe;

注意:管道的方式必须使用空的return表示结束。

调用函数的方式如下:

select * from table(f_pipe(5));
2.2.2、普通的方式
create or replace function f_normal(s number)
return t_table
as
    rs t_table:= t_table();
begin
    for i in 1..s loop
        rs.extend;
        rs(rs.count) := obj_table(rs.count,'name'||to_char(rs.count));
        --rs(rs.count).name := rs(rs.count).name || 'xxxx';
    end loop;
return rs;
end f_normal;

调用方式同上

3、oracle复杂自定义函数写法与实例

3.1、Oracle自定义函数的语法如下
create or replace function 函数名(参数1 模式 参数类型)
return 返回值类型
as
变量1 变量类型;
变量2 变量类型;
begin
    函数体;
end 函数名;

参数的模式有3种:(如果没有注明, 参数默认的类型为 in.)

in: 为只读模式, 在函数中, 参数的值只能被引用, 不能被改变;

out: 为只写模式, 只能被赋值, 不能被引用;

in out: 可读可写.

提醒:

  • 在Oracle自定义函数中, else if 的正确写法是 elsif 而不是 else if
  • 使用 if 需要加 then “if 条件 then 操作”
3.2、简单例子: 读入两个值, 返回比较大的值
create or replace function function1(para1 in number, para2 in number) 
return number 
as 
begin
  if para1 > para2 then
      return para1;
  else
      return para2; 
  end if;
end function1;
select function1(666, 333) from dual;

result:

666
3.3、较复杂实际中会用到的例子(值得把玩)

场景说明:

有时候我们需要按非自然月进行数据统计, 这种时候我们只需要写一个自定义的函数处理日期就行了.

函数说明: 读入date型日期,大于15号的归入下一个月,小于等于15号归入本月

create or replace function fn_mymonth(oridate in date)
return varchar2
as
  oriday number;
  orimonth number;
  oriyear number; 
begin
  oriday := to_number(to_char(oridate, 'dd'));
  orimonth := to_number(to_char(oridate, 'mm'));
  oriyear := to_number(to_char(oridate, 'yyyy'));
 
  if oriday <= 15 then                              --少于等于15号属于本月
    return to_char(oridate, 'yyyymm');
  else
    if orimonth <= 8 then                           -- 月 <=8 则+1后转char还要补0,单独出来作为一种情况
      return to_char(oriyear)||'0'||to_char(orimonth + 1);
    elsif( orimonth <= 11 ) then                    -- 月 <= 11则+1后不会跨年,转char不需要补零, 单独出来作为一种情况
      return to_char(oriyear)||to_char(orimonth + 1);
    else                                            -- 最后一种情况就是跨年, 改变年份, 月份补零就行
      return to_char(oriyear + 1)||'0'||to_char(orimonth - 11);
    end if;
  end if;
end fn_mymonth;
select fn_mymonth(to_date('2015-12-14', 'yyyy-mm-dd')) from dual;
result: 201512

select fn_mymonth(to_date('2015-12-15', 'yyyy-mm-dd')) from dual;
result: 201512

select fn_mymonth(to_date('2015-12-16', 'yyyy-mm-dd')) from dual;
result: 201601

select fn_mymonth(to_date('2015-08-16', 'yyyy-mm-dd')) from dual;
result: 201509

select fn_mymonth(to_date('2015-11-16', 'yyyy-mm-dd')) from dual;
result: 201512
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章