oracle_third

oracle-third

1.PL/SQL編程語言

1)什麼是PL/SQL:

PL/SQL==(procedure language/SQL)

PL/SQLoraclesql語言的過程化擴展,在sql命令語言中增加了過程處理語句(如分支,循環),使SQL語句具有過程處理能力。

   例子1:給所有人的工資漲10%

update  emp  set sal=sal*1.1;

   例子2:按職工職位漲工資總裁漲1000元,經理漲800元,其他人員漲400元。

使用jdbc打開連接,創建statement,執行三次executeUpdatesql

本例子我們不能使用一條sql來完成這個操作,我們可以分解成多個sql來完成,也可以使用我們的PL/SQL做,那麼PL/SQL實際上相當於我們的jdbc的感覺,但是呢相比於jdbc來說jdbc是外部程序,跟我們在界面手工執行sql差不多,但是PL/SQL不同他是在oracle服務器裏執行的程序。效率當然不一樣了。

set serveroutput on;//打開控制檯輸出

 

2)PL/SQL的語法結構:

declare

--說明部分  (變量申明,光標申明,例外說明)

begin

--語句序列:DML語句多個

exception

--例外異常處理語句

end;

/

 

3)常量和變量的定義

※聲明變量(char ,varchar2,date,number,boolean,long)

var1 char(30);  --說明變量名,類型等等信息以分號結尾。

var2 boolean:=true;  --說明變量並且指定默認值

username emp.ename%type;  --引用行變量和emp表中ename類型一樣

emp_rec emp%rowtype;  --記錄類型的變量

※使用變量



empname:=’sdf'

我們在程序中定義了變量之後使用sql語句給我們變量賦值的關鍵字是

into

 

declare

emprec emp%rowtype;

begin

select * into emprec from emp where  empno=7876;

dbms_output.put_line(emprec.ename ||’工資爲’||emprec.sal);

end;

 

 

 

4)IF判斷

※語法:

IF 條件

THEN

語句1

語句2

...

END IF;

IF 條件
    THEN 語句序列;

ELSE 語句序列;

END IF;

IF 條件 THEN語句序列;

ELSIF 條件 THEN語句序列;

...

ELSE 語句序列;

END  IF;

 

例子1:從控制檯輸入姓名,然後輸出‘我是xxx

declare

myname_ varchar2(20) :='&myname_p';

begin

dbms_output.put_line('我是'||myname_);

end;


例子2:從控制檯輸入姓名,判斷是不是李嘉誠如果是李嘉誠輸出:‘我是李嘉誠,我有錢我任性。’,如果不是那麼輸出‘我不是李嘉誠,我是xxx;

declare

myname_ varchar(20):='&myname_p';

begin

if myname_='李嘉誠' then

dbms_output.put_line('我是李嘉誠,我有錢,我任性。');

else

dbms_output.put_line('我不是李嘉誠,我是'||myname_||'(o)!!!');

end if;

end;



declare

myname_ varchar2(20):='&inputname';

begin

if myname_='李嘉誠' then

dbms_output.put_line('我是李嘉誠,我有錢我任性。');

elsif myname_='馬雲' then

dbms_output.put_line('我是馬雲,我有錢我任性。');

else

dbms_output.put_line('矮窮矬');

end if;

end;



高難度例子3:從控制檯輸入用戶的編號,判斷員工工資是否大於5000如果大於5000輸出厲害了我的哥;

分析:1.得到用戶編號用地址符的方式接受輸入,你需要一個變量來接收

  2.還的拿到員工工資,sql into  ,你又需要一個變量來接收

3.這時候你就可以開始if判斷 然後輸出

declare

empno_ number :=&empno;

emprec_ emp%rowtype;

usercount_ number;

begin

select  count(1)  into  usercount_  from  emp where empno=empno_;

If usercount_=1  then

select  *  into  emprec_  from  emp  where empno=empno_;

if emprec_.sal>5000 then

dbms_output.put_line('厲害了我的哥,您的工資是:'||emprec_.sal||'');

else

dbms_output.put_line('夥計你還的加油啊!');

end if;

  else

dbms_output.put_line('編號爲:的員工找到了0或者找到了多條');

end if;

end;



5)循環

語法1

while 條件  loop

    語句1;

    語句2;

    ...

    total :=total+1;

end  loop;

語法2

loop

exit  when 條件;

    語句1;

    語句2;

    ...      

end  loop;

語法3

for  i  in  1..4

loop

   語句1;

   語句2;

end loop;

 

列子1:語法11輸出到100?

declare

index_ number :=1;

begin

while index_<=100 loop

dbms_output.put_line(index_);

index_:=index_+1;

end loop;

end;

 

列子2:語法21輸出到100?

declare

index_ number:=1;

begin

loop exit when index_>=100;

