SQL是用於訪問ORACLE數據庫的語言
PL/SQL擴展和加強了SQL的功能
它同時引入了更強的程序邏輯
PL/SQL支持DML命令和SQL的事務控制語句
DDL在PL/SQL中不被支持
這就意味作在PL/SQL程序塊中不能創建表或其他任何對象
較好的PL/SQL程序設計是在PL/SQL塊中使用象DBMS_SQL這樣的內建包或執行EXECUTE IMMEDIATE命令建立動態SQL來執行DDL命令
PL/SQL編譯器保證對象引用以及用戶的權限
下面我們將討論各種用於訪問ORACLE數據庫的DDL和TCL語句
查詢
SELECT語句用於從數據庫中查詢數據
當在PL/SQL中使用SELECT語句時
要與INTO子句一起使用
查詢的返回值被賦予INTO子句中的變量
變量的聲明是在DELCARE中
SELECT INTO語法如下
SELECT [DISTICT|ALL]{*|column[
column
]}
INTO (variable[
variable
] |record)
FROM {table|(sub
query)}[alias]
WHERE
PL/SQL中SELECT語句只返回一行數據
如果超過一行數據
那麼就要使用顯式游標(對游標的討論我們將在後面進行)
INTO子句中要有與SELECT子句中相同列數量的變量
INTO子句中也可以是記錄變量
%TYPE屬性
在PL/SQL中可以將變量和常量聲明為內建或用戶定義的數據類型
以引用一個列名
同時繼承他的數據類型和大小
這種動態賦值方法是非常有用的
比如變量引用的列的數據類型和大小改變了
如果使用了%TYPE
那麼用戶就不必修改代碼
否則就必須修改代碼
例
v_empno SCOTT
EMP
EMPNO%TYPE;
v_salary EMP
SALARY%TYPE;
不但列名可以使用%TYPE
而且變量
游標
記錄
或聲明的常量都可以使用%TYPE
這對於定義相同數據類型的變量非常有用
DELCARE
V_A NUMBER(
):=
;
V_B V_A%TYPE:=
;
V_C V_A%TYPE;
BEGIN
DBMS_OUTPUT
PUT_LINE
(
V_A=
||V_A||
V_B=
||V_B||
V_C=
||V_C);
END
SQL>/
V_A=
V_B=
V_C=
PL/SQL procedure successfully completed
SQL>
其他DML語句
其它操作數據的DML語句是:INSERT
UPDATE
DELETE和LOCK TABLE
這些語句在PL/SQL中的語法與在SQL中的語法相同
我們在前面已經討論過DML語句的使用這裡就不再重復了
在DML語句中可以使用任何在DECLARE部分聲明的變量
如果是嵌套塊
那麼要注意變量的作用范圍
例
CREATE OR REPLACE PROCEDURE FIRE_EMPLOYEE (pempno in number)
AS
v_ename EMP
ENAME%TYPE;
BEGIN
SELECT ename INTO v_ename
FROM emp
WHERE empno=p_empno;
INSERT INTO FORMER_EMP(EMPNO
ENAME)
VALUES (p_empno
v_ename);
DELETE FROM emp
WHERE empno=p_empno;
UPDATE former_emp
SET date_deleted=SYSDATE
WHERE empno=p_empno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT
PUT_LINE(
Employee Number Not Found!
);
END
DML語句的結果
當執行一條DML語句後
DML語句的結果保存在四個游標屬性中
這些屬性用於控制程序流程或者了解程序的狀態
當運行DML語句時
PL/SQL打開一個內建游標並處理結果
游標是維護查詢結果的內存中的一個區域
游標在運行DML語句時打開
完成後關閉
隱式游標只使用SQL%FOUND
SQL%NOTFOUND
SQL%ROWCOUNT三個屬性
SQL%FOUND
SQL%NOTFOUND是布爾值
SQL%ROWCOUNT是整數值
SQL%FOUND和SQL%NOTFOUND
在執行任何DML語句前SQL%FOUND和SQL%NOTFOUND的值都是NULL
在執行DML語句後
SQL%FOUND的屬性值將是
TRUE :INSERT
TRUE :DELETE和UPDATE
至少有一行被DELETE或UPDATE
TRUE :SELECT INTO至少返回一行
當SQL%FOUND為TRUE時
SQL%NOTFOUND為FALSE
SQL%ROWCOUNT
在執行任何DML語句之前
SQL%ROWCOUNT的值都是NULL
對於SELECT INTO語句
如果執行成功
SQL%ROWCOUNT的值為
如果沒有成功
SQL%ROWCOUNT的值為
同時產生一個異常NO_DATA_FOUND
SQL%ISOPEN
SQL%ISOPEN是一個布爾值
如果游標打開
則為TRUE
如果游標關閉
則為FALSE
對於隱式游標而言SQL%ISOPEN總是FALSE
這是因為隱式游標在DML語句執行時打開
結束時就立即關閉
事務控制語句
事務是一個工作的邏輯單元可以包括一個或多個DML語句
事物控制幫助用戶保證數據的一致性
如果事務控制邏輯單元中的任何一個DML語句失敗
那麼整個事務都將回滾
在PL/SQL中用戶可以明確地使用COMMIT
ROLLBACK
SAVEPOINT以及SET TRANSACTION語句
COMMIT語句終止事務
永久保存數據庫的變化
同時釋放所有LOCK
ROLLBACK終止現行事務釋放所有LOCK
但不保存數據庫的任何變化
SAVEPOINT用於設置中間點
當事務調用過多的數據庫操作時
中間點是非常有用的
SET TRANSACTION用於設置事務屬性
比如read
write和隔離級等
顯式游標
當查詢返回結果超過一行時
就需要一個顯式游標
此時用戶不能使用select into語句
PL/SQL管理隱式游標
當查詢開始時隱式游標打開
查詢結束時隱式游標自動關閉
顯式游標在PL/SQL塊的聲明部分聲明
在執行部分或異常處理部分打開
取數據
關閉
下表顯示了顯式游標和隱式游標的差別
表
隱式游標和顯式游標
[[The No
Picture
]]
使用游標
這裡要做一個聲明
我們所說的游標通常是指顯式游標
因此從現在起沒有特別指明的情況
我們所說的游標都是指顯式游標
要在程序中使用游標
必須首先聲明游標
聲明游標
語法
CURSOR cursor_name IS select_statement;
在PL/SQL中游標名是一個未聲明變量
不能給游標名賦值或用於表達式中
例
DELCARE
CURSOR C_EMP IS SELECT empno
ename
salary
FROM emp
WHERE salary>
ORDER BY ename;
BEGIN
在游標定義中SELECT語句中不一定非要表可以是視圖
也可以從多個表或視圖中選擇的列
甚至可以使用*來選擇所有的列
打開游標
使用游標中的值之前應該首先打開游標
打開游標初始化查詢處理
打開游標的語法是
OPEN cursor_name
cursor_name是在聲明部分定義的游標名
例
OPEN C_EMP;
關閉游標
語法
CLOSE cursor_name
例
CLOSE C_EMP;
從游標提取數據
從游標得到一行數據使用FETCH命令
每一次提取數據後
游標都指向結果集的下一行
語法如下
FETCH cursor_name INTO variable[
variable
]
對於SELECT定義的游標的每一列
FETCH變量列表都應該有一個變量與之相對應
變量的類型也要相同
例
SET SERVERIUTPUT ON
DECLARE
v_ename EMP
ENAME%TYPE;
v_salary EMP
SALARY%TYPE;
CURSOR c_emp IS SELECT ename
salary FROM emp;
BEGIN
OPEN c_emp;
FETCH c_emp INTO v_ename
v_salary;
DBMS_OUTPUT
PUT_LINE(
Salary of Employee
|| v_ename
||
is
|| v_salary);
FETCH c_emp INTO v_ename
v_salary;
DBMS_OUTPUT
PUT_LINE(
Salary of Employee
|| v_ename
||
is
|| v_salary);
FETCH c_emp INTO v_ename
v_salary;
DBMS_OUTPUT
PUT_LINE(
Salary of Employee
|| v_ename
||
is
|| v_salary);
CLOSE c_emp;
END
這段代碼無疑是非常麻煩的
如果有多行返回結果
可以使用循環並用游標屬性為結束循環的條件
以這種方式提取數據
程序的可讀性和簡潔性都大為提高
下面我們使用循環重新寫上面的程序
SET SERVERIUTPUT ON
DECLARE
v_ename EMP
ENAME%TYPE;
v_salary EMP
SALARY%TYPE;
CURSOR c_emp IS SELECT ename
salary FROM emp;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO v_ename
v_salary;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT
PUT_LINE(
Salary of Employee
|| v_ename
||
is
|| v_salary);
END
記錄變量
定義一個記錄變量使用TYPE命令和%ROWTYPE
關於%ROWsTYPE的更多信息請參閱相關資料
記錄變量用於從游標中提取數據行
當游標選擇很多列的時候
那麼使用記錄比為每列聲明一個變量要方便得多
當在表上使用%ROWTYPE並將從游標中取出的值放入記錄中時
如果要選擇表中所有列
那麼在SELECT子句中使用*比將所有列名列出
From:http://tw.wingwit.com/Article/program/Oracle/201311/17373.html