Oracle存儲過程與觸發器


7-1(存儲過程)創建一個顯示學生總人數的存儲過程

 1 SQL>SET SERVEROUTPUT  ON
 2 SQL>CREATE  OR REPLACE PROCEDURE STU_COUNT
 3   2AS           --需要定義的存儲過程內的變量均寫在AS下
 4    3TOTAL    NUMBER --定義
 5    4BEGIN
 6    5     SELECT COUNT(SNO) INTO TOTAL FROM STUDENT; --SELECT 后的變量個數要與INTO 后一致
 7    6     DBMS_OUTPUT.PUT_LINE('總數:'||TOTAL);  --字符'||'的含義是連接兩個字符串
 8    7END;
 9    8/
10 
11 SQL>EXECUTE STU_COUNT;
總數:12

PL/SQL 過程已成功完成。

 

7-2(存儲過程)創建顯示學生信息的存儲過程STUDENT_LIST,並引用STU_COUNT存儲過程

 1 SQL> SET SERVEROUTPUT ON
 2 SQL> CREATE OR REPLACE PROCEDURE STUDENT_LIST
 3   2  AS
 4   3  SNO                STUDENT.SNO%TYPE;
 5   4  SNAME      STUDENT.SNAME%TYPE;
 6   5  CURSOR C_STUDENT_INFO IS SELECT SNO,SNAME FROM STUDENT;
 7   6  BEGIN
 8   7     FOR C_STUDENT_i IN C_STUDENT_INFO
 9   8     LOOP
10   9     DBMS_OUTPUT.PUT_LINE(C_STUDENT_i.SNO||'---'||C_STUDENT_i.SNAME);
11  10     END LOOP;
12  11     STU_COUNT();
13  12  END;
14  13  /
15 
16 過程已創建。

運行結果

SQL> EXECUTE STUDENT_LIST;
96001---馬小燕
96002---黎明
96003---劉東明
96004---趙志勇
97001---馬蓉
97002---李成功
97003---黎明
97004---李麗
74313---錢常來
96006---張然
96005---司馬志明
20001---趙薇
總數:12

PL/SQL 過程已成功完成。

如果寫存儲過程總是會報錯,可以先測試一下游標環節是否有問題,游標測試編寫如下:

SQL> DECLARE
  2  SNO        STUDENT.SNO%TYPE;
  3  SNAME      STUDENT.SNAME%TYPE;
  4  CURSOR C_STUDENT_INFO IS SELECT SNO,SNAME FROM STUDENT;
  5  BEGIN
  6     FOR C_STUDENT_i IN C_STUDENT_INFO
  7     LOOP
  8     DBMS_OUTPUT.PUT_LINE(C_STUDENT_i.SNO||'---'||C_STUDENT_i.SNAME);
  9     END LOOP;
 10  END;
 11  /
96001---馬小燕
96002---黎明
96003---劉東明
96004---趙志勇
97001---馬蓉
97002---李成功
97003---黎明
97004---李麗
74313---錢常來
96006---張然
96005---司馬志明
20001---趙薇

PL/SQL 過程已成功完成。

 

7-3(存儲過程)創建一個顯示學生平均成績的存儲過程

 1 SQL> SET SERVEROUTPUT ON;
 2 SQL> CREATE OR REPLACE PROCEDURE AVGSCORE(NO IN STUDENT.SNO%TYPE)
 3   2  AS
 4   3  AVERAGE NUMBER(5,2);
 5   4  BEGIN
 6   5     SELECT AVG(SCORE)INTO AVERAGE FROM SCORE GROUP BY SNO HAVING SNO = NO;
 7   6     DBMS_OUTPUT.PUT_LINE(NO||'---'||AVERAGE);
 8   7  END;
 9   8  /
10 SQL> EXECUTE AVGSCORE('96001');
11 96001---83.63
12 
13 PL/SQL 過程已成功完成。

7-4  (存儲過程)  創建顯示所有學生平均成績的存儲過程

 1 SQL> SET SERVEROUTPUT ON
 2 SQL> CREATE OR REPLACE PROCEDURE STUDENT_AVG
 3   2  AS
 4   3  CURSOR SCORE_AVG IS SELECT SNO,AVG(SCORE) AS AVG_SCORE FROM SCORE GROUP BY SNO;
 5   4  BEGIN
 6   5     FOR I IN SCORE_AVG
 7   6     LOOP
 8   7             DBMS_OUTPUT.PUT_LINE(I.SNO||'---'||I.AVG_SCORE);
 9   8     END LOOP;