dbms_output.put_line(index_);

index_:=index_+1;

end loop;

end;

 

列子3:語法31輸出到100

declare

index_ number :=1;

begin

for index_ in 1..100

loop

dbms_output.put_line(index_);

end loop;

end;

 

6)遊標

當在PL/SQL中查詢出來的結果集是多個的時候,我們要分別對每個記錄進行處理那麼我們要用到遊標,PL/SQL中的遊標我們可以想象成jdbc中的ResultSetnext next的這個過程。

語法: cursor 遊標名(參數1類型,參數2類型...) is  select語句

用法:

→打開遊標:         open 遊標名

→取出一行遊標的值: fetch  遊標名into變量

→關閉遊標:           close 遊標名

→遊標的結束方式:   exit when 遊標名%notfound

 

例子1:使用遊標的方式輸出所有員工的姓名和編號?

declare

cursor empcur is select * from emp;

emprec emp%rowtype;

begin

open empcur;

loop

fetch empcur into emprec;

exit when empcur%notfound;

dbms_output.put_line(emprec.ename||'工號'||emprec.empno);

end loop;

close empcur;

end;

     SAL      EMPNO ENAME

-------- ---------- ---------

    2000          1 王振

    2450       7782 CLARK

    5000       7839 KING

    1300       7934 MILLER

    SAL      EMPNO ENAME

------- ---------- ----------

   3000          1 王振

   3675       7782 CLARK

   7500       7839 KING

   1950       7934 MILLER

例子2:爲部門號爲10的員工漲工資?

declare

cursor empcur is select * from emp;

emprec emp%rowtype;

begin

open empcur;

loop

fetch empcur into emprec;

exit when empcur%notfound;

if emprec.deptno=10 then

dbms_output.put_line(emprec.ename||'工號'||emprec.empno);

update emp t set t.sal=t.sal+1000;

end if;

end loop;

close empcur;

end;

 

例子3:給10號部門漲10%,給20號部門漲20%,給30號部門漲30%,姓名是《MARTIN

》這個員工不能漲。

declare

cursor empcur is select * from emp;

emprec emp%rowtype;

begin

open empcur;

loop

fetch empcur into emprec;

exit when empcur%notfound;

if emprec.ename!='MARTIN' then

if emprec.deptno=10 then

update emp set sal=sal*1.1 where empno=emprec.empno;

elsif emprec.deptno=20 then

update emp set sal=sal*1.2 where empno=emprec.empno;

elsif emprec.deptno=30 then

update emp set sal=sal*1.3 where empno=emprec.empno;

end if;

end if;

end loop;

close empcur;

end;

 

7)例外(異常)

異常是程序設計中提供的一種功能,用來增強程序的容錯性和健壯性。

例外類型

描述

no_data_found

沒有找到數據

too_many_rows

Select into from 匹配了多個行

zero_divide

被零除

value_error

算術或者轉換錯誤

timeout_on_resource

在等待資源時發生意外

我們可以拋出自定義的例外,必須在聲明部分聲明意外?

 

例子1:捕獲plsql的意外?

declare

ename_ emp.ename%type;

begin

select ename into ename_ from emp where empno=0;

exception

when no_data_found then

dbms_output.put_line('找不到員工');

end;




例子2:拋出一個自定義異常

declare

empcount_ number;

empno_ number:=&empno_p;

user_not_found exception;

begin

select count(1) into empcount_ from emp where empno=empno_;

if empcount_<=0 then

raise user_not_found;

end if;

exception

when user_not_found then

dbms_output.put_line('用戶未找到');

end;


8)存儲過程

存儲過程(stored procedure)是在大型數據庫系統中,一組爲了完成特定功能的SQL語句,經過編譯後存儲在數據庫中,用戶通過指定存儲過程的名字並給出參數來執行它。存儲過程對象是數據庫中的一個重要對象,大型的企業級應用,會使用存儲過程來完成一系列複雜的操作。主要的作用是能被外部程序調用,比如jdbc

語法:

create or replace procedure 過程名(參數1參數類型,參數2  參數類型,......) is

申明變量

begin

pl/sql語句

end;(或者end存儲過程名)

例子1:我們要給指定員工漲工資100,並且打印出漲前工資和漲工資後的工資?

create or replace procedure addsal(empno_p number) is

emprec_ emp%rowtype;

empsalnew number;

begin

select * into emprec_ from emp where empno=empno_p;

empsalnew:=emprec_.sal+1000;

update emp set sal=empsalnew where empno=empno_p;

dbms_output.put_line('員工'||emprec_.ename||'原工資:'||emprec_.sal||',漲後工資:'||empsalnew);

exception

when no_data_found then

dbms_output.put_line('找不到員工');

end;

 



調用存儲過程

begin

addsal(7876);

