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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章