【Oracle PLSQL】基礎

一、PLSQL簡介

  • PLSQL是一種程序語言,叫做過程化SQL語言(Procedural Language/SQL)
  • PLSQL是Oracle數據庫對SQL語句的擴展。在普通SQL語句的使用上增加了編程語言的特點。
  • PLSQL是Oracle系統的核心語言,現在Oracle的許多部件都是由PLSQL
    寫成的
  • PLSQL具有簡單、高效、靈活、實用的特點
  • Oracle數據庫對SQL 的擴展是PLSQL,SQL Server則是Transac-SQL(T-SQL)

PLSQL的官方文檔地址:https://docs.oracle.com/cd/E11882_01/appdev.112/e25519/toc.htm

二、PLSQL語法結構

1.PLSQL塊

塊(block)是PLSQL的基本程序單位。由聲明部分、執行部分、異常處理部分組成

DECLARE
	/*聲明部分----聲明變量、常量、複雜數據類型、遊標等*/
BEGIN
	/*執行部分----PLSQL語句和SQL語句*/
EXCEPTION
	/*異常處理部分----處理運行錯誤*/
END;----塊結束標記
	
2.PLSQL塊的分類

匿名塊:動態構造,只能執行一次。
子程序:存儲在數據庫中的存儲過程、函數及包等。當在數據庫上建立好後可以在其它程序中調用它們。
觸發器:當數據庫發生操作時,會觸發一些事件,從而自動執行相應的程序。
示例:(全文代碼環境全部在navicat 查詢界面)

BEGIN
	DBMS_OUTPUT.PUT_LINE('hello,word!');--打印語句
END;

三、PLSQL變量

1.命名規則

當編寫PLSQL塊時,爲了臨時存儲數據,需要定義變量和常量,這些名稱的定義需要滿足一下規則:

  • 標識名不能超過30個字符
  • 第一個字符必須爲字母
  • 不分大小寫
  • 不能用“-”減號等特殊符號
  • 儘量不把變量名聲明和表中字段名一樣

參考規則(name是表名):

標識符 命名規則
程序變量 v_name
程序常量 c_name
遊標變量 name_curror
異常標識 e_name
記錄類型 name_record
2.變量類型
  • 數值類型:NUMBER(p,s)以及子類型INT、FLOAT等
  • 字符類型:CHAR(n)、VARCHAR2(n)
  • 日期類型:DATE
  • 布爾類型:BOOLEAN
3.大小寫規則

當編寫sql語句的PLSQL語句時,既可以採用大寫格式,也可以採用小寫格式。但是爲了程序的可讀性,應儘量按照以下規則:

  • SQL關鍵字採用大寫格式,如:SELECT ,UPDATE等
  • PLSQL關鍵字採用大寫格式,如:DECLARE, BEGIN, END等
  • 數據類型採用大寫格式,如:INT, DATE等
  • 標識符采用小寫格式,如:v_sal等
  • 數據庫對象和列採用小寫格式,如:emp,sal等
4.註釋
  • 單行註釋: --註釋內容
  • 多行註釋:/註釋內容/
5.變量賦值

variable:=expression
如果在聲明部分賦值,也可以使用DEFAULT關鍵字

6.示例
DECLARE
	v_name VARCHAR2(10);
	v_sal NUMBER(7,2);
	v_hiredate DATE;
	c_tax_rate CONSTANT NUMBER(3,2)= 0.02;--變量常量賦值,這裏:=也可以用DEFAULT代替
	v_tax_sal NUMBER(7,2);
	v_valid BOOLEAN DEFAULT TRUE;--DEFAULT也可以用賦值符號:=代替,布爾類型變量主要勇士邏輯判斷
	c_empno INT :=7369;
