31.5. 函數重載

多個函數可以定義成同樣的 SQL 名字,只要它們接受的參數不同。 換句話說,函數名可以重載。 在執行一個查詢的時候,伺服器會從提供的參數的類型和個數上判斷應該調用哪個函數。 重載也可以用於模擬有變化個數參數,但是參數有上限的函數。

在建立一族重載函數的時候,我們應該小心避免歧義。比如,給出下面函數

CREATE FUNCTION test(int, real) RETURNS ...
CREATE FUNCTION test(smallint, double precision) RETURNS ...

如果給出一些簡單的輸入,比如 test(1, 1.5), 系統要想判斷出來應該調用哪個函數可不是一件很容易的事情。 目前實現的解析規則在 Chapter 10 裡描述, 但是設計一個隱含地以來這些行為的系統可不算明智。

一個接受單個復合類型參數的函數通常不應該和該類型和該類型的任何屬性(字串)同名。 記住:attribute(table) 被認為是等效於 table.attribute 的。 在這種情況下,一個復合類型上的函數會和一個復合類型的屬性有歧義, 這時候總是會使用屬性。我們可以透過使用模式修飾函數名的方法來繞開這限制 (也就是說,schema.func(table)),但是最好透過使用無衝突的名字來避免這個問題。

在重載 C 語言函數的時候,還有一個額外的約束:重載族的每個函數的 C 名字必須和所有其他函數的 C 名字不同,其它函數包括內部的和動態裝載的。 如果違反這條規則,那麼行為是不可移植的。您可能會得到一個執行時的鏈接錯誤, 或者是其中一個函數被調用(通常是內部的那個)。 SQL 命令 CREATE FUNCTION 可選的 AS 子句把 SQL 函數名和 C 原始碼裡面的函數名分離開。比如,

CREATE FUNCTION test(int) RETURNS int
    AS 'filename', 'test_1arg'
    LANGUAGE C;
CREATE FUNCTION test(int, int) RETURNS int
    AS 'filename', 'test_2arg'
    LANGUAGE C;

這裡的 C 函數名代資料表許多可能的傳統之一。