plsql 書寫命名規範

俗話說事不預則廢,無規矩不成方圓。sql

對sql腳本程序的設計,我的認爲應該是從編碼規範開始。網絡

前段時間公司一些同事提交的腳本,風格迥異,讓我審覈起來倍感難受,絲毫沒有審覈代碼的快感。oracle

特整理了公司部分常規的編碼規範,對新人進行了培訓,但願同志們寫的代碼更美觀和高效(注:規範部分收集於網絡,感謝網絡大蝦們的貢獻):app

 

 

1.1. PL/SQL 程序命名規範

1.              不管是 PL/SQL 對象仍是 PL/SQL 對象內部用的變量和遊標等,都必須能從名稱上能讓人理解變量和遊標的含義,並且必定要作好註釋。函數

2.              傳到 CVS 上的文本文件所有采用 ’.sql’ 做爲文件名的後綴oop

1.1.1.   存儲過程

存儲過程的命名必須符合USP_DETAILNAME 格式,其中 USP 表示是存儲過程,DETAILNAME 是與存儲過程意義相關的意義的名稱,如:USP_BUSINESS_RULE 。測試

1.1.2.   軟件包

軟件包的命名必須符合PKG_ DETAILNAME 格式,其中 PKG 表示是軟件包, DETAILNAME 是與軟件包意義相關的意義的名稱,例如:PKG_SORCE_ALL 。fetch

1.1.3.   觸發器

觸發器的的命名必須符合TRG_DETAILNAME 格式,其中TRG 表示是觸發器,DETAILNAME 是與觸發器用途相關的意義的名稱,具體能夠參考已有的TRIGGER 對象。編碼

1.1.4.   函數

  函數的命名必須符合FNC_DETAILNAME 格式,其中FNC 表示是函數,,DETAILNAME 是與函數意義相關的意義名稱,例如:FNC_SALARYCOUNT 。設計

1.1.5.   變量&遊標

1.    變量的命名必須符合規約, 請採用 」 XXX_variablename 」 開頭, 其中XXX 表示變量的類型。Variablename 表示變量名,如爲函數傳入參數請根據傳入類型加上IN,OUT,INOUT 等,如: IN_NUM_CUST_CODE.

 

2.    若是依據表的字段請採用%type 或者%rowtype 方式。請不要直接定義變量。

如: NUM_CUST_CODE TableName.CUST_CODE%type

3.    顯示遊標請採用 」 CUR_ 」 開頭,在代碼開頭請說明,同時說明遊標的定義.

如:CUR_CUST_INFO

   

4.    全部的變量前必須帶上變量類型的標誌,NUMBER 型採用NUM,VARCAHR2 採用VAR ,而在函數等入口的傳入方法IN_VAR_CUST_NAME,OUT_NUM_CODE,INOUT_NUM_CODE 的方式來區分變量的類型是否位IN,OUT,INOUT 類型

5.    不能超過30 個字符,不能採用關鍵字,要以字母開頭。

 

 

注: 以上命名規則將主要在於新建對象時使用,若是在原有的PL/SQL 對象的基礎上修改,請按照原來代碼的命名規範,注意作好代碼的註釋。同時必須在PL/SQL 代碼開頭,作好註釋說明。

1.2. PL/SQL 編碼規範

PL/SQL 的編碼規範包括:

²        註釋

²        變量命名

²        書寫格式

²        邏輯分支

²       循環處理

1.2.1註釋

1.  請在全部程序一開始處嚴格按以下格式寫出註釋塊:

-- *******************************************

-- 過程名: 

-- 功能描述:

-- 輸入參數說明:

-- 輸出參數說明:

-- 調用的過程或函數:

-- 建立人員:

-- 建立日期:

-- 修改人員:

-- 修改日期:

-- 修改緣由:

-- 修改結果:

-- 版本說明:

-- ********** *********************************

2.  一般在PL/SQL 塊的declare ,begin ,exception 和end 部分設置分隔線和註釋;

3.  每一個變量都須要加上變量的註釋,說明變量的用途;

4.  請在重要的程序段和難懂的程序段加上分隔線和註釋;

5.  請註明遊標等的用途和用法