BEGIN
	SELECT ename,sal,hiredate INTO v_name,v_sal,v_hiredate FROM emp WHERE EMPNO=c_empno;--將查詢字段結果賦值給變量用INTO關鍵字,前後順序對應
	--計算納稅額
	v_tax_sal:=v_sal*c_tax_rate;
	--打印信息(使用聲明處已被賦值的變量或常量)
	DBMS_OUTPUT.PUT_LINE(v_name||'的工資是'||v_sal||',僱傭日期是'||v_hiredate||',納稅額是'||v_tax_sal);
	--條件判斷
	IF v_valid THEN
		DBMS_OUTPUT.PUT_LINE('已覈實');
	END IF;
END;

四、PLSQL引用型變量和記錄型變量

當一些變量在聲明的時候就要求和表列具有完全一致的數據類型,因此可以直接使用原表列的類型用於定義變量。

1.引用型變量

是指其數據類型與已經定義的某個數據變量的類型相同,或者與數據庫表的某個列的數據類型相同。如:v_name emp.ename%TYPE

DECLARE
	v_name emp.ename%TYPE;--v_name的數據類型和emp的ename字段相同
	v_sal emp.sal%TYPE;
BEGIN
	SELECT ename,sal INTO v_name,v_sal FROM emp WHERE empno=7788;
	DBMS_OUTPUT.PUT_LINE(v_name||'的工資是'||v_sal);
END;
2.記錄型變量

變量定義的時候使用%ROWTYPE操作符,返回一整條記錄的類型,其數據類型和數據庫表的數據結構一致。如:emp_record emp%ROWTYPE是將emp表的一整條數據類型賦給變量emp_record,emp_record.ename:='ROSE’是取其一個字段ename形成子變量

DECLARE
	emp_record emp%ROWTYPE;--emp_record就是emp表的一條記錄類型的集合
	c_tax_rate CONSTANT NUMBER(3,2)DEFAULT 0.02;
	v_tax_sal NUMBER(7,2);
BEGIN
	SELECT * INTO emp_record FROM EMP WHERE EMPNO=7788;
	v_tax_sal:=emp_record.sal*c_tax_rate;--emp_record.sal就是取其一個字段的子變量
	DBMS_OUTPUT.PUT_LINE(emp_record.ename||'的工資是'||emp_record.sal||',納稅額是'||v_tax_sal);--子變量直接使用emp表的字段名
END;

五、PLSQL運算符

1.關係運算符
運算符 含義
+ 加號
- 減號
* 乘號
** 乘方
DECLARE
	v_n1 NUMBER:=3;
	v_n2 NUMBER:=5;
BEGIN
	DBMS_OUTPUT.PUT_LINE(v_n1+v_n2);
	DBMS_OUTPUT.PUT_LINE(v_n1-v_n2);
	DBMS_OUTPUT.PUT_LINE(v_n1*v_n2);
	DBMS_OUTPUT.PUT_LINE(v_n1/v_n2);
	DBMS_OUTPUT.PUT_LINE(v_n1**v_n2);
END;
2.關係運算符
運算符 含義
= 等於
<>,!=,~=,^= 不等於
< 小於
> 大於
< 小於等於
> 大於等於
DECLARE
	v_n1 NUMBER(2):=&n1;--&替代變量,系統提示輸入,navicat中無法使用
	v_n2 NUMBER(2):=&n2;
BEGIN
	IF (v_n1 = v_n2) THEN
		DBMS_OUTPUT.PUT_LINE('等於');
	ELSIF (v_n1 > v_n2) THEN
		DBMS_OUTPUT.PUT_LINE('大於');
	ELSIF (v_n1 < v_n2) THEN 
		DBMS_OUTPUT.PUT_LINE('小於');
	END IF;

	IF (v_n1 <> v_n2) THEN
		DBMS_OUTPUT.PUT_LINE('不等於');
	END IF;
END;
3.比較運算符
運算符 含義
IS NULL 是空值
BETWEEN… AND 介於兩者之間
IN 等於列表中某個值
DECLARE
	v_num NUMBER :=3;
	v_str VARCHAR2(10):='apple';