10   9  END;
11  10  /
12 
13 過程已創建。
14 
15 SQL> EXECUTE STUDENT_AVG;
16 74313---72
17 96001---83.625
18 96002---90.16666666666666666666666666666666666667
19 96003---80
20 96004---87
21 96005---86.75
22 97001---95.5
23 97002---91.5
24 97003---58.5
25 97004---83.33333333333333333333333333333333333333
26 
27 PL/SQL 過程已成功完成。

--如何讓輸出數據格式一致??
SQL> DECLARE
  2  SNO                SCORE.SNO%TYPE;
  3  AVG_SCORE          SCORE.SCORE%TYPE;
  4  CURSOR STUDENT_AVG IS SELECT AVG(SCORE) INTO AVG_SCORE FROM SCORE GROUP BY SNO;
  5  BEGIN
  6     FOR I IN STUDENT_AVG
  7     LOOP
  8             DBMS_OUTPUT.PUT_LINE(I.SNO||'---'||I.AVG_SCORE);
  9     END LOOP;
 10  END;
 11  /
                DBMS_OUTPUT.PUT_LINE(I.SNO||'---'||I.AVG_SCORE);
                                       *8 行出現錯誤:
ORA-06550: 第 8 行, 第 26 列:
PLS-00302: 必須聲明 'SNO' 組件
ORA-06550: 第 8 行, 第 3 列:
PL/SQL: Statement ignored

這是什么錯?

7-5(修改數據庫)在STUDENT表中增加SAVG(N,6,2)字段

1 SQL> ALTER TABLE STUDENT ADD SAVG NUMBER(6,2);
2 
3 表已更改。

 

7-6(存儲過程)創建存儲過程,計算每個學生的平均成績保存到學生表中SAVG字段中

 1 SQL> SET SERVEROUTPUT ON
 2 SQL> CREATE OR REPLACE PROCEDURE SAVE_SAVG
 3   2  AS
 4   3  CURSOR STUDENT_AVG IS SELECT SNO,AVG(SCORE) AS AG FROM SCORE GROUP BY SNO;
 5   4  BEGIN
 6   5     FOR I IN STUDENT_AVG
 7   6             LOOP
 8   7             UPDATE STUDENT SET SAVG = I.AG WHERE SNO = I.SNO;
 9   8     END LOOP;
10   9  END;
11  10  /
12 
13 過程已創建。
14 
15 SQL> EXECUTE SAVE_SAVG;
16 
17 PL/SQL 過程已成功完成。
18 
19 SQL> SELECT * FROM STUDENT;
20 
21 SNO        SNAME                    SDEP SCLA SSEX         SAGE       SAVG
22 ---------- ------------------------ ---- ---- ------ ---------- ----------
23 96001      馬小燕                   CS   0122      83.63
24 96002      黎明                     CS   0119      90.17
25 96003      劉東明                   MA   0118         80
26 96004      趙志勇                   IS   0220         87
27 97001      馬蓉                     MA   0219       95.5
28 97002      李成功                   CS   0121       91.5
29 97003      黎明                     IS   0319       58.5
30 97004      李麗                     CS   0220      83.33
31 74313      錢常來                   SC   0219         72
32 96006      張然                     CS   0220
33 96005      司馬志明                 CS   0219      86.75
34 
35 SNO        SNAME                    SDEP SCLA SSEX         SAGE       SAVG
36 ---------- ------------------------ ---- ---- ------ ---------- ----------
37 20001      趙薇                     IS   0219
38 
39 已選擇12行

 

7-7  (觸發器)  當更新學生成績表SCORE 中的學生成績時,自動計算該學生的平均成績保存到學生表中SAVG字段中

 

SQL>CREATE OR REPLACE PACKAGE MY_PACK    
        AS
        a    STUDENT.SNO%TYPE;
        END;
        /

SQL>CREATE OR REPLACE TRIGGER UPD_SC
        BEFORE UPDATE ON SCORE
        REFERENCING NEW AS NEW OLD AS OLD
        FOR EACH ROW
        BEGIN
            MY_PACK.a := :NEW.SNO;
        END;
        /

SQL>CREATE OR REPLACE TRIGGER UPD_SC_1
        AFTER UPDATE ON SCRE
        REFERENCING NEW AS NEW OLD AS OLD
        FOR EACH ROW
        DECLARE
        b    SCORE.SCORE%TYPE;
        PRAGMA AUTONOMOUS TRANSATION;
        BEGIN
            IF UPDATING    THEN
                SELECT AVG(SCORE) INTO b FROM SCORE WHERE SNO = MY_PACK.a  GROUP BY SNO;
            UPDATE STUDENT SET SAVG=b WHERE SNO= MY_PACK.a;
            END IF ;
        COMMIT;
        END;
        /

 

