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;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM