oracle數據庫——存儲函數 存儲過程 觸發器 包 視圖

存儲函數

create or replace function 函數名
  (參數)
  return 返回數據類型
  is
  begin
  end;

--求兩個數的和
 create or replace function f_sum
 (
     v_a number,v_b number
 )
 return number
 is
 begin
   return nvl(v_a,0)+nvl(v_b,0);
 end;


--從新聞表中查詢新聞標題,如果標題比定義的len長,就截取標題,後面換成...,否則就輸出標題
          
create or replace function f_newstitle
(
     v_newstitle varchar2,
     len number
)
return varchar2
is
begin
   if length(v_newstitle)>len then
      return substr(v_newstitle,1,len-3)||'...';
   else
      return v_newstitle;
   end if;
end;

存儲過程

1 .不帶參數
--給所有員工工資加一百
create or replace procedure p_addsal
is
begin
  update emp set sal=sal+100;
end;


執行過程:exec p_addsal;
打開輸出功能:set serveroutput on;
2.帶參數
--根據部門編號返回最高工資和最低工資
create or replace procedure p_getsal
(
   v_deptno in number,
   v_maxsal out number,
   v_minsal out number
)
is  
begin
  select max(sal),min(sal) into v_maxsal,v_minsal from emp where deptno=v_deptno;
end;
  
--定義一個語句塊來執行這個過程
declare
    v_max emp.sal%type;
    v_min emp.sal%type;
begin
    p_getsal(&deptno,v_max,v_min);
    dbms_output.put_line('最高工資:'||v_max|| '   最低工資:'||v_min);
end;

--根據職位查詢該職位的最高工資的姓名和最低工資的姓名
create or replace procedure p_getname
(
v_job in varchar2,
v_maxsalname out varchar2,
v_minsalname out varchar2
)
is
begin
select ename into v_maxsalname from emp where sal=(select max(sal) from emp where job=v_job);
select ename into v_minsalname from emp where sal=(select min(sal) from emp where job=v_job);
end;


declare
v_maxsalname emp.ename%type;
v_minsalname emp.ename%type;
begin
  p_getname('&job',v_maxsalname,v_minsalname);
  dbms_output.put_line('最高工資的姓名:'||v_maxsalname||'最低工資的姓名:'||v_minsalname);
  end

--輸入輸出型參數 in out
--根據員工編號查詢他的工資  
create or replace procedure p_getsal
(
    v_empno in out number
)
is
begin
   select sal into v_empno from emp where empno=v_empno;
end;

declare 
  v_empno number(10);
begin
    v_empno:=7788;
    p_getsal(v_empno);
    dbms_output.put_line('工資'||v_empno);
end;

--根據部門編號查詢該部門的員工姓名,職位,薪水
create or replace procedure p_getemp
(
    v_deptno in number,
    v_result out sys_refcursor
)
is 
begin
    open v_result for select ename,job,sal from emp where deptno=v_deptno;
  end;


--調用過程
declare 
    mycur sys_refcursor;
--定義一個記錄集
    type t_record is record
    (
        v_name emp.ename%type,
        v_job emp.job%type,
        v_sal emp.sal%type
    );
--用類型聲明一個變量
    v_row t_record;
begin
   p_getemp(&deptno,mycur);
   loop
--提取數據
      fetch mycur into v_row;
        exit when mycur%notfound;
        dbms_output.put_line(v_row.v_name||'   '||v_row.v_job|| '   '||v_row.v_sal );
   end loop;
   close mycur;
end;


--輸入季節,返回這個季節入職的員工的姓名,職位,部門名稱;
  思路1:select ename,job,(select dname from dept where deptno=emp.deptno) as dname from emp 
    where decode(to_char(hiredate,'q'),1,'春',2,'夏',3,'秋',4,'冬')='春'

  思路2:select ename,job,(select dname from dept where deptno=emp.deptno) as dname from emp 
    where to_char(hiredate,'q')=instr('春夏秋冬','春')



create or replace procedure p_get
(
v_season in varchar2,
v_result out sys_refcursor
)
is
begin
  open v_result for select ename,job,
  (select dname from dept where deptno=emp.deptno) as dname from emp
  where decode(to_char(hiredate,'q'),1,'春',2,'夏',3,'秋',4,'冬')='&v_reason';
end;