7-8 (觸發器) 創建包含插入、刪除、修改多種觸發事件的觸發器DBM_LOG,對SCORE表的操作進行記錄。用INSETING、DELETING、UPDATING謂詞來區別不同的DML操作

先創建事件記錄表LOGS,該表用來對操作進行記錄。該表的字段含義解釋如下:

    LOG_ID:操作記錄的編號,數值型,它是該表的主鍵,自動增1,可由序列自動生成。

    LOG_TABLE:進行操作的表名,字符型,非空,該表設計成可以由多個觸發器共享使用。比如我們可以為Student表創建類似的觸發器,同樣將操作記錄到該表。

    LOG_DML:操作的動作,即INSERT、DELETE或UPDATE三種之一。

    LOG_KEY_ID:操作時表的主鍵值,數值型。之所以記錄表的主鍵,是因為主鍵是表的記錄的惟一標識,可以識別是對哪一條記錄進行了操作。對於Score表,主鍵是由SNO_CNO構成。

    LOG_DATE:操作的日期,日期型,取當前的系統時間。

    LOG_USER:操作者,字符型,取當時的操作者賬戶名。比如登錄SCOTT賬戶進行操作,在該字段中,記錄賬戶名為SCOTT。

CREATE TABLE LOGS
(
    LOG_ID    NUMBER(10) PRIMARY KEY,
    LOG_TABLE    VARCHAR2(10) NOT NULL,
    LOG_DML        VARCHAR2(10),
    LOG_KEY_ID    NUMBER(10),
    LOG_DATE    DATE,
    LOG_USER     VARCHAR2(15)
);
CREATE SEQUENCE LOGS_ID_SQU 
INCREMENT BY 1
START WITH 1
MAXVALUE 99999
NOCYCLE NOCACHE;

 

SQL> CREATE OR REPLACE TRIGGER DML_LOG
  2  BEFORE
  3  DELETE OR INSERT OR UPDATE ON SCORE
  4  REFERENCING NEW AS NEW OLD AS OLD
  5  FOR EACH ROW
  6  BEGIN
  7     IF INSERTING THEN
  8             INSERT INTO LOGS VALUES(LOGS_ID_SQU.NEXTVAL,'SCORE','INSERT',:NEW.SCORE,SYSDATE,USER);
  9     ELSIF DELETING THEN
 10             INSERT INTO LOGS VALUES(LOGS_ID_SQU.NEXTVAL,'SCORE','DELETE',:NEW.SCORE,SYSDATE,USER);
 11     ELSIF UPDATING THEN
 12             INSERT INTO LOGS VALUES(LOGS_ID_SQU.NEXTVAL,'SCORE','UPDATE',:NEW.SCORE,SYSDATE,USER);
 13     END IF ;
 14  END;
 15  /

觸發器已創建

SQL> INSERT INTO SCORE VALUES('96001','002',83);

已創建 1 行。

SQL> select * from logs;

    LOG_ID LOG_TABLE                                LOG_DML                                  LOG_KEY_ID LOG_DATE       LOG_USER
---------- ---------------------------------------- ---------------------------------------- ---------- -------------- ----------------------------------------
1 SCORE INSERT 83 18-6月 -18 SYSTEM

LOG_KEY_ID:操作時表的主鍵值,數值型,對於Score表,主鍵是由SNO_CNO構成。 ?????

 

SQL> SELECT * FROM SCORE WHERE SNO='96001';

SNO        CNO         SCORE
---------- ------ ----------
96001      001            90
96001      002            83
96001      003            92
96001      004            92
96001      005            92

SQL> UPDATE SCORE SET SCORE = 97 WHERE SNO = '96001' AND CNO= '003';

已更新 1 行。

SQL> DELETE FROM SCORE WHERE SNO='96001' AND CNO='005';

已刪除 1 行。

SQL> SELECT * FROM LOGS;

    LOG_ID LOG_TABLE
---------- ----------------------------------------
LOG_DML                                  LOG_KEY_ID LOG_DATE
---------------------------------------- ---------- --------------
LOG_USER
----------------------------------------
         1 SCORE
INSERT                                           83 18-6月 -18
SYSTEM

         2 SCORE
UPDATE                                           97 18-6月 -18
SYSTEM

    LOG_ID LOG_TABLE
---------- ----------------------------------------
LOG_DML                                  LOG_KEY_ID LOG_DATE
---------------------------------------- ---------- --------------
LOG_USER
----------------------------------------

         3 SCORE
DELETE                                              18-6月 -18
SYSTEM

 


免責聲明!

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



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