2010-02-25 76 views
14

我一直在BEGIN ... END塊中將代碼小節偶然分組,當它看起來正確時。大多數情況下,當我正在處理更長的存儲過程並且需要在一個地方使用臨時變量時,我會爲該代碼的那部分聲明它。當我想識別和處理針對特定代碼段拋出的異常時,我也會這樣做。什麼時候應該嵌套PL/SQL BEGIN ... END塊?

爲什麼要在程序,函數或其他更大的PL/SQL塊中嵌套塊的其他原因?

回答

17

當你想在本地處理異常這樣的:

begin 
    for emp_rec in (select * from emp) loop 
     begin 
     my_proc (emp_rec); 
     exception 
     when some_exception then 
      log_error('Failed to process employee '||emp_rec.empno); 
     end; 
    end loop; 
end; 

在這個例子中,異常被處理,然後我們繼承和處理下一個員工。

的另一個用途是聲明局部變量具有有限的範圍是這樣的:

declare 
    l_var1 integer; 
    -- lots of variables 
begin 
    -- lots of lines of code 
    ... 
    for emp_rec in (select * from emp) loop 
     declare 
     l_localvar integer := 0; 
     begin 
     -- Use l_localvar 
     ... 
     end 
    end loop; 

end; 

你要知道,想要做這往往是一個跡象,表明你的程序太大,應該被打破了:

declare 
    l_var1 integer; 
    -- lots of variables 
    ... 
    procedure local_proc (emp_rec emp%rowtype): 
     l_localvar integer := 0; 
    begin 
     -- Use l_localvar 
     ... 
    end 
begin 
    -- lots of lines of code 
    ... 
    for emp_rec in (select * from emp) loop 
     local_proc (emp_rec); 
    end loop; 

end; 
+1

+1。 「開始/結束」塊的最佳做法是匿名塊,命名塊(過程/函數)或處理特定異常,如第一個示例中所述。在'begin/end'塊中嵌套一個'declare'語句,我會調用一個編程錯誤,因爲它引入了可變範圍碰撞的可能性,而這些都是一個調試的痛苦。 – 2010-02-25 18:48:51

1

當我想創建特定於只存在於塊內的數據的過程時,我傾向於嵌套塊。這是一個人爲的例子:

BEGIN 
    FOR customer IN customers LOOP 
    DECLARE 

     PROCEDURE create_invoice(description VARCHAR2, amount NUMBER) IS 
     BEGIN 
     some_complicated_customer_package.create_invoice(
      customer_id => customer.customer_id, 
      description => description, 
      amount => amount 
     ); 
     END; 

    BEGIN 

     /* All three calls are being applied to the current customer, 
     even if we're not explicitly passing customer_id. 
     */ 
     create_invoice('Telephone bill', 150.00); 
     create_invoice('Internet bill', 550.75); 
     create_invoice('Television bill', 560.45); 

    END; 
    END LOOP; 
END; 

誠然,這通常不是必要的,但它已經來到了真的方便,當一個程序可以從許多地方調用。

+0

我看不到需要 - 你已經在一個循環內。其次,存儲過程聲明不應該發生在循環之外嗎? – 2010-02-25 15:12:47

+0

@OMG Ponies:這個例子的目的是爲了說明這樣一個事實,即可以在塊中聲明過程來利用該塊的數據,而不必通過參數傳遞信息。你是對的,如果你想明確地把'customer_id'作爲參數傳遞給'create_invoice',它就必須在循環之外聲明。根據我的經驗,我遇到了利用該塊信息更清晰的情況。 – 2010-02-25 15:59:03

0

嵌套BEGIN/END塊的一個原因是能夠處理代碼的特定本地部分的異常,並且可能在處理異常時繼續處理。

相關問題