declare
mycur sys_refcursor;
type t_record is record 
(
ename emp.ename%type,
job emp.job%type,
dname dept.dname%type
);
v_row t_record;
begin
  p_get('&v_season',mycur);
  loop
    fetch mycur into v_row;
    exit when mycur%notfound;
    dbms_output.put_line(v_row.ename||' '||v_row.job||' '||v_row.dname);
    end loop;
    close mycur;
    end;

觸發器

定義之後不能調用,在滿足某些特定條件的時候自動運行
分爲表級觸發器和行級觸發器
根據在事件前後觸發又分爲 before、after
根據觸發事件的不同又分爲insert、update、delete
for each row表示是行級觸發器,沒有它就表示是表級觸發器
特殊變量:
new --爲一個引用最新的列值
old --爲一個引用以前的列值

--只允許15號修改工資  
   create trigger tr_before_update_emp_sal
    before update of sal on emp
    for each row
   declare       
   begin
        if to_number(to_char(sysdate,'dd'))<>15 then
  --引發一個自定義的異常,錯誤編號在-20000和-29999之間
            RAISE_APPLICATION_ERROR(-20001,'今天不允許修改工資');
        end if;
   end;

-- 根據添加的交易記錄自動更新餘額
   --創建餘額表
   create table account
   (
       accid number(10) not null,
       password varchar2(30) not null,
       username varchar2(30) not null,
       balance number(10,2) not null,
       opendate date not null
   );
   --創建交易表
   create table trade
   (
       accid number(10) not null,
       tradedate date not null,
       tradetype varchar2(20)  not null,
       money number(10,2) not null,
       remark varchar2(50) 
   );
   --在表中插入數據
insert into account values(10086,'123456','中國移動',10000,sysdate);
insert into account values(10010,'123456','中國聯通',50000,sysdate);
   --創建觸發器
   create or replace trigger tr_after_insert_trade
     after insert on trade
     for each row
   declare
   begin
     if :new.tradetype='存入' then
         update account set balance=balance+:new.money where accid=:new.accid;
      else
         update account set balance=balance-:new.money where accid=:new.accid;
      end if;
   end; 
   --在交易表中添加數據,此時查詢餘額表時餘額也多了八百
   insert into trade values(10086,sysdate,'存入',800,null);
   
--數據校驗,在進行數據操作時進行提示
   create or replace trigger tr_test
     after  insert or delete or update on account
     for each row
     declare
     begin
          if inserting then
              dbms_output.put_line('正在添加數據:'||:new.accid);
          elsif deleting then
              dbms_output.put_line('正在刪除數據:'||:old.accid);
          elsif updating then        
              dbms_output.put_line('正在修改數據:'||:old.accid);
          end if;
     end;  

--創建包頭  
 create or replace package mypackage
   is
      type t_record is record
      (
         ename varchar2(50),
         job varchar2(50),
         sal number(10,2)
      );
      type t_cursor is ref cursor return  t_record;
      function sum(v_a number,v_b number)return number;
      procedure p_getemp(v_deptno in number,v_cursor out  t_cursor);
   end;
   
--創建包體 
   create or replace package body mypackage
   is   
      function sum(v_a number,v_b number)return number
        is
         begin
           return v_a+v_b;
          end;
      procedure p_getemp(v_deptno in number,v_cursor out  t_cursor)
        is
        begin
          open v_cursor for select ename,job,sal from emp where deptno=v_deptno;
        end;
   end;

視圖

--創建視圖  
--虛擬的查詢,建立視圖的目的是方便查詢,一般不做修改
   create or replace view v_emp
   as
   select ename,job,hiredate,dname,grade from emp
      inner join dept on emp.deptno=dept.deptno
      inner join salgrade on sal between losal and hisal;
   
   
   select * from v_emp
   <==>
   select * from
   (
     select * from emp
   )
   
--刪除視圖
drop view v_emp;
--創建別名
create synonym mm for emp;
--創建索引
create index ix_emp_job on emp(job);
--正則表達式
select * from emp where regexp_like(ename,'\d{1,5}');

--在PL/SQL中使用DDL
--將sql語句賦給一個varchar2變量,再用execute immediate 執行這個varchar2變量即可;
   declare
     v_sql varchar2(100);
     v_ename varchar2(50);
   begin
        v_sql:='select ename from emp where empno=7788';
       execute immediate v_sql into v_ename;
       dbms_output.put_line(v_ename);
   end;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章