1. 程式人生 > 其它 >Oracle的儲存過程

Oracle的儲存過程

  一、什麼是儲存過程?

    儲存過程就是一組為了完成特定功能的SQL語句集,儲存在資料庫中;這樣經過第一次編譯後再次呼叫不需要再次編譯,直接呼叫或者通過java掉用(就是個SQL語句集)

    在Oracle中儲存過程是procedure

    優勢:

      1. 相比普通的sql語句,每次都要先編譯在執行,相對而言儲存過程效率更高

      2. 降低網路流量(儲存過程編譯好後直接存在資料庫中,遠端呼叫時,不會傳輸大量的字串型別的sql語句)

      3. 複用性高:一次編譯後,以後直接呼叫

      4. 可維護性更高:修改比較容易

      5. 安全性高:可以指定使用者進行儲存過程的呼叫

  二、儲存過程的建立方式:

  2.1 無參

CREATE OR REPLACE PROCEDURE 儲存過程名稱
AS/IS
    變數2 DATE;
    變數3 NUMBER;
BEGIN
    --要處理的業務邏輯
    EXCEPTION    --儲存過程異常(可寫可不寫)
END

  2.2 有參

  2.2.1 帶引數的儲存過程(輸入引數:id ; 輸出引數:name)

1 CREATE OR REPLACE PROCEDURE 儲存過程名稱(param1 student.id%TYPE)
2 AS/IS
3 name student.name%TYPE;
4 age number :=20;
5 BEGIN
6   --業務處理.....
7 END

上面指令碼中,

第1行:param1 是引數,型別和student表id欄位的型別一樣。

第3行:宣告變數name,型別是student表name欄位的型別(同上)。

第4行:宣告變數age,型別數數字,初始化為20

  

  2.2.2 帶引數的儲存過程並且進行賦值

 1 CREATE OR REPLACE PROCEDURE 儲存過程名稱(
 2        s_no in varchar,
 3        s_name out varchar,
 4        s_age number) AS
 5 total NUMBER := 0;
 6 BEGIN
 7   SELECT COUNT(1) INTO total FROM student s WHERE s.age=s_age;
 8   dbms_output.put_line('符合該年齡的學生有'||total||'人');
 9   EXCEPTION
10     WHEN too_many_rows THEN 
11     DBMS_OUTPUT.PUT_LINE('返回值多於1行'); 
12 END

上面指令碼中:

其中引數IN表示輸入引數,是引數的預設模式。
OUT表示返回值引數,型別可以使用任意Oracle中的合法型別。
OUT模式定義的引數只能在過程體內部賦值,表示該引數可以將某個值傳遞迴呼叫他的過程
IN OUT表示該引數可以向該過程中傳遞值,也可以將某個值傳出去

第7行:查詢語句,把引數s_age作為過濾條件,INTO關鍵字,把查到的結果賦給total變數。

第8行:輸出查詢結果,在資料庫中“||”用來連線字串

第9—11行:做異常處理

  三、儲存過程的語法

  3.1 將結果放入一個或多個變數中:

 1 CREATE OR REPLACE PROCEDURE DEMO_CDD1 IS
 2 s_name VARCHAR2;   --學生名稱
 3 s_age NUMBER;      --學生年齡
 4 s_address VARCHAR2; --學生籍貫
 5 BEGIN
 6   --給單個變數賦值
 7   SELECT student_address INTO s_address
 8   FROM student where student_grade=100;
 9    --給多個變數賦值
10   SELECT student_name,student_age INTO s_name,s_age
11   FROM student where student_grade=100;
12   --輸出成績為100分的那個學生資訊
13   dbms_output.put_line('姓名:'||s_name||',年齡:'||s_age||',籍貫:'||s_address);
14 END

  3.2 選擇語句:

IF s_sex=1 THEN
  dbms_output.put_line('這個學生是男生');
END IF


IF s_sex=1 THEN
  dbms_output.put_line('這個學生是男生');
ELSE
  dbms_output.put_line('這個學生是女生');
END IF

  3.3 迴圈語句

 1 -- 基本迴圈
 2 LOOP
 3   IF 表示式 THEN
 4     EXIT;
 5   END IF
 6 END LOOP;
 7 
 8 -- while迴圈
 9 WHILE 表示式 LOOP
10   dbms_output.put_line('haha');
11 END LOOP;
12 
13 -- for迴圈
14 FOR a in 10 .. 20 LOOP
15   dbms_output.put_line('value of a: ' || a);
16 END LOOP;

練習:

有表student(s_no, s_name, s_age, s_grade),其中s_no-學號,也是主鍵,是從1開始向上排的(例如:第一個學生學號是1,第二個是2,一次類推);s_name-學生姓名;s_age-學生年齡;s_grade-年級;這張表的資料量有幾千萬甚至上億。一個學年結束了,我要讓這些學生全部升一年級,即,讓s_grade欄位加1。
這條sql,寫出來如下:

update student set s_grade=s_grade+1

分析:

如果我們直接執行執行這條sql,因資料量太大會把資料庫undo表空間撐爆,從而發生異常。那我們來寫個儲存過程,進行批量更新,我們每10萬條提交一次。

CREATE OR REPLACE PROCEDURE process_student is
total NUMBER := 0;
i NUMBER := 0;
BEGIN
  SELECT COUNT(1) INTO total FROM student;
  WHILE i<=total LOOP
    UPDATE student SET grade=grade+1 WHERE s_no=i;
    i := i + 1;
    IF i >= 100000 THEN
      COMMIT;
    END IF;
  END LOOP;
  dbms_output.put_line('finished!');
END;