BEGIN
	IF (v_num BETWEEN 0 AND 10) THEN
		DBMS_OUTPUT.PUT_LINE('位於0~10');
	ELSE
		DBMS_OUTPUT.PUT_LINE('不位於0~10');
	END IF;

	IF (v_num IN (1,3,5)) THEN
		DBMS_OUTPUT.PUT_LINE('在集合內');
	ELSE
		DBMS_OUTPUT.PUT_LINE('不在集合內');
	END IF;

	IF (v_num IS NULL) THEN
		DBMS_OUTPUT.PUT_LINE('爲空');
	ELSE
		DBMS_OUTPUT.PUT_LINE('不爲空');
	END IF;

	IF (v_str LIKE 'a%') THEN
		DBMS_OUTPUT.PUT_LINE('以a開頭');
	ELSE
		DBMS_OUTPUT.PUT_LINE('不以a開頭');
	END IF;
END;
4.邏輯運算符
運算符 含義
AND 邏輯與
OR 邏輯或
NOT 取反,如 IS NOT NULL, NOT IN
DECLARE
	v_b1 BOOLEAN :=TRUE;
	v_b2 BOOLEAN :=FALSE;
BEGIN
	IF (v_b1 AND v_b2) THEN
		DBMS_OUTPUT.PUT_LINE('AND--TRUE');
	END IF;
	IF (v_b1 OR v_b2) THEN
		DBMS_OUTPUT.PUT_LINE('OR--TRUE');
	END IF;
	IF (NOT v_b2) THEN
		DBMS_OUTPUT.PUT_LINE('n_b2--NOT--TRUE');
	END IF;
END;
5.NULL的運算特點
  • 空值加數字仍是空值:NULL+<數字>=NULL,所以如果要避免空值話,可以使用NVL函數
  • 空值連接字符,結束是字符:NULL||<字符串>=<字符串>
DECLARE
	v_num NUMBER :=3;
	v_str VARCHAR2(10):='apple';
BEGIN
		DBMS_OUTPUT.PUT_LINE(v_num+NULL);
		DBMS_OUTPUT.PUT_LINE(v_str||NULL);
END;

六、條件控制語句

1.IF 語句
  • 簡單條件判斷:IF-THEN
    語法格式:
IF condition THEN
	statements;
END IF;

示例:

--輸入員工號,判斷員工工資顯示小於3000的員工
DECLARE
	v_name EMP.ENAME%TYPE;
	v_sal  EMP.SAL%TYPE;
BEGIN
	SELECT ename,sal INTO v_name,v_sal FROM EMP WHERE EMPNO=&n;
	IF v_sal<3000 THEN
	 DBMS_OUTPUT.PUT_LINE(v_name);
	END IF;
END;
  • 二重條件分支:IF-THEN-ELSE
    語法格式:
IF condition THEN
	statements;
ELSE
	statements;
END IF;

示例:

--輸入員工號,判斷員工工資,將工資小於3000的員工工資漲200,並顯示漲工資的員工姓名,其它員工顯示員工姓名及工資
DECLARE
	v_name EMPNEW.ENAME%TYPE;
	v_sal  EMPNEW.SAL%TYPE;
	v_empno EMPNEW.EMPNO%TYPE=7788;
BEGIN
	SELECT ename,sal INTO v_name,v_sal FROM EMPNEW WHERE EMPNO=v_empno;
	IF v_sal<3000 THEN
		UPDATE EMPNEW SET SAL=SAL+200 WHERE EMPNO=&v_empno;
		COMMIT;--數據庫操作語言DML,執行後需要提交
		DBMS_OUTPUT.PUT_LINE(v_name||'漲工資了');
	ELSE
		DBMS_OUTPUT.PUT_LINE(v_name||'的工資是'||v_sal);
	END IF;
END;
  • 多重條件分支:IF-THEN-ELSIF
    語法格式:
IF condition THEN
	statements;
