Oracle的PL/SQL編程

什麼是PL/SQL

PL/SQL(Procedure Language/SQL)
PLSQL 是 Oracle 對 sql 語言的過程化擴展,指在 SQL 命令語言中增加了過程處理語句(如分
支、循環等),使 SQL 語言具有過程處理能力。把 SQL 語言的數據操縱能力與過程語言的數
據處理能力結合起來,使得 PLSQL 面向過程但比過程語言簡單、高效、靈活和實用。

PL/SQL的基本語法

DECLARE
	聲明部分(變量聲明,光標聲明,例外聲明)
BEGIN
	語句序列(DML語句...)
EXCEPTION
	例外處理語句
END;

聲明部分

再把數據類型貼一下
數據類型

變量的聲明方式爲先變量名,再變量類型
普通數據類型

--類型後面要跟上長度
var		char(15);

-- :=就是賦值的意思,後面可以直接跟要賦的值
married		boolean :=true;

-- number類型第一個參數爲精度,包括小數點後面的位數,第二個參數爲小數點後面的位數
psal		number(7,2)

除了普通數據類型,還有引用數據類型

-- 引用型變量,即 my_name 的類型與 emp 表中 ename 列的類型一樣
emprec 		emp.ename%type;

--使用into對它進行賦值
declare
	v_ename		emp.ename%type;
begin
	select e.ename into v_ename from emp e where e.empno = 7369;
	dbms_output.put_line(v_ename);
end;



-- 記錄型變量,爲可以接受emp表一樣所有數據的對象
v_obj_emp	emp%rowtype
    
-- 也是使用into進行賦值,注意,它只能接收到一行的數據,如果查詢結果爲多行或空,就會報錯
declare
	v_obj_emp 	emp%rowtype;
begin
	select * into v_obj_emp from emp e where e.empno = 7369;
	dbms_output.put_line(v_obj_emp.ename || ' ' || v_obj_emp.sal);
end;

邏輯控制語句

if語句

-- if語句
declare
	pnum number := # --&的功能爲從控制檯輸入 後面的num顯示在控制檯
begin
	if pnum = 1 then
		dbms_output.put_line('我是 1');
	end if;
end;

-- if else 語句
declare
	mynum number := #  
begin
	if mynum = 1 then
		dbms_output.put_line('我是 1');
	else
		dbms_output.put_line('我不是 1');
	end if;
end;


-- if  elseif 語句
declare
	mynum number := #
begin
	if mynum < 18 then
		dbms_output.put_line('未成年人');
	elsif mynum >= 18 and mynum < 40 then
		dbms_output.put_line('中年人');
	elsif mynum >= 40 then
		dbms_output.put_line('老年人');
	end if;
end;

循環

-- while loop循環
declare
step number := 1;
begin
	while step <= 10 
	loop
		dbms_output.put_line(step);
		step := step + 1;
	end loop;
end;


-- loop exit when 循環
declare
	step number := 1;
begin
	loop
		exit when step > 10;
		dbms_output.put_line(step);
		step := step + 1;
	end loop;
end;


-- for循環
declare
	step number := 1;
begin
	for step in 1 .. 10 
	loop
		dbms_output.put_line(step);
	end loop;
end;

遊標

遊標可以理解爲java中的集合,用來儲存查詢返回的多條數據
語法

CURSOR 遊標名 [(參數名 數據類型,參數名 數據類型,...)] IS SELECT語句;
--中括號內爲可選,一般不用

遊標的使用步驟
0. 定義遊標和變量 cursor c1 is select ename from emp; pjob emp.empjob%type;

  1. 打開遊標 open c1;
  2. 取一行遊標的值 fetch c1 into pjob;
  3. 當講所有值取出後關閉循環exit when c1%notfound
  4. 關閉遊標,釋放資源 close c1;

例子,用遊標的方式輸出emp表中的員工編號和姓名

declare
	cursor pc is select * from emp; --聲明遊標
	pemp emp%rowtype; --聲明記錄型變量
begin
	open pc; --開啓遊標
	loop
		fetch pc into pemp; --取出遊標每一行的數據
		exit when pc%notfound; --當遊標所有數據被取出後,跳出循環
		dbms_output.put_line(pemp.empno || ' ' || pemp.ename); -- 執行邏輯操作
	end loop;
	close pc;
end;

另一個例子,爲部門號爲10的員工漲工資

declare
	cursor pc(dno myemp.deptno%type) is 
	select empno from myemp where deptno = dno; --聲明遊標
	pno myemp.empno%type; --聲明記錄型變量
