1. 程式人生 > >PL/SQL過程和函式以及引數

PL/SQL過程和函式以及引數

PL/SQL過程和函式

PL/SQL中過程和函式設計的目的就是為了將程式碼模組化,有效的管理程式碼。

我寫這篇文章的目的是為了在我閱讀《Oracle.PL.SQL程式設計》一書是做些筆記,並分享給其他同學。

過程

我們可以把過程理解為一個或者多個動作的集合,我們可以像是呼叫PL/SQL中可執行語句一樣來呼叫過程。下面來介紹一下過程的格式。

procedure [scheam.]name[(parameter)]  --scheam 可選 預設為當前使用者名稱,如果當前使用者具有許可權,也可以為其他模式建立過程。
  [AUTHID DEFINER|CURRENT_USER
] --AUTHID 可選 設定了當前過程的執行許可權,定義者|當前使用者 IS [declaration statement] BEGIN executable statement [EXCEPTION EXCEPTION HANDLERS ] END [NAME];

下面我寫了一個批量設定員工工資的過程

CREATE OR REPLACE PROCEDURE EDIT_SALARY(in_year in NUMBER,per in BINARY_DOUBLE)
IS
CURSOR  ALL_EMP IS SELECT hiredate,sal,empno FROM EMP
where GET_YEAR(EMP.HIREDATE) < in_year;
BEGIN for cur_emp in ALL_EMP LOOP UPDATE EMP set sal = cur_emp.sal *(1+ per) where empno = cur_emp.empno; end LOOP; end EDIT_SALARY;

首先我為這個儲存過程設定了兩個引數,in_year 的含義為入職年份早於此年份則可以漲工資,per 的含義為漲工資的比率是多少。
之後我聲明瞭一個遊標,取出了emp表附和可以漲工資年份的員工的資訊。GET_YEAR(EMP.HIREDATE) 是一個函式,我將在下面介紹函式時講解。
最後在執行單元中遍歷遊標,設定每個員工的新工資。

我們呼叫一個過程時,當這個過程沒有引數可以這樣寫: “procedure_name;”不需要加上()。
在儲存過程的結尾 end [name]; name 雖然是可選的,但是可以提升程式碼的可讀性。

函式

在呼叫函式時更像是一種類似呼叫表示式的語句,他只能作為可執行語句的一部分,函式必須有RETURN的設定,提供了返回引數的功能。當然,我們也可以設定更多的RETUEN以滿足我們函式的需求。
下面介紹一下函式的結構

FUNCTION [SCHEAM.]NAME[(PARAMETERS)]
      RETURN return_datatype     --設定了返回值型別。
  [AUTHID DEFINER | CURRENT_USER]
  [DETERMINISTIC]        --保留函式返回值,查詢優化器可以決定直接使用結果還是重新執行
  [PARALLEL_ENABLE..]   --當函式在select語句中,可以併發執行
  [PIPELINED] --結果通過pipe row 多次返回
  [RESULT_CACHE ...] --將輸入值和返回值都儲存在快取中
IS
  [declaration statement]
BEGIN
  executable statement
[EXCEPTION
  EXCEPTION HANDLERS
]

END [NAME];

在上一個過程中,我們用到了一個函式,在這裡我們來一起看一下

create or replace function get_year(in_date IN DATE)
RETURN CHAR
IS
       return_year char(4,char);
BEGIN
   return_year:=substr(to_char(to_date(in_date),'yyyy-MM-dd'),0,4);
   RETURN return_year;
END get_year;

首先我們建立一個函式,並且有一個輸入引數,型別為日期型別,返回值是一個char型別。在執行單元首先我們設定了日期的格式,並將它設定為字串,然後使用substr擷取年份部分並返回。

引數

不論過程還是函式,都需要引數作為由外部傳遞資料的載體,引數的定義和宣告變數十分相似,但是不同的是引數具有傳遞性,而且引數是不受宣告限制的。

DECLEARE
    my_variable  VARCHAR2(10);
function my_function(paramater IN VARCHAR) RETURN VARCHAR

這裡可以看出,引數的定義不可以對其進行約束(將varchar後對長度的約束去掉)。

在PL/SQL中引數一共有三種模式
- IN 只可以被讀取
- OUT 只可以被寫入
- IN OUT 即可以被讀取也可以被寫入。

IN 引數模式

IN引數模式是隻讀的,可以把它理解為一個常量,它只是將資料傳遞給過程內部,並不負責將資料傳遞出去,並且IN模式是引數的預設模式,當一個引數沒有指定引數模式時,我們預設它就是IN模式的。

OUT 引數模式

OUT引數模式和IN模式相反,你可以通過這個引數模式將資料傳遞給呼叫者。在程式內部,out引數更像是一個沒有被初始化的變數,我們只能寫入一些資料,但是不能讀出一些什麼。在使用OUT引數模式要注意,我們不能把out引數賦值給其他甚至是他自己;我們不能為out引數提供預設值,只能在程式內部設定它的值;out引數的實參必須是一個變數,不能是常量,表示式等。我們為OUT引數賦值時,其實都是在對一個PL/SQL程式內褲建立的副本進行操作,當程式返回到呼叫者部分時,才會將副本中的值返回給真正的OUT引數。

IN OUT 引數模式

IN OUT 即可以被讀取也可以被寫入,同樣的,他也不能被設定預設值,而且它的實參也必須是一個變數,除此之外就沒什麼要求了。

形參和實參的關聯

關聯方式有兩種,其一時位置關聯,其二是命令關聯。

 function get_year(in_date IN DATE , in_varchar varchar2)
-----------------------------------------------------------------
get_yaer(date,‘asdasd’);

上面的方式就是依靠引數的位置來關聯,date指向第一個引數in_date,像是這樣的。

 function get_year(in_date IN DATE , in_varchar varchar2)
-----------------------------------------------------------------
get_yaer(in_date =>> date ,in_varchar =>> ‘asdasd’);

這種方式就是命令表示法,依靠 =>>指明關聯關係。

這兩種關聯方法可以混用,在一次呼叫中可以用兩種不同的關聯方法指明引數,但是值得注意的是,一旦使用了命令關聯,則後面的引數就不能使用位置關聯表示了。

NOCOPY

之前我們提到過,OUT,INOUT引數模式,我們在程式中為這類引數賦值時,實際上是在對PL/SQL程式生成的引數的副本進行操作,但當我們操作一些集合等體積較大的資料時會影響我們的效率,所以可以使用NOCOPY來該縣這種情況。

IN引數的預設值

上面提到的OUT,INOUT引數模式 不能由預設值,所以這裡顯示一下IN引數的預設值

function get_year(in_varchar varchar2 := ‘asdad’)