CREATE [ OR REPLACE ] FUNCTION name ( [ argtype [, ...] ] ) RETURNS rettype { LANGUAGE langname | IMMUTABLE | STABLE | VOLATILE | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT | [EXTERNAL] SECURITY INVOKER | [EXTERNAL] SECURITY DEFINER | AS 'definition' | AS 'obj_file', 'link_symbol' } ... [ WITH ( attribute [, ...] ) ]
CREATE FUNCTION は新しい関数を定義します。 CREATE OR REPLACE FUNCTION は、新しい関数の作成、または、既存定義の置換のどちらかを行ないます。
スキーマ名が含まれている場合、関数は指定されたスキーマで作成されます。 スキーマ名がなければ、関数は現在のスキーマで作成されます。 新しい関数の名前には、同じスキーマ内の同じ引数データ型を持つ既存の関数と同じ名前は使用できません。 しかし、異なる引数データ型を持つ関数であれば、同じ名前でも構いません (これを、オーバーロード と言います)。
既存の関数定義を更新するには、CREATE OR REPLACE FUNCTION を使用します。 この方法では関数の名前や引数の型を変更することはできないことに注意して下さい。 (これを行なった場合、新しい別の関数が作成されるだけです。) また、CREATE OR REPLACE FUNCTION では、既存関数の戻り値の型を変更させることはできません。 このためには、その関数を削除し、再度作成して下さい。
関数を削除し再作成した場合、新しい関数は古いものと同じ実体にはなりません。 古い関数を参照する、既存のルール、ビュー、トリガなどは壊れてしまいます。 関数を参照するオブジェクトを破壊しないように、関数定義を変更するには CREATE OR REPLACE FUNCTION を使用します。
関数を作成したユーザが、その関数の所有者となります。
作成する関数の名前です。
もしあれば、関数の引数のデータ型です。(スキーマ修飾名も可。) 引数の型は、基本、複合、ドメイン、もしくは既存の列の型のコピーを使用することができます。
列の型を参照するには、tablename.columnname%TYPE と記述します。 これを使用して、テーブル定義が変更されても関数が影響を受けないようにすることができます。
また、言語の実装に依存しますが、cstring といった "疑似型" を指定することもできできる場合があります。 疑似型は、実際の引数の型が不完全に指定されている、もしくは、普通のSQLデータ型の集合を越えていることを示します。
返されるデータ型です。(スキーマ修飾名も可。) 返されるデータ型は、基本型、複合型、ドメイン型のいずれか、もしくは、既存の列の型のコピーを設定することができます。 既存の列の型を参照する方法については、上のargtypeの説明を参照してください。
また、実装している言語によりますが、cstring のような"疑似型" も指定することが可能です。 SETOF 修飾子は、その関数が、1 つのアイテムではなくアイテムの集合を返すことを示します。
関数を実装している言語の名前です。 このパラメータには、SQL、C、internal、もしくはユーザ定義手続き言語の名前を指定可能です。 (createlang も参照してください。) 後方互換のため、この名前を単一引用符で括ることもできます。
上記の属性を指定すると、実行時の最適化のため、関数の複数の評価を 1 つの評価に置き換えても問題ないかどうかという情報を、システムに提供することができます。 指定するのは、いずれか 1 つのみです。 指定がない場合は、デフォルトでVOLATILE と解釈されます。
IMMUTABLE を指定すると、その関数に同じ引数値を与えた場合、常に同じ結果を返します。 つまり、データベースを検索したり、その引数リスト中に直接存在しない情報を使用したりはしません。 このオプションが指定された場合、引数が定数である関数が呼び出されるとすぐ、関数値と置き換えることができます。
STABLE を指定すると、その関数に同じ引数値を与えられた場合、1 テーブルスキャン内で常に同じ結果を返すことができます。 ただし、その結果は、SQL 文が異なると変わってしまう可能性があります。 これは、関数の結果が、データベース検索や (現在のタイムゾーンのような) パラメータ変数などに依存する関数において適切な選択といえます。 また、current_timestamp ファミリの関数は、その値がトランザクション内で変更されないため、STABLE であることに注意してください。
VOLATILE を指定すると、1 テーブルスキャン内でもその関数の値を変更することが可能になります。 したがって、最適化を行なうことはできません。 このような意味で揮発的 (volatile) なデータベース関数は、比較的少数です。 たとえば、random()、currval()、timeofday() などです。 また、例えばたとえば setval()といった副作用がある関数は、その結果を完全に予測できるとしても、呼び出しを最適化しないよう、揮発的と分類する必要があることに注意してください。
CALLED ON NULL INPUT (デフォルト) を指定すると、その関数の引数に NULL がある場合でも、通常通り呼び出されます。 その場合は、必要に応じて NULL 値を確認し、適切な対応をすることが関数の作成者の責任になります。
RETURNS NULL ON NULL INPUT もしくは STRICT を指定すると、関数の引数に NULL がある場合、常に NULL を返します。 このパラメータが指定されると、その関数に NULL 引数がある場合実行されません。 代わりに、NULL という結果が自動的に仮定されます。
SECURITY INVOKER を指定すると、関数を呼び出したユーザの権限で、その関数が実行されます。 これがデフォルトです。 SECURITY DEFINER を指定すると、関数を作成したユーザの権限で、その関数が実行されます。
キーワード EXTERNAL は、SQL との互換性を保つために存在しています。 しかし、SQL とは異なり、この機能は外部関数にのみ適用されるわけではないため、このキーワードはオプションです。
関数を定義する文字列です。 この意味は言語に依存します。 内部的な関数名、オブジェクトファイルへのパス、SQLコマンド、手続き言語で書かれたテキストなどを指定できます。
この形式のAS句は、C言語のソースコード中の関数名がSQL関数の名前と同じでない場合、動的にロードされるC言語関数に使われます。 文字列obj_fileは動的にロードできるオブジェクトを含むファイルの名前で、link_symbolはC言語ソースコード中の関数の名前であるオブジェクトのリンクシンボルです。 リンクシンボルが省略された場合、定義されるSQL関数の名前と同じものであると仮定されます。
関数に関する情報を、部分的に選択して指定する伝統的な方法です。 ここで関連するのは、以下の属性です。
STRICT または RETURNS NULL ON NULL INPUT と同じです。
isCachable は、IMMUTABLE と同じですが、すでに廃止されています。 しかし、下位互換性のため、まだ受け付けることはできます。
属性名では、大文字小文字を区別しません。
さらに詳しい外部関数の書き方については 項33.3を参照してください。
SQLの型の構文は入力引数と返り値において完全に認められています。 しかし、型指定のいくつかの細部(たとえばnumeric型の精度フィールド)は、その関数の実装の仕方に責任があり、CREATE FUNCTION コマンドによって警告なく包含されます(つまり認識や強制はされません)。
PostgreSQLは関数のオーバーロードを許可します。 これは、異なる引数の型を持っていれば別の関数が同じ名前を使うことができるということです。 しかし、全ての関数のC言語における名前は異なる必要があります。 したがって、オーバーロードするCの関数には異なるCの名前を与える必要があります。 (例えば、Cの名前の一部に引数の型を使用してください。)
同一オブジェクトファイルを参照する、CREATE FUNCTION 呼び出しが繰り返された場合、そのファイルは一度だけロードされます。 (おそらく開発段階で)ファイルをアンロードし再ロードするには、LOAD コマンドを使用してください。
ユーザ定義の関数を削除するには DROP FUNCTION を使用してください。
関数定義内では、単一引用符やバックスラッシュは必ず2重にエスケープしなければなりません。
関数を定義するには、ユーザはその言語の USAGE 権限が必要です。
ここでは、初心者向けの簡単な例を示します。 より多くの情報と例が項33.3に記載されています。
CREATE FUNCTION add(integer, integer) RETURNS integer AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT;