2016-10-04 78 views
1

我正在從Firebird將數據庫移植到PostgreSQL,並且有許多與類型轉換相關的錯誤。例如,讓我們以一個簡單的函數:PostgreSQL - 自動演算的類型?

CREATE OR REPLACE FUNCTION f_Concat3 (
    s1 varchar, s2 varchar, s3 varchar 
) 
RETURNS varchar AS 
$body$ 
BEGIN 
    return s1||s2||s3; 
END; 
$body$ LANGUAGE 'plpgsql' IMMUTABLE CALLED ON NULL INPUT SECURITY INVOKER LEAKPROOF COST 100; 

由於火鳥是相當靈活的類型本功能被稱爲是不同的:一些參數可能是另一種類型:整數/雙精度/時間戳。當然在Postgres的函數調用的f_Concat3 ('1', 2, 345.345)導致類似的錯誤:

function f_Concat3(unknown, integer, numeric) not found.

該文檔recomended使用顯式轉換,如:

f_Concat3 ('1'::varchar, 2::varchar, 345.345::varchar) 

我也可以爲所有可能的組合創建一個功能克隆鍵入可能發生的事情,它會起作用。解決錯誤的示例:

CREATE OR REPLACE FUNCTION f_Concat3 (
    s1 varchar, s2 integer, s3 numeric 
) 
RETURNS varchar AS 
$body$ 
    BEGIN 
    return s1::varchar||s2::varchar||s3::varchar; 
    END; 

但是,這是非常糟糕和醜陋的,它不適用於大功能。

重要提示:我們對所有DB都有一個通用代碼庫,並使用我們自己的語言來創建包含select查詢的應用程序對象(表單,報告等)。在函數調用中使用顯式轉換是不可能的,因爲我們將失去與其他數據庫的兼容性。

我感到困惑的是,整型參數不能被澆鑄成numericdouble precision,或date/numberstring。我甚至遇到integersmallint的問題,反之亦然。大多數數據庫不像這樣。

這種情況有什麼最佳做法嗎?
顯式轉換是否有其他選擇?

+1

您可以在調用函數時使用':: varchar'。 –

+2

爲什麼你想創建一個新的功能? Postgres已經有一個'concat()'函數可以接受任意數量的參數? –

+0

@a_horse_with_no_name concat()函數是例如。想象任何複雜的函數,其中任何輸入參數都可以寫成整數或字符串。火鳥會允許的。 – Ice2burn

回答

4

SQL是一種類型化的語言,PostgreSQL比其他關係數據庫更認真。不幸的是,這意味着使用潦草編碼移植應用程序時需要額外的努力。

這是很有誘惑力的add implicit casts,但the documentation警告你之間建立強制類型轉換的內置數據類型:

Additional casts can be added by the user with the CREATE CAST command. (This is usually done in conjunction with defining new data types. The set of casts between built-in types has been carefully crafted and is best not altered.)

這不是一個閒置的警告,因爲function resolution和其他的東西可能會突然失敗,或者如果你表現不好在現有類型之間創建新的轉換。

我認爲如果你真的不想清理代碼(這將使它更容易未來),你別無選擇,只能添加更多版本的函數。

幸運的是PostgreSQL有function overloading這使得這一點成爲可能。

您可以通過使用一個參數與函數定義一個polymorphic type,這樣使工作更容易:

CREATE OR REPLACE FUNCTION f_concat3 (
    s1 text, s2 integer, s3 anyelement 
) RETURNS text 
    LANGUAGE sql IMMUTABLE LEAKPROOF AS 
'SELECT f_concat3(s1, s2::text, s3::text)'; 

不能雖使用一個以上的anyelement的說法,因爲這將只有當所有這些工作參數是相同的類型。

如果使用函數重載,請注意不要造成使函數解析失敗的歧義。

+0

如果Postgres允許使用SQL或PL/pgSQL創建像concat()這樣的函數(它是用'「any」類型的單個參數定義的)函數,但這似乎只適用於C –

+0

有一些遺留函數具有多於13個參數,所以函數重載是最後一種選擇。僞類型是我最後的希望:) – Ice2burn