Oracle-PL/SQL編程語言

Oracle-PL/SQL編程語言

  1. 變量定義

    declare
       定義變量
    begin
       處理業務邏輯
    end;
    
    
    
    
    -- 案例
    -- 聲明方法
    -- 賦值操作可以使用:=也可以使用into查詢語句賦值 
    declare
       -- 定義一個i 類型爲number(數字或小數)長度爲2 賦值爲10
       i number(2) := 10;
       
       -- 定義一個s 類型varchar2(字符串)長度爲10 賦值爲'小明'
       s varchar2(10) := '小明';
       
       -- 定義一個ena 類型是emp表下的ename列的類型長度也是
       ena emp.ename%type; -- 引用型變量
       
       -- 存放emp表中的一行記錄
       emprow emp%rowtype; -- 記錄型變量 
    begin
       -- 輸出i的值
       dbms_output.put_line(i);
       
       -- 輸出s的值
       dbms_output.put_line(s);
       
       -- 把查詢出來的結果 賦值給ena (into 變量名)
       select ename into ena from emp where empno = 7788;
       
       -- 輸出ena的值
       dbms_output.put_line(ena);
       
       -- 把查詢出來的結果 賦值給emprow (into 變量名)
       select * into emprow from emp where empno = 7788;
       
       -- 輸出emprow哪一行中的數據 (|| 輸出多個值得連接符)
       dbms_output.put_line(emprow.ename || '的工作爲: ' || emprow.job);
    end;
    
  2. if判斷

    declare
       定義變量 
    begin
       if 判斷 then
       		邏輯代碼塊
       elsif 判斷 then
       		邏輯代碼塊
       else
       		邏輯代碼塊
       end if;
    end;
    
    
    -- 案例
    
    -- 輸入小於18的數字, 輸出未成年
    -- 輸入大於18小於40的數字, 輸出中年人
    -- 輸入大於40的數字, 輸出老年人
    declare
       -- i的值是輸入的 (&後面隨便寫個字母單詞都行)
       i number(3) := &i;
    begin
       if i < 18 then
          dbms_output.put_line('未成年');
       elsif i < 40 then
          dbms_output.put_line('中年人');   
       else
          dbms_output.put_line('老年人');  
       end if;
    end;
    
  3. loop循環

    -- while循環
    declare
       定義變量
    begin
       while 判斷 loop
            邏輯
       end loop;
    end;
    
    
    -- exit循環
    declare
       定義變量
    begin
       loop
         exit when 判斷;
         	邏輯
       end loop;
    end;
    
    
    -- for循環
    declare
       
    begin
       for 變量 in 範圍 loop
           邏輯
       end loop;
    end;
    
    
    
    
    -- 案例
    
    -- 用三種方式輸出110的數字
    -- where循環
    declare
       i number(2) := 1;
    begin
       -- i 大於 10 時 退出循環
       while i < 11 loop
            dbms_output.put_line(i); 
            i := i + 1;
       end loop;
    end;
    
    -- exit循環
    declare
       i number(2) := 1;
    begin
       loop
         -- i 大於 10 時 退出循環
         exit when i > 10;
         dbms_output.put_line(i); 
         i := i + 1;
       end loop;
    end;
    
    -- for循環
    declare
       
    begin
       -- 循環110的值
       for i in 1..10 loop
           dbms_output.put_line(i); 
       end loop;
    end;
    
  4. 遊標

    declare
    
       cursor 遊標名稱 is 結果集;
       
       定義一個記錄型變量
    begin
       open 遊標名稱;
       
          loop
            fetch 遊標名稱 into 記錄型變量;
          
            exit when 遊標名稱%notfound;
          
          	業務邏輯
          
          end loop;
       
       close 遊標名稱;
    end;
    
    
    
    -- 案例
    
    
    -- 遊標: 可以存放多個對象, 多行記錄.
    -- 輸出emp表中所有員工的姓名
    declare
       -- 把emp表中的全部記錄, 存儲到c1遊標中
       cursor c1 is select * from emp;
       
       -- 定義一個記錄型變量
       emprow emp%rowtype;
    begin
       -- 打開遊標
       open c1;
       
          loop
            -- 把c1中遍歷的每一行 都 賦值給emprow
            fetch c1 into emprow;
          
            -- 當它查不到的時候退出
            exit when c1%notfound;
            
            -- 輸出名稱
            dbms_output.put_line(emprow.ename);
          
          end loop;
       
       -- 關閉遊標
       close c1;
    end;
    
    
    
    
    -- 給指定部門員工漲工資
    declare
       -- 定義一個帶參數的遊標, 參數作爲條件
       cursor c2(eno emp.deptno%type) is select empno from emp where deptno = eno;
       
       -- 定義一個引用型變量
       en emp.empno%type;
    begin
       -- 注意:打開的時候, 必須賦值
       open c2(10);
            loop
               -- 把c2中遍歷的每一行 都 賦值給en
               fetch c2 into en;
               
               -- 當它查不到的時候退出
               exit when c2%notfound;
            
               -- 執行更新語句
               update emp set sal = sal + 100 where empno = en;
               
               -- 提交事務
               commit;
            
            end loop;
       
       close c2;
    
    end;
    
  5. 存儲過程的使用

    -- 存儲過程
    -- 存儲過程: 存儲過程就是提前已經編譯好的一段pl/sql語言, 放置在數據庫端, 
    -- 可以直接被調用. 這一段pl/sql一般都是固定步驟的業務.
    create or replace procedure 方法名(參數) 
    
    is
    
    begin
    	業務邏輯
    end;
    
    
    
    
    -- 案例
    
    -- 給指定員工漲100塊錢
    create or replace procedure p1(eno emp.empno%type) -- 參數不寫in 或者 out 默認是in
    
    is
    
    begin
    
       update emp set sal = sal + 100 where empno = eno;
       commit;
    end;
    
    -- 測試p1
    declare
    
    begin
       -- 調用方法 傳遞參數
       p1(7788);
    end;
    
  6. 存儲函數

    create or replace function f_yearsal(參數) return 返回值類型
    
    is
    
      定義變量
    
    begin
           
       邏輯
       
       return 返回值;
    
    end;
    
    
    
    
    -- 案例
    
    -- 通過存儲函數實現計算指定員工的年薪
    -- 存儲過程和存儲函數的參數都不能帶長度
    -- 存儲函數的返回值類型不能帶長度
    create or replace function f_yearsal(eno emp.empno%type) return number
    
    is
    
      s number(10);
    
    begin
           
       select sal * 12 + nvl(comm, 0) into s from emp where empno = eno;
       
       return s;
    
    end;
    
    -- 測試f_yearsal
    -- 存儲函數在調用的時候, 返回值需要接收.
    declare
       s number(10);
    begin
       s := f_yearsal(7788);
       dbms_output.put_line(s);
    end;
    
  7. out類型參數的講解

    -- out類型參數如何使用
    -- 使用存儲過程來算年薪
    create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number)
    is
    
       s number(10);
       c emp.comm%type;
    
    begin
    
       select sal * 12, nvl(comm, 0) into s, c from emp where empno = eno;
    
       yearsal := s + c;
       
    end;
    
    
    -- 測試p_yearsal
    declare
       yearsal number(10);
    begin
       p_yearsal(7788, yearsal);
       dbms_output.put_line(yearsal);
    end;
    
    
    -- in和out類型參數的區別是什麼?
    -- 凡是涉及到into查詢語句賦值或者:=賦值操作的參數, 都必須使用out來修飾.
    
    
  8. 存儲過程和存儲函數的區別

    /*
     存儲過程和存儲函數的區別
     語法區別: 關鍵字不一樣.
           存儲函數比存儲過程多了兩個return.
     本質區別: 存儲函數有返回值, 存儲過程沒有返回值.
           如果存儲過程想實現由返回值的業務, 我們就必須使用out類型的參數.
           即便是存儲過程使用了out類型的參數, 其本質也不是真的有了返回值.
           而是在存儲過程內部給out類型參數賦值, 在執行完畢後, 我們直接拿到輸出類型參數的值.
    */
    -- 我們可以使用存儲函數有返回值的特性, 來自定義函數.
    -- 而存儲過程不能用來自定義函數.
    -- 案例需求: 查詢出員工姓名, 員工所在部門名稱.
    -- 使用傳統方式來實現案例需求
    select 
       e.ename,
       d.dname
    from
       emp e,
       dept d
    where
       e.deptno = d.deptno;
       
    -- 使用存儲函數來實現提供一個部門編號, 輸出一個部門名稱.
    create or replace function fdna(dno dept.deptno%type) return dept.dname%type
    is
       dna dept.dname%type;
    begin
       select dept.dname into dna from dept where deptno = dno;    
       return dna;
    end;
    
    -- 使用fdna存儲函數來實現案例需求: 查詢出員工姓名, 員工所在部門名稱.
    select e.ename, fdna(e.deptno)
    from emp e;
    
  9. 觸發器案例

    /*
      觸發器, 就是制定一個規則, 在我們做增刪改操作的時候, 
           只需要滿足該規則, 自動觸發, 無需調用.
           語句級觸發器: 不包含for each row的觸發器.
           行級觸發器: 包含for each row的就是行級觸發器.
                     加for each row是爲了使用:old或者:new對象或者一行記錄.
    */
    
    -- 語句觸發器
    create or replace trigger 觸發器名稱
    after  -- 執行後觸發
    操作
    on 表名稱 
    declare
    
    begin
       邏輯
    end;
    
    
    -- 行級觸發器
    create or replace trigger 觸發器名稱
    before -- 執行前觸發
    操作
    on 表名稱
    for each row
    declare
    
    begin
        邏輯
    end;
    
    
    
    
    -- 案例
    -- 語句觸發器
    -- 插入一條記錄, 輸出一個新員工入職
    create or replace trigger t1
    after  -- 執行後觸發
    insert -- insert操作
    on person 
    declare
    
    begin
       dbms_output.put_line('一個新員工入職');
    end;
    
    -- 觸發t1
    insert into person values(1, '小紅');
    commit;
    
    
    
    -- 行級觸發器
    -- 不能給員工降薪
    -- raise_application_error(-20001~-20999之間, '錯誤提示信息');
    create or replace trigger t2
    before -- 執行前觸發
    update -- update操作
    on emp
    for each row
    declare
    
    begin
        -- 修改前的工資 大於 修改後的工資
        if :old.sal > :new.sal then 
           -- 拋異常
           raise_application_error(-20001, '不能給員工降薪');
        end if;
    end;
    
    
    -- 觸發t2
    update emp set sal = sal - 1 where empno = 7788;
    commit;
    
  10. 使用觸發器實現主鍵自增

    -- 觸發器實現主鍵自增. [行級觸發器]
    -- 分析: 在用戶做插入操作之前, 拿到即將插入的數據.
    -- 給該數據中的主鍵列賦值.
    create or replace trigger auid
    before
    insert
    on person
    for each row
    declare
    
    begin
       select s_person.nextval into :new.pid from dual;
    end;
    
    -- 使用auid實現主鍵自增
    insert into person (pname) values ('小明');
    commit;
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章