begin
	open pc(20); --開啓遊標
	loop
		fetch pc into pno; --取出遊標的每一行數據賦值給變量
		exit when pc%notfound; --當遊標所有值被取出,跳出循環
		update myemp t set t.sal = t.sal + 1000 where t.empno =
		pno; --執行邏輯命令
	end loop;
	close pc; --關閉遊標,釋放資源
end;

例外

異常是程序設計語言提供的一種功能,用來增強程序的健壯性和容錯性。Oracle PL/SQL中的異常就是例外
Oracle中內置了20000個例外,絕大多數需求都可以被滿足
比較常用的有

no_data_found (沒有找到數據)
too_many_rows (select …into 語句匹配多個行)
zero_divide ( 被零除)
value_error (算術或轉換錯誤)
timeout_on_resource (在等待資源時發生超時)

舉個栗子

declare
	pnum number;
begin
	pnum := 1 / 0;
exception
	when zero_divide then
		dbms_output.put_line('被0除');
	when value_error then
		dbms_output.put_line('數值轉換錯誤');
	when others then
		dbms_output.put_line('其他錯誤');
end;

此外,我們可以自定義例外,處理業務異常
看下面這個例子

declare
	no_emp_found exception; --聲明一個例外
	cursor pemp is
	select t.ename from emp t where t.deptno = 50; --聲明瞭一個遊標
	pename emp.ename%type; --聲明瞭一個記錄型變量
begin
	open pemp;
	fetch pemp into pename;
	if pemp%notfound then
		raise no_emp_found; --觸發在下面定義的 no_emp_found
	end if;
	close pemp;
exception
	when no_emp_found then
		dbms_output.put_line('沒有找到員工');
	when others then
		dbms_output.put_line('其他錯誤');
end;

需要注意的是,沒事使用自定義例外都要重新編寫,聲明

儲存過程

存儲過程(Stored Procedure)是在大型數據庫系統中,一組爲了完成特定功能的 SQL 語句集,經編譯後存儲在數據庫中,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。
儲存過程就相當於java中封裝的方法;

創建格式如下

create [or replace] PROCEDURE  過程名[(名 參數名 in/out  數據類型)] AS
begin
	PLSQL 子程序體; 子程序體;
End;

--或者
create [or replace] PROCEDURE  過程名[(名 參數名 in/out  數據類型)] is
	定義儲存過程需要用到的變量
begin
	PLSQL 子程序體; 子程序體;
End 過程名 過程名;

看這個例子 給員工變更工資 並打印 前後工資的情況


--參數要注意下,in爲輸入的參數,out爲輸出的參數,這個場景下,我們只需要進行數據輸入
--而且參數不需要寫數據類型的參數
--一般儘量使用CREATE OR REPLACE這樣就算改儲存過程已經存在,也可以進行更改
CREATE OR REPLACE PROCEDURE CHANGEEMPSALBYENPNO(ENO IN NUMBER,MON IN NUMBER)
IS
       V_OLD_SAL EMP.SAL%TYPE;
       V_NEW_SAL EMP.SAL%TYPE;
BEGIN
       --查詢漲工資之前的工資情況,賦值給變量V_OLD_SAL;
       SELECT E.SAL INTO V_OLD_SAL FROM EMP E 
       WHERE E.EMPNO=ENO;
       --對該員工工資數據進行操作,並提交
       UPDATE EMP SET SAL=SAL+MON where empno=eno;
       COMMIT;
       --再查詢一下變更之後的該員工工資
       SELECT E.SAL INTO V_NEW_SAL FROM EMP E
       WHERE E.EMPNO=ENO;
       DBMS_OUTPUT.put_line('操作完成!');
       dbms_output.put_line('漲工資之前:'||V_OLD_SAL);
       dbms_output.put_line('漲工資之後'||V_NEW_SAL);
exception
       WHEN NO_DATA_FOUND THEN
           DBMS_OUTPUT.put_line('沒有查詢到數據!');
       WHEN TOO_MANY_ROWS THEN 
           DBMS_OUTPUT.put_line('查詢返回多條結果!');
       WHEN OTHERS THEN
           dbms_output.put_line('系統未知錯誤!');
end;     



--調用這個儲存過程非常簡單
begin
           CHANGEEMPSALBYENPNO(7369,100);
end;

===========輸出結果==============
操作完成!
漲工資之前:800
漲工資之後900

儲存函數

儲存函數和儲存過程本質上沒區別。只是函數有限制只能返回一個標量,而存儲過程可以返回多個。並且函數是可以嵌入在SQL中使用的,可以在SELECT等SQL語句中調用,而存儲過程不行。執行的本質都一樣。

create or replace function  函數名(Name in type, Name out type, ...) return 型 數據類型 is
	 結果變量 數據類型;
begin
	return( 結果變量);
end[ 函數名];
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章