CREATE AGGREGATE
語法
CREATE AGGREGATE name ( input_data_type [ , ... ] ) ( SFUNC = sfunc, STYPE = state_data_type [ , FINALFUNC = ffunc ] [ , INITCOND = initial_condition ] [ , SORTOP = sort_operator ] ) 下面是舊語法 CREATE AGGREGATE name ( BASETYPE = base_type, SFUNC = sfunc, STYPE = state_data_type [ , FINALFUNC = ffunc ] [ , INITCOND = initial_condition ] [ , SORTOP = sort_operator ] )
描述
CREATE AGGREGATE 定義一個新的聚集函數。一些常用的聚集函數已經包含在基礎軟件包裏了;在節9.15裏有文檔記錄。如果你需要定義一個新類型或需要一個還沒有提供的聚集函數,這時 CREATE AGGREGATE 便可排上用場。
如果給出了一個模式的名字(比如 CREATE AGGREGATE myschema.myagg ...),那麼該聚集函數是在指定模式中創建的。否則它是在當前模式中創建的。
一個聚集函數是用它的名字和輸入數據類型來標識的。同一模式中如果兩個聚集處理的輸入數據不同,它們可以有相同的名字。一個聚集函數的輸入數據類型必須和所有同一模式中的普通函數的名字和輸入類型不同。
一個聚集函數是用一個或兩個普通函數做成的:一個狀態轉換函數 sfunc 和一個可選的最終計算函數 ffunc 。它們是這樣使用的:
sfunc( internal-state, next-data-values ) ---> next-internal-state ffunc( internal-state ) ---> aggregate-value
PostgreSQL 創建一個類型爲 stype 的臨時變量。它保存這個聚集的當前內部狀態。對於每個輸入數據條目,都調用狀態轉換函數計算內部狀態值的新數值。在處理完所有數據後,調用一次最終處理函數以計算聚集的返回值。如果沒有最終處理函數,則將最後的狀態值當做返回值。
一個聚集函數還可能提供一個初始條件,也就是內部狀態值的初始值。這個值是作爲一個類型爲 text 的字段存儲在數據庫裏的,不過它們必須是狀態值數據類型的合法的外部表現形式的常量。如果沒有提供狀態,那麼狀態值初始化爲 NULL 。
如果該狀態轉換函數被定義爲"strict",那麼就不能用 NULL 輸入調用它。此時,聚集的執行如下所述。帶有任何 NULL 輸入值的行將被忽略(不調用此函數並且保留前一個狀態值)。如果初始狀態值是 NULL ,那麼在第一個含有非 NULL 值的行上,使用第一個參數值替換狀態值,然後狀態轉換函數在隨後所有的含有非 NULL 值的行上調用。這樣做讓比較容易實現像 max
這樣的聚集。請注意這種行爲只是當 state_data_type 與 input_data_type 相同的時候才表現出來。如果這些類型不同,你必須提供一個非
NULL 的初始條件或者使用一個非"strice"的狀態轉換函數。
如果狀態轉換函數不是嚴格(strict)的,那麼它將無條件地在每個輸入行上調用,並且必須自行處理 NULL 輸入和 NULL 轉換值,這樣就允許聚集的作者對聚集中的 NULL 有完全的控制。
如果最終轉換函數定義爲"strict",那麼如果最終狀態值是 NULL 時就不會調用它;而是自動輸出一個 NULL 結果。這纔是 strict 函數的正常特徵。不管是那種情況,最終處理函數可以自由選擇是否返回 NULL 。比如,avg
的最終處理函數在零輸入記錄時就會返回 NULL 。
行爲類似 MIN
或 MAX
的聚集有時候可以優化爲使用索引,而不用掃描每個輸入行。如果這個聚集可以如此優化,則用一個排序操作符標識它。這裏基本的要求是聚集必須以操作符歸納出來的排序順序生成第一個元素;換句話說
SELECT agg(col) FROM tab;
必須等於
SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
更多的假設是聚集忽略 NULL 輸入,並且只有在輸入沒有非空數值的時候,它才生成 NULL 結果。通常,數據類型的 < 操作符是 MIN
的適用排序操作符,而 > 是 MAX
的適用操作符。請注意,除非聲明的操作符是
B-tree 索引操作符類的"小於"或者"大於"策略號,否則這種優化將不會生效。
參數
- name
-
要創建的聚集函數名(可以有模式修飾)
- input_data_type
-
該聚集函數要處理的輸入數據類型。要創建一個零參數聚集函數,可以使用 * 代替輸入數據類型列表。
count(*)
就是這種聚集函數的一個實例。 - base_type
-
在舊式的 CREATE AGGREGATE 語法中,輸入數據類型是通過 basetype 參數指定的,而不是寫在聚集的名稱之後。需要注意的是這種舊式語法僅允許一個輸入參數。要創建一個零參數聚集函數,可以將 basetype 指定爲 "ANY"(而不是 *)。
- sfunc
-
將在每一個輸入行上調用的狀態轉換函數的名稱。對於有 N 個參數的聚集函數,sfunc 必須有 N+1 個參數,其中的第一個參數類型爲 state_data_type ,其餘的匹配已聲明的輸入數據類型。函數必須返回一個 state_data_type 類型的值。這個函數接受當前狀態值和當前輸入數據,並返回下個狀態值。
- state_data_type
-
聚集的狀態值的數據類型
- ffunc
-
在轉換完所有輸入行後調用的最終處理函數,它計算聚集的結果。此函數必須接受一個類型爲 state_data_type 的參數。聚集的輸出數據類型被定義爲此函數的返回類型。如果沒有聲明 ffunc 則使用聚集結果的狀態值作爲聚集的結果,且輸出類型爲state_data_type 。
- initial_condition
-
狀態值的初始設置(值)。它必須是一個 state_data_type 類型可以接受的文本常量值。如果沒有聲明,狀態值初始爲 NULL 。
- sort_operator
-
用於
MIN
或MAX
類型聚集的排序操作符。這個只是一個操作符名(可以有模式修飾)。這個操作符假設接受和聚集一樣的輸入數據類型。
CREATE AGGREGATE 的參數可以以任何順序書寫,而不只是上面顯示的順序。