1. 程式人生 > >Oracle的PL SQL語法

Oracle的PL SQL語法

PL/SQL

一、函式的應用

1.變數的宣告與賦值

--宣告一個變數,並賦值、列印

declare

        str varchar2(30);

        sname emp.ename%type;--宣告一個與emp表的ename屬性一致的型別

        ctable emp%rowtype;--宣告一個與emp表相同的行型別

begin

        str:='&請輸入:';--手動輸入,是一種動態賦值

        select ename into sname from emp whereempno=7369;

        select * into ctable from emp whereempno=7499;

        dbms_output.put_line('str='||str);

        dbms_output.put_line('sname='||sname);

       dbms_output.put_line('ename='||ctable.ename);

end;

2.if語句的使用

--if 取出7369的薪水,判斷是否納稅

declare

     salary emp.sal%type;

begin

     select sal into salary from emp whereempno=7369;

     if salary>=3000 then

        dbms_output.put_line('需要納稅');

     else            --elsif相當於javaelseif

        dbms_output.put_line('需努力');

     end if;

end;

--case 的兩種用法

1>.declarestr varchar2(10);

begin

str:='A';

        case str

             when'A' then dbms_output.put_line('優秀');

             when 'B' thendbms_output.put_line('良好');

             when 'C' thendbms_output.put_line('好');

             when 'D' thendbms_output.put_line('一般好');

             when 'E' thendbms_output.put_line('不好');

             else dbms_output.put_line('很不好');

        end case;

end;

2>.

declare mysalnumber(6,2);

eno number(6);

begin

    eno:=7369;      --直接賦值

    select sal intomysal from emp where empno=eno;  --這也是一種賦值

    case when mysal>3500 then dbms_output.put_line('交稅');

         when mysal=3500 thendbms_output.put_line('剛好');

         when mysal<3500 thendbms_output.put_line('努力');

         else dbms_output.put_line('其他');

     end case;

end;

3.Loop While For 三種迴圈

1>  --輸出1..100;

declare inumber(6):=1;

mysumnumber(6):=0;

begin

<<b_loop>>--loop取個名字

loop

        dbms_output.put_line(i);

        mysum:=mysum+i;

        exit b_loopwhen i=200; --跳出迴圈

        i:=i+1;

end loop;

dbms_output.put_line(mysum);

end;

 

declare inumber(6):=1;

mysumnumber(6):=0;

begin

while i<=100 loop

      mysum:=mysum+i;

      i:=i+1;

end loop;

dbms_output.put_line(mysum);

end;

 

declare

mysumnumber(6):=0;

begin

for i in 1..100 loop  --1..100這兩個引數均可使用變數

    mysum:=mysum+i;

    --i:=i+1;

end loop;

dbms_output.put_line(mysum);

end;

4.Oracle兩種常見的報錯

too_many_rows //太多行錯誤

no_data_found //沒找到資料

二、遊標

遊標分為隱式遊標、顯示遊標、REF遊標。

1>.隱式遊標

   隱式遊標無需我們申明、建立、使用,它全由系統自動完成,我們在JDBC中使用的ResultSet物件就是這種用法。

2>顯示遊標

--pl/sql 宣告(declare)  程式碼(begin  end) 異常(exception)

declare

cursor myc is select * from emp;--宣告遊標

myr emp%rowtype;

begin

open myc;--開啟遊標

--使用遊標:fetch (從遊標中提取一行)

loop

  fetch myc intomyr;

  exit when myc%notfound;

  dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);

end loop;

close myc;

end;

 

--帶條件的遊標:列印2500以下的員工資訊

declare

cursor myc isselect * from emp where sal<2500;

myr emp%rowtype;

begin

open myc;

loop

     fetch myc into myr;

     exit when myc%notfound;

      dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);

end loop;

close myc;

end;

 

--由使用者指定查詢的薪水:帶引數的遊標

declare

cursor myc(mysal number) is select * from emp wheresal<mysal;

myr emp%rowtype;

issalnumber(8,2);

begin

issal:=&請輸入;

open myc(issal);

loop

     fetch myc into myr; 

     exit when myc%notfound;

      dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);

end loop;

close myc;

end;

 

--for 循環遊標

declare

cursor myc(mysalnumber) is select * from emp where sal<mysal;

begin

for myr in myc(2500) loop

     dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);

end loop;

end;

3.REF遊標

declare

type myc is ref cursor

return emp%rowtype;--有返回值表示它是強型別,無則是弱型別

mycd myc;

myr emp%rowtype;

begin

open mycd for select * from emp;

loop

     fetch mycd into myr;

       exit when mycd%notfound;

      dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);

end loop;    

close mycd;

end;

 

--動態ref

declare

type myc is refcursor;

myce myc;

myr emp%rowtype;

mysalnumber(7,2);

begin

mysal:=2500;

open myce for 'select * from emp where sal>:1' using mysal;--“:1”表預備的第一個引數,相當於JDBC中的預備語句的“?”

loop

     fetch myce into myr;

       exit when myce%notfound;

      dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);

end loop;

close myce;

end;

三、同義詞、授權、序列、檢視、索引、

1.同義詞

--建立同義詞(需授權)

create or replacesynonym a for scott.emp;

--使用同義詞

select * from a;

--刪除同義詞

drop synonym a;--為什麼只刪除該同義詞的內容,此框架還存在,那應該怎麼刪除?