ELSIF condition THEN
	statements;	
ELSE
	statements;
END IF;

示例:

--輸入員工號,判斷員工工資,工資小於2000,顯示低收入,工資小於6000,顯示中等收入,其它顯示高收入
DECLARE
	v_name EMPNEW.ENAME%TYPE;
	v_sal  EMPNEW.SAL%TYPE;
	v_empno EMPNEW.EMPNO%TYPE:=7788;
BEGIN
	SELECT ename,sal INTO v_name,v_sal FROM EMPNEW WHERE EMPNO=v_empno;
	IF v_sal<2000 THEN
		DBMS_OUTPUT.PUT_LINE(v_name||'低收入');
	ELSIF v_sal<6000 THEN
		DBMS_OUTPUT.PUT_LINE(v_name||'中等收入');
	ELSE
		DBMS_OUTPUT.PUT_LINE(v_name||'其它');		
	END IF;
END;
2.CASE

使用CASE語句執行多重條件分支操作,語句更加簡潔執行效率更好。

  • 單一選擇符進行等值比較
    語法格式:
CASE selector
	WHEN expression1 THEN sequence_of_statements1;
	WHEN expression2 THEN sequence_of_statements2;	
	...
	WHEN expressionN THEN sequence_of_statementsN;
	[ELSE sequence_of_statements;]
END CASE;

示例:

--輸入成績等級,判斷屬於哪個層次,並打印輸出
DECLARE
	v_grade CHAR(1):='&n';
BEGIN
	CASE v_grade
		WHEN 'A' THEN
			DBMS_OUTPUT.PUT_LINE('優秀');
		WHEN  'B' THEN
			DBMS_OUTPUT.PUT_LINE('中等');
		ELSE
			DBMS_OUTPUT.PUT_LINE('其它');
	END CASE;
END;

  • 多種條件進行非等值比較
    語法格式:
CASE 
	WHEN condition1 THEN sequence_of_statements1;
	WHEN condition2 THEN sequence_of_statements2;	
	...
	WHEN conditionN THEN sequence_of_statementsN;
	[ELSE sequence_of_statements;]
END CASE;

示例:

--輸入員工號,獲取員工工資,判斷工資,如果小於1500,補助加100,如果小於2500,補助加80,如果小於5000,補助加50
DECLARE
	v_name EMPNEW.ENAME%TYPE;
	v_sal  EMPNEW.SAL%TYPE;
	v_empno EMPNEW.EMPNO%TYPE:=7788;
BEGIN
	SELECT ename,sal INTO v_name,v_sal FROM EMPNEW WHERE EMPNO=v_empno;
	CASE
		WHEN v_sal<1500 THEN
			UPDATE EMPNEW SET COMM=NVL(COMM,0)+100 WHERE EMPNO=v_empno;
		WHEN v_sal<2500 THEN
			UPDATE EMPNEW SET COMM=NVL(COMM,0)+80 WHERE EMPNO=v_empno;
		WHEN v_sal<5000 THEN
			UPDATE EMPNEW SET COMM=NVL(COMM,0)+50 WHERE EMPNO=v_empno;
		COMMIT;
	END CASE;
END;

七、循環語句

1.基本循環

語法格式:

LOOP
	statement1;
	......
END LOOP;

示例:

--循環打印數字1~10
DECLARE
	v_n INT:=1;
BEGIN	
	LOOP
		DBMS_OUTPUT.PUT_LINE(v_n);
		v_n:=v_n+1;--變量自增
		EXIT WHEN v_n>10;--退出條件
	END LOOP;
END;
2.WHILE循環

語法格式:

WHILE condition LOOP
	statement1;
	......
END LOOP;

示例:

DECLARE
	v_n INT:=1;
BEGIN
	WHILE v_n <=10 LOOP
		DBMS_OUTPUT.PUT_LINE(v_n);
		v_n:=v_n+1;
	END LOOP;
