2013-04-12 79 views
0

如何根據函數中的參數大小爲oracle包中的Varchar2類型的全局變量設置大小。Oracle包中的全局變量大小

CREATE OR REPLACE PACKAGE Test 
AS 

    g_lastname Varchar2(15); 
    FUNCTION search(p_lastname IN varchar2); 

END; 

CREATE OR REPLACE PACKAGE BODY Test 
AS 
    FUNCTION search(p_lastname IN VARCHAR2) return VARCHAR2 
    IS 
    BEGIN 
     g_lastname := p_lastname; 
     return g_lastname; 
    END; 
END; 

這裏的問題是,如果p_lastname大小超過15那麼它會給出錯誤。

+0

@APC我將p_lastname的值賦給g_lastname的時候有問題,它給了我ORA-06502:PL/SQL:數字或值的錯誤:字符串緩衝區太小,錯誤。這應該是什麼原因,這裏p_lastname的大小是varchar2(1)。 謝謝。 – eatSleepCode

回答

1

不能,因爲函數參數可以是任何大小的varchar2,並且直到運行時纔會知道。

如果您知道稍後如何使用該值,那麼您可能可以基於表列對其進行約束;因此,如果它最終將在選擇從表people使用,你可以聲明爲:

g_lastname people.last_name%type; 

您也可以使用該語法在函數聲明:

FUNCTION search(p_lastname IN people.last_name%type) return VARCHAR2 

...雖然說實際上並沒有限制可以傳入的值的大小;如果p_lastname的值太大,分配仍然會失敗。可以說,在這種情況下它必須在某個時候失敗,並且這可能會比在稍後嘗試在select中使用它時更好。但它在代碼中提供了一定的一致性,並且(IMO)顯示了全局和參數的意圖,以後可以用於維護和故障排除。

如果你只是想避免錯誤,你必須截斷傳遞的值,如果它太長的選項:

 g_lastname := substr(p_lastname, 1, 15); 

...或測試長度第一,但幻數並不完全理想(如果你改變了g_lastname的定義,你必須記得找到並替換任何依賴於該長度的東西);或抓住和做一些例外。

否則沒有太大的缺點,只是宣稱它大於你認爲它可能是最多的:

g_lastname varchar2(32767); 

雖然你也許可以想出一個現實的較小的最大長度價值將永遠需要(直到有人改變了需求,當然!)。 documentation討論關於大變量的內存分配。

+0

用最大尺寸聲明變量會浪費內存,不是嗎? – eatSleepCode

+0

對於我來說%的類型也沒有幫助。 :( – eatSleepCode

+2

@eatSleepCode - 不是[根據文檔](http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/datatypes.htm#CIHEDDFG),no。您可以設置一個更現實的限制如果你能找到一個你認爲當然是安全的,但是你可以通過聲明> = 4000(字節)來節省內存。我會留下%類型的位以防其他人使用... –

1

"%type is not helpful in my case."

這很不尋常。在PL/SQL程序之間傳遞的大多數數據來自或結束於數據庫表中。所以最好的做法是通過引用相應列的聲明來定義變量和參數。

但是,對於真正不映射到任何表列的數據項,存在子類型聲明。你可以在任何地方定義這些,但它有助於組織所有的聲明在一個地方:

create or replace package types as 
    subtype name_t is varchar2(15); 
end; 
/

你可以在你的程序中使用這樣的:

CREATE OR REPLACE PACKAGE Test 
AS 

    FUNCTION search(p_lastname IN types.name_t) return types.name_t; 

END; 

(我從規範到移動g_lastname因爲將包變量封裝在主體中並僅通過打包過程訪問它們是一個好主意。)

CREATE OR REPLACE PACKAGE BODY Test 
AS 

    g_lastname types.name_t; 

    FUNCTION search(p_lastname IN types.name_t) return types.name_t 
    IS 
    BEGIN 
     g_lastname := p_lastname; 
     return g_lastname; 
    END; 
END; 

使用子類型的優點是隻有一個地方定義了類型的精度。如果您需要使用20個字符的名稱,只需更改該軟件包規範中的聲明,並將更改傳播到所有參考程序。

+0

' CREATE OR REPLACE PACKAGE測試AS g_lastname Varchar2(15); FUNCTION search(p_lastname IN varchar2); END; CREATE OR REPLACE PACKAGE BODY測試AS功能搜索(p_lastname IN VARCHAR2)返回VARCHAR2 IS BEGIN g_lastname:= p_lastname; return g_lastname; END; END;' 這裏我得到的ORA-06502:PL/SQL:數值或值錯誤:字符串緩衝區太小異常,同時分配值爲g_lastname實際上p_lastname大小爲1字節。 – eatSleepCode