2、授權

  --授權

grant create synonym to scott;

--收權

revoke create synonym from scott;

3.序列

  --建立序列(它不能重複建立)

create sequence seq

start with 1

increment by 3

maxvalue 100

minvalue 1

cache 20;

 

create sequenceseq;--這也可以,預設為從1開始,每次加1;

--使用序列

select seq.nextvalfrom dual;

select seq.currvalfrom dual;

--刪除序列

drop sequence seq;

--修改序列裡的內容(不能修改其序列名,修改後也就不是此序列)

-- Alter sequence

alter sequence SEQ

minvalue 2

maxvalue 399

increment by 3;

-- Modify thelast number

alter sequenceSEQ increment by 2 nocache;

selectSEQ.nextval from dual;

alter sequenceSEQ increment by 3 cache 20;

4、檢視

   --建立檢視(需授權)

檢視是一個虛表,資料表刪除了,但它還存在,只是不能執行,也就是說,檢視實際是一段select語句,它能保證資料的安全性。理論上檢視是可修改,但實際上不去修改,檢視可以巢狀檢視,但不能無窮巢狀。並且sqlserver 只能巢狀32層。

create or replace view v_emp as select * from emp;

--使用檢視

select * fromv_emp;

--刪除檢視

drop view v_emp;

5、索引(index

索引:是資料庫內部編排資料的一種方法,兩個列可以建立同一個索引,稱為組合索引,表的每一個列都可以建立索引。索引依附於表存在,表刪除了,索引也沒了;能提高查詢速度,但會降低增、刪、改的速度。索引非常佔硬碟空間,若一個表裡有五個列,100萬行資料,有一個列加了索引,則硬碟除了儲存那原先的100萬行資料外,還要儲存100萬行索引資料,其中包含兩列,一個是主鍵,一個是建立索引的那個列,也就意味著,表裡每增加一個索引就會增加100萬行索引資料。

6.

  nvl(condition,value);此方法:若condition為空,則值用value的值來填充。

五、儲存過程

儲存過程:是一段預先編譯好的儲存在資料庫裡一段SQL語句集。

其優點:模組化,安全性,減少網路的流通量

--建立儲存過程

create or replaceprocedure  pname_1203(eno number)

as

myename varchar2(80);

mysal number(8,2);

begin

select ename,sal into myename,mysal fromemp where empno=eno

dbms_output.put_line('姓名'||myename||' 薪水為'||mysal);

end;

  --使用儲存過程

begin

pname_1203(7369);

end;

 

過程引數的三種模式

IN: 用於接受呼叫程式的值,預設的引數模式

OUT: 用於向呼叫程式返回值

IN OUT: 用於接受呼叫程式的值,並向呼叫程式返回更新的值

--out 型別表示該值是從儲存過程傳到外面去的

create or replace procedurepname_1203a(eno number,myjob out varchar2)

as

myename varchar2(50);

begin

select ename,job into myename,myjob fromemp where empno=eno;

dbms_output.put_line('姓名是'||myename);

end;

注意:oracle裡的子程式包括儲存過程與函式。

六、程式包(package)

--包頭的建立

create or replacepackage pname1203 is

procedure pr1203(eno number);

function fu1203(eno number)returnvarchar2;

end pname1203;

--包體的建立

create or replacepackage body pname1203 is

    procedure pr1203(eno number)

     is

        myename varchar2(55);

    begin

        select ename into myename from emp whereempno=eno;

       dbms_output.put_line('姓名是'||ename);

      end pr1203;

     function fu1203(eno number) return varchar2 is

           myename varchar2(55);

     begin

         select ename into myename from emp whereempno=eno;

     return myename||'hello';

     end fu1203;

end pname1203;

 

--如何呼叫包裡面的東西

select pname1203.fu1203(7369)from dual;

七、觸發器

1.需記住的

       (1).三種操作:delete   update   insert

(2).兩個臨時表:  :new   :old

:old表用來儲存要刪除時的資料,只有一行資料

:new表用來儲存要插入時的資料,只有一行資料

更新時需要:old  and  :new  兩個表都需要

(3).兩個時間點: after    before

(4).兩種重要模式:行級   語句級(即表級)

(5).條件:when

     2. --建立觸發器:學生資訊表中‘s25301'不能刪除、修改; 插入時,

--  檢查名字叫'張洋洋'的不能新增  's25302'不能改

createor replace trigger t_stu

afterdelete or update or insert on stuinfo

for each row  //這表示是行級觸發器,若沒寫,則為表級觸發器。

declaresno varchar2(40);

snamevarchar2(50);

begin

sno:=:old.stuno;

sname:=:new.stuname;

if deleting then

  if sno='s25301'  then

     raise_application_error(-20009,'該學生不能動');//-20009是自定義錯誤,其自定義錯誤程式碼範圍:-20000-21000.

  end if;

elsif updating then

   if sno='s25302'  then

     raise_application_error(-20004,'該學生不能動');

  end if;

elsif inserting then

      if sname='張洋洋'then

          raise_application_error(-20006,'該學生不能要');

      end if;

end if;

end;

   3.在插入資料時自動插入序列號

       create or replace trigger t_stua

beforeinsert on tb_study

for eachrow

begin

--:new.sid:=mys1208.nextval;     //11g版本可使用

select mys1208.nextval into :new.sid from dual;    //10g可使用

end;