END;
3.FOR循環

語法格式:

FOR counter in [REVERSE] lower_bound ...upper_bound LOOP
	statement1;
	......
END LOOP;

注意:步長默認爲1,且不需要事先定義變量,REVERSE反相打印
示例:

BEGIN
	FOR i in 1..10 LOOP
		DBMS_OUTPUT.PUT_LINE(i);
	END LOOP;
END;

BEGIN
    FOR i  IN REVERSE 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE(i);
    END LOOP;
END;

八、嵌套循環和退出語句

1.嵌套循環

嵌套循環是指在一個循環語句中嵌入兩一個循環語句,標號用於標記嵌套塊或嵌套玄幻,使用<<label_name>>定義標號

DECLARE
	v_result INT;
BEGIN
	<<outter>>
	FOR i IN 1..5 LOOP
		<<inter>>
		FOR j IN 1..4 LOOP
			v_result:=i;
			EXIT outter WHEN i=3;
			DBMS_OUTPUT.PUT_LINE(i||j);
		END LOOP;
		DBMS_OUTPUT.PUT_LINE('內:'||v_result);--整個內循環結束一次記錄一次i的值
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('外:'||v_result);--當整個外循環全部結束後纔會執行,此時就是結束外循環時j的值
END;
2.退出語句
  • EXIT和EXIT WHEN語句
    • EXIT語句用於直接退出當前循環
    • EXIT WHEN語句用於在滿足特定條件時退出當前循環
DECLARE
	v_cnt INT:=1;
BEGIN
	LOOP
		DBMS_OUTPUT.PUT_LINE(v_cnt);
		EXIT WHEN v_cnt=10;
		v_cnt:=v_cnt+1;
	END LOOP;
END;
  • CONTINUE和CONTINUE WHEN語句
    • CONTINUE語句用於直接結束當前循環並繼續下一組循環
    • CONTINUE WHEN語句用於在滿足特定條件時結束當前循環並繼續下一組循環
DECLARE
	v_cnt INT:=0;
BEGIN
	LOOP
		v_cnt:=v_cnt+1;
		CONTINUE WHEN v_cnt=5;
		DBMS_OUTPUT.PUT_LINE(v_cnt);
		EXIT WHEN v_cnt=10;
	END LOOP;
END;

九、順序語句

1.GOTO語句

GOTO語句用於跳轉到特定標號處執行語句
GOTO label_name;
注意當桑勇GOTO跳轉到特定標號時,標號後面至少要包含一條執行語句
比較繁瑣,減少使用

DECLARE
	v_cnt INT:=1;
BEGIN
	LOOP
		DBMS_OUTPUT.PUT_LINE(v_cnt);
		IF v_cnt=10 THEN
			--EXIT;
			GOTO end_loop;
		END IF;
		v_cnt:=v_cnt+1;
	END LOOP;
	<<end_loop>>
	DBMS_OUTPUT.PUT_LINE('循環結束');--標號後面至少一條語句
END;
2.NULL語句

NULL語句不會執行任何操作,並且會直接將控制傳遞到下一個語句,使用該語句的主要目的是提高PLSQL的可讀性

--根據輸入的員工號,判斷員工的工資,如果工資小於3000,將該員工的不止加工資的2%,並打印輸出某員工的獎金更新了
DECLARE
	v_name EMPNEW.ENAME%TYPE;
	v_sal  EMPNEW.SAL%TYPE;
	v_empno EMPNEW.EMPNO%TYPE:=7369;
BEGIN
	SELECT ename,sal INTO v_name,v_sal from EMPNEW WHERE empno=v_empno;
	IF v_sal<3000 THEN
		UPDATE EMPNEW set COMM=nvl(comm,0)+sal*0.2 WHERE ename=v_name;
		COMMIT;
		DBMS_OUTPUT.PUT_LINE(v_name||'的獎金更新了');
	ELSE
		NULL;--沒有任何操作
	END IF;

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