PL/SQL編碼規(guī)范: 注釋、變量命名、書寫格式、邏輯分支、 循環(huán)處理
PL/SQL編碼規(guī)范
TBPL/SQL的編碼規(guī)范包括:
² 注釋
² 變量命名
² 書寫格式
² 邏輯分支
² 循環(huán)處理
1.2.1注釋
1. 請在所有程序一開始處嚴格按如下格式寫出注釋塊:
-- *******************************************
-- 過程名:
-- 功能描述:
-- 輸入?yún)?shù)說明:
-- 輸出參數(shù)說明:
-- 調(diào)用的過程或函數(shù):
-- 被哪些過程或函數(shù)調(diào)用:
-- 創(chuàng)建人員:
-- 創(chuàng)建日期:
-- 修改人員:
-- 修改日期:
-- 修改原因:
-- 修改結(jié)果:
-- 版本說明:
-- 引用對象:
-- *******************************************
2. 通常在PL/SQL塊的declare,begin,exception和end部分設(shè)置分隔線和注釋;
3. 每個變量都需要加上變量的注釋,說明變量的用途;
4. 請在重要的程序段和難懂的程序段加上分隔線和注釋;
5. 請注明游標等的用途和用法
6.注釋量與程序量的總比例盡量做到1 :1。
1.2.2變量取名及含義
變量取名請遵守命名規(guī)范,對使用頻繁、關(guān)鍵變量,為了便于閱讀和修改,請在定義時加上注釋標明其含義。
為了便于閱讀和調(diào)試,盡量少用單字母變量,禁止使用諸如i、l等作為變量名,同時注意小寫字母l和數(shù)字1之間的區(qū)別使用。并嚴禁使用關(guān)鍵字,要符合ORACLE的命名規(guī)范。
1.2.3對現(xiàn)有程序的修改
1. 刪除 在刪除代碼前后上/*deleted by yourname on yyyy/mm/dd start*/和/*deleted by yourname on yyyy/mm/dd end*/ 同時請注明刪除的原因。
2. 修改 將原有的代碼全部注釋(刪除)掉,在最后說明注釋的原因,同時將你新增加的代碼寫在注釋后,首先加上/*modified by yourname on yyyy/mm/dd start*/和/* modified by yourname on yyyy/mm/dd end*/ 需要保證
a. 所有被注釋的代碼都是原來的代碼
b. 所有沒有被注釋的代碼都是新增加的代碼
3. 增加,在增加的代碼前加后/*added by yourname on yyyy/mm/dd start*/和/*added by yourname on yyyy/mm/dd end*/ 同時請注釋說明,增加的原因等。
為了便于閱讀和調(diào)試,盡量少用單字母變量,禁止使用諸如i、l等作為變量名,同時注意小寫字母l和數(shù)字1之間的區(qū)別使用。
請注意,必須在PL/SQL代碼的開頭處,詳細說明你所做的修改,包括修改了那些地方,修改的原因,修改的日期,修改人等。
1.2.4書寫格式
1.用語句分層縮進的寫法顯示嵌套結(jié)構(gòu)的層次;
2.在注釋段與程序段、以及不同程序段插入空行;
3.每行只寫一條語句。
1.2.5邏輯分支
邏輯分支的格式如下:
l IF……THEN
……
ELSE
……
END IF;
l CHOOSE CASE
CASE 1 …
……
CASE 2 …
……
CASE ELSE …
……
CASE END;
1.2.6循環(huán)處理
循環(huán)處理的格式如下:
l FOR …… LOOP
……
END LOOP;
l WHILE ……LOOP
……
END LOOP;
l DECLARE
CURSOR cursor_name IS
……
(SQL STATEMENT FOR THER CURSOR)
BEGIN
FOR variable_name IN cursor_name LOOP
…
(STATEMENT)
END LOOP;
END
1.2.7 游標處理
游標的本身就是一個SQL的工作區(qū),用于處理多行或單行的查詢處理,主要分為如下兩類
1. implicit cursor由DML和PL/SQL的SELECT隱式的定義,不能使用FETCH,OPEN,COLSE等來控制SQL游標,但可以使用游標的屬性,如select xxx into xxx from xxx.
2. explicit cursor主要由程序控制,用于顯示返回一行或者多行數(shù)據(jù)。
執(zhí)行的四個步驟
:
1.
聲明:定義游標的名字和結(jié)構(gòu),select 中可以使用order by
2.打開游標:執(zhí)行查詢同時綁定所有涉及到的變量
執(zhí)行的內(nèi)容:
為select 分配內(nèi)存并分析select語句
綁定輸入的變量
配置指針在活動集的第一行
注意:如果 查詢不返回結(jié)果,不會引發(fā)PL/SQL的異常,你可以在執(zhí)行fetch后測試返回的結(jié)果
如果游標內(nèi)的聲明包括update。一樣會執(zhí)行行鎖定
3.Fetch:把當前行的值賦給變量,每個fetch都會把游標指針向下移動一行。
如果到了最后一行就會自動退出for loop
4.關(guān)閉:釋放活動的集,可以再次使用open
游標的幾個屬性:
SQL%ROWCOUNT 受最近執(zhí)行的SQL語句影響的行的數(shù)目。(一個整數(shù)值)
SQL%FOUND Boolean屬性,如果最近的SQL語句影響了一行或多行,其值為
TRUE。
SQL%NOTFOUND Boolean屬性,如果最近的SQL語句沒有影響任何行,其值為
TRUE。
SQL%ISOPEN 總是為FALSE,原因是PL/SQL總是它們結(jié)束執(zhí)行后立即關(guān)閉內(nèi)隱游標。
例子
EG1:常規(guī)用法
CURSOR c1 IS
SELECT empno, ename
FROM emp;
emp_record c1%ROWTYPE;
BEGIN
OPEN c1;
. . .
FETCH c1 INTO emp_record;
EG2:使用for循環(huán)實現(xiàn)游標
DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp;
emp_record c1%ROWTYPE;
BEGIN
FOR emp_record IN c1 LOOP
-- implicit open and implicit fetch occur
IF emp_record.empno = 7839 THEN
...
END LOOP; -- implicit close occurs
END;
游標FOR循環(huán)不需要FETCH語句的。游標打開,在循環(huán)中每次重復(fù)提取一行,所有的行都處理后,游標會自動關(guān)閉。
EG3:不定義游標的方式
BEGIN
FOR emp_record IN ( SELECT empno, ename
FROM emp) LOOP
-- implicit open and implicit fetch occur
IF emp_record.empno = 7839 THEN
...
END LOOP; -- implicit close occurs
END;
EG1:帶變量的游標
你必須指定指定參數(shù)的數(shù)據(jù)類型,但不用指定大小
DECLARE
CURSOR c1
(v_deptno NUMBER, v_job VARCHAR2) IS
SELECT empno, ename
FROM emp
WHERE deptno = v_deptno
AND job = v_job;
BEGIN
OPEN c1(10, 'CLERK');
...
EG5:FOR UPDATE----當加上for update則把整個表或字段鎖住了。
SELECT ... FROM ...
FOR UPDATE [OF column_reference][NOWAIT]
DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp
FOR UPDATE NOWAIT;
NOWAIT:返回一個oracle的錯誤信息如果此行給其他的會話鎖住了。
EG6:WHERE CURRENT OF
用于在游標中刪除和更新當前行
必須使用 FORUPDATE去鎖住行
使用WHERE CURRENT OF去指向當前的行
DECLARE
CURSOR c1 IS
SELECT ...
FOR UPDATE NOWAIT;
BEGIN
...
FOR emp_record IN c1 LOOP
UPDATE ...
WHERE CURRENT OF c1;
...
END LOOP;
COMMIT;
END;
1.2.8 異常處理
PL/SQL的異常主要分為三大類
1. Predefined Exception 異常
2. Non-Predefined Exception異常
3. User Defined Exception 異常
其中1,2將隱式raised,3需要顯示raised
如下例子
Predefined Exception
BEGIN SELECT ... COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
statement1;
statement2;
WHEN TOO_MANY_ROWS THEN
statement1;
WHEN OTHERS THEN
statement1;
statement2;
statement3;
END;
…….
Non-Predefined Exception
DECLARE
e_products_invalid EXCEPTION;
PRAGMA EXCEPTION_INIT (
e_products_invalid, -2292);
v_message VARCHAR2(50);
BEGIN
. . .
EXCEPTION
WHEN e_products_invalid THEN
:g_message := 'Product code
specified is not valid.';
. . .
END;
User-Defined Exception
DECLARE
e_amount_remaining EXCEPTION;
. . .
BEGIN
. . .
RAISE e_amount_remaining;
. . .
EXCEPTION
WHEN e_amount_remaining THEN
:g_message := 'There is still an amount
in stock.';
. . .
END;
RAISE_APPLICATION_ERROR
DECLARE
…….
Invalidpart EXCEPTION;
BEGIN
…….
IF SQL%NOTFOUND THEN
RAISE invalidpart;
END IF;
EXCEPTION
WHEN invalidpart THEN
Raise_application_error(-20003,’Invalid Part id #’|| partnum);
WHEN OTHERS THEN
Raise_application_error(-20000,errNum||errMsg);
END
² 使用EXCEPTION關(guān)鍵字在一個PL/SQL塊的聲明部分聲明用戶自定義異常
² 使用PL/SQL命令RAISE檢測用戶自定義異常
² PL/SQL可使用Raise_Application_Error過程返回一個用戶自定義錯誤數(shù)和消息給調(diào)用環(huán)境。所有的用戶自定義錯誤消息必須在-20000到-20999之間
² PL/SQL程序可以使用WHEN OTHERS 異常處理來處理沒有特定處理的所有異常,WHEN OTHERS一定放在異常處理的最后
² PL/SQL程序可以使用特殊的SQLCODE和SQLERRM函數(shù)返回oracle內(nèi)部錯誤號碼和消息
² SQLCODE SQLERRM,SQLCODE返回一個NUMBER型的錯誤類型,而SQLERRM將返回錯誤類型相關(guān)的錯誤信息描述。
DECLARE
v_error_code NUMBER;
v_error_message VARCHAR2(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
ROLLBACK;
v_error_code := SQLCODE ;
v_error_message := SQLERRM ;
INSERT INTO errors VALUES(v_error_code,
v_error_message);
END;