6. 註釋量與程序量的總比例儘可能作到1 :1 。

1.2.2變量取名及含義

變量取名請 遵照命名規範,對使用頻繁、關鍵變量,爲了便於 閱讀和修改, 請在定義時加上註釋標明其含義。

爲了便於閱讀和調試,儘可能少用單字母變量,禁止使用諸如i 、l 等做爲變量名,同時注意小寫字母l 和數字1 之間的區別使用。並嚴禁使用關鍵字,要符合ORACLE 的命名規範。

1.2.3對現有程序的修改

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*/ 同時請註釋說明,增長的緣由等。

爲了便於閱讀和調試,儘可能少用單字母變量,禁止使用諸如i 、l 等做爲變量名,同時注意小寫字母l 和數字1 之間的區別使用。

 

請注意,必須在PL/SQL 代碼的開頭處,詳細說明你所作的修改,包括修改了那些地方,修改的緣由,修改的日期,修改人等。

1.2.4書寫格式

1. 用語句分層縮進的寫法顯示嵌套結構的層次;

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循環處理

循環處理的格式以下:

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 的工做區,用於處理多行或單行的查詢處理,主要分爲以下兩類

1.     implicit cursor 由DML 和PL/SQL 的SELECT 隱式的定義,不能使用FETCH,OPEN,COLSE 等來控制SQL 遊標,但可使用遊標的屬性, 如select xxx into xxx from xxx.

2.     explicit cursor 主要由程序控制, 用於顯示返回一行或者多行數據。

執行的四個步驟

1.

聲明:定義遊標的名字和結構,select 中可使用order by

 

2. 打開遊標:執行查詢同時綁定全部涉及到的變量

執行的內容:

爲select 分配內存並分析select 語句

綁定輸入的變量

配置指針在活動集的第一行

注意: 若是 查詢不返回結果,不會引起PL/SQL 的異常,你能夠在執行fetch 後測試返回的結果

若是遊標內的聲明包括update 。同樣會執行行鎖定

3.Fetch :把當前行的值賦給變量,每一個fetch 都會把遊標指針向下移動一行。

           若是到了最後一行就會自動退出for loop

 

4. 關閉:釋放活動的集, 能夠再次使用open 

 

遊標的幾個屬性:

 SQL%ROWCOUNT 受最近執行的SQL 語句影響的行的數目。(一個整數值) 
SQL%FOUND Boolean 屬性,若是最近的SQL 語句影響了一行或多行,其值爲 
TRUE 。 
SQL%NOTFOUND Boolean 屬性,若是最近的SQL 語句沒有影響任何行,其值爲 
TRUE 。 
SQL%ISOPEN 老是爲FALSE ,緣由是PL/SQL 老是它們結束執行後當即關閉內隱遊標。

 

例子

EG1: 常規用法

CURSOR c1 IS

    SELECT empno, ename

    FROM       emp;

  emp_record   c1%ROWTYPE;

BEGIN

  OPEN c1;

. . .

  FETCH c1 INTO emp_record;

 

 

 

 

EG2: 使用for 循環實現遊標

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 循環不須要FETCH 語句的。遊標打開,在循環中每次重複提取一行,全部的行都處理後,遊標會自動關閉。

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: 帶變量的遊標

你必須指定指定參數的數據類型,但不用指定大小

  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 關鍵字在一個PL/SQL 塊的聲明部分聲明用戶自定義異常

²        使用PL/SQL 命令RAISE 檢測用戶自定義異常

²        PL/SQL 可以使用Raise_Application_Error 過程返回一個用戶自定義錯誤數和消息給調用環境。全部的用戶自定義錯誤消息必須在-20000 到-20999 之間

²        PL/SQL 程序可使用WHEN OTHERS 異常處理來處理沒有特定處理的全部異常,WHEN OTHERS 必定放在異常處理的最後

²        PL/SQL 程序可使用特殊的SQLCODE 和SQLERRM 函數返回oracle 內部錯誤號碼和消息

²        SQLCODE SQLERRM ,SQLCODE 返回一個NUMBER 型的錯誤類型,而SQLERRM 將返回錯誤類型相關的錯誤信息描述。

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;

相關文章
相關標籤/搜索