commit;

end;

9)函數

函數和存儲過程的十分類似,區別在於函數是有返回值的,而過程沒有返回值,當然我們可以使用存儲過程的out參數來完成數據的返回動作。

函數的語法:

create or replace function 函數名(參數1 in參數類型,參數2 out參數類型...) return數據類型is

申明變量(包含結果變量);

begin

return 結果變量;

end 函數名;

例子1:用函數來獲取指定員工的年收入?

create or replace function queryEmpYearSal(empno_p in number) return number is

empsal_return number;

emprec_ emp%rowtype;

begin

select * into emprec_ from emp where empno=empno_p;

empsal_return:=emprec_.sal*12 + nvl(emprec_.comm,0);

return empsal_return;

exception

when no_data_found then

dbms_output.put_line('找不到員工信息');

empsal_return:=-1;

return empsal_return ;

end;

//sql中直接調用

select queryEmpYearSal(7876) from dual;



例子2:編寫一個函數完成nvl的功能?

create or replace function nvlnew(num1 number,num2 number) return number is

return_num number;

begin

if num1 is null then

return_num:=num2;

else

return_num:=num1;

end if;

return return_num;

end nvlnew;



10)觸發器

觸發器是一個與表關聯的PL/SQL存儲程序,每當一個特定的數據操作語句發生時例如:

insert,update,delete在指定的表上發生前或者發生後,oracle會自動執行觸發器中定義的語句序列。

1)觸發器的作用

數據確認:員工的工資超過10000000將員工的職位設置BIGBOSS

實施複雜的安全性校驗:男人的工資不能超過200

做審計、備份等操作。

2)觸發器的分類

語句級觸發

行級觸發

3)觸發器的語法

create or replace trigger 觸發器名 before或者after

deleteinsertupdate [of列名]

on 表名

[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]

[for each row[when 條件]]---使用oldnew關鍵字來引用變化前後

declare

申明變量等;...

begin

PL/SQL語句序列;

end 觸發器名;

注意:觸發器拋出運行時異常時可以阻斷事務提交;raise_application_error(-9999,’錯誤消息’)

準備活動:

create table teacher_info(

id varchar2(50) primary key,

tname varchar2(20) not null,

sex varchar2(2) check(sex in('','')),

stu_count number(10)

);

 

create table student_info(

id varchar2(50) primary key,

stuname varchar2(20) not null,

owner_tech_id  references teacher_info(id)

);

insert into teacher_info values('1','喬布斯','',49);

insert into teacher_info values('2','川普','',49);

 

insert into student_info values('1','李雷','1');

insert into student_info values('2','韓梅梅','1');

insert into student_info values('3','tom','1');

insert into student_info values('4','jerry','1');

 

例子1:老師和學生一對多,當插入學生前判斷老師的學生數量不能超過50;

create or replace trigger triger_before_insert_stu

before insert on student_info

--  referencing NEW as new

for each row

declare

  stucount_ number;

begin

     select stu_count into stucount_ from teacher_info where id=:NEW.owner_tech_id;

     if stucount_>=50 then

        raise_application_error(-20001,'老師的學生不能超過50');

     end if;

end triger_before_insert_stu;


例子2:當刪除學生的後,修改老師的學生數量字段;

create or replace trigger trigger_delete_stu after delete

on student_info

for each row

declare

begin

  update teacher_info set stu_count=stu_count-1 where id=:OLD.owner_tech_id;

end trigger_delete_stu;

 

例子3:當插入學生後,修改老師學生數量字段;

create or replace trigger trigger_after_insert_stu after insert

on student_info

for each row

declare

begin

  update teacher_info set stu_count=stu_count+1 where id=:NEW.owner_tech_id;

end trigger_after_insert_stu;

例子4:當修改學生所屬老師時候,修改老師的學生數量字段;

create or replace trigger triger_alter_update_stu

after update on student_info

--  referencing NEW as new

for each row

declare

  stucount_ number;

begin

     update teacher_info set stu_count=stu_count-1 where id=:OLD.owner_tech_id;

     update teacher_info set stu_count=stu_count+1 where id=:NEW.owner_tech_id;

end triger_before_insert_stu;

 

 

 

2.JAVA調用存儲過程

存儲過程1

create or replace procedure test_procedure(empno_p number, out_sal_   out   number) is

  emprec_ emp%rowtype;

begin

  select * into emprec_ from emp where empno=empno_p;

  out_sal_:=emprec_.sal;

exception

  when no_data_found then

  dbms_output.put_line('找不到員工');

  out_sal_:=-1;

end;

 

 

存儲過程2

create or replace procedure test_procedure_cursor(deptno_p number,outemplist outsys_refcursor) is

begin

  open outemplist for select * from emp where deptno=deptno_p;

end;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章