CREATE TYPE typename ( INPUT = input_function, OUTPUT = output_function , INTERNALLENGTH = { internallength | VARIABLE } [ , DEFAULT = default ] [ , ELEMENT = element ] [ , DELIMITER = delimiter ] [ , PASSEDBYVALUE ] [ , ALIGNMENT = alignment ] [ , STORAGE = storage ] ) CREATE TYPE typename AS ( column_name data_type [, ... ] )
作成するデータ型の名前です (スキーマ修飾名でも可)。
新しいデータ型の内部長を指定するリテラル値です。
CREATE FUNCTION で作成した、外部形式のデータをその型の内部形式のデータに変換する関数の名前です。
CREATE FUNCTION で作成した、内部形式によるデータを表示に適した形式のデータに変換する関数の名前です。
配列型を作成する場合、その配列の要素の型を指定します。
このデータ型の配列値間の区切り文字です。
そのデータ型のデフォルト値です。 通常、これは省略されます。省略された場合、デフォルトは NULL です。
データ型の格納位置配置条件です。 このオプションが指定された場合、char、 int2、int4またはdoubleである必要があります。 デフォルトはint4です。
データ型の格納手法です。 指定する場合は、plain、 external、extended、または 'mainでなければなりません。 デフォルトは plainです。
複合型の列の名前です。
既存のデータ型の名前です。
CREATE TYPE を実行すると、ユーザは、現在のデータベースで使用する新しいデータ型を PostgreSQL に登録することができます。 データ型を定義したユーザが、その所有者となります。
スキーマ名が与えられている場合、そのデータ型は指定されたスキーマで作成されます。 スキーマ名がなければ、そのデータ型は現在のスキーマ (検索パスの前にあるスキーマ。CURRENT_SCHEMA() 参照) で作成されます。 データ型名は、同じスキーマにある既存のデータ型もしくはドメインとは異なる名前にする必要があります。 (また、テーブルはデータ型と関連しているため、データ型名は同じスキーマのテーブル名とも競合しないようにしてください。)
1 つ目の CREATE TYPE の形式を使用すると、基本型 (スカラ型) を新しく作成できます。 CREATE TYPE では、型を定義する前に、(CREATE FUNCTION を用いて) 2 つの関数を登録しておく必要があります。新しい基本型の表現形式は、型の外部表現形式をその型用に定義された演算子と関数が使用可能な内部表現形式に変換する、input_function で決定されます。当然、 output_function はこの逆の変換をします。 入力関数は、1 つの cstring 型の引数、または、cstring、OID、int4 という 3 つの引数をとるように宣言されます。 (最初の引数は C スタイルの入力テキスト、2 番目は配列型の場合の要素の型、3 番目は既知の場合、対象列の typmod です。) この関数では、データ型自身の値を返します。 出力関数は、新しいデータ型の 1 つの引数、または、2 番目の型が OID 型である 2 つの引数をとるように宣言されます。 (入力関数と同じく、2 番目の引数は、配列型の場合の配列要素の型です。) 出力関数では、cstring 型を返します。
ここで、新しいデータ型を作成できるより前に入力または出力関数を作成する必要があるのに、どうしてその関数で新しいデータ型の結果や入力を受け取るように宣言できるのか、疑問に思うかもしれません。 そのような疑問の答えは、まず入力関数が最初に作成され、それから出力関数、そして最後にデータ型が作成される必要があるということです。 PostgreSQL では、まず入力関数の戻り値の型として新しいデータ型の名前を参照します。 その際に、"shell" 型を作成します。shell 型は、単に pg_type 内のプレースホルダエントリであり、入力関数の定義とリンクされます。 同様に、出力関数も (この時点ですでに作成されている) shell 型とリンクされます。 最後に、CREATE TYPE を実行すると、shell エントリが完全なデータ型定義に置き換えられ、新しいデータ型が使用可能になります。
Note: PostgreSQL 7.3 より前のバージョンでは、関数の下位参照を、プレースホルダ擬似データ型である OPAQUE 型のデータ型名と置き換えることによって、shell 型を作成することを慣習的に避けていました。 また、7.3 より前のバージョンでは、cstring 型の入力および結果も OPAQUE 型として宣言する必要がありました。 古いダンプファイルのロードをサポートするため、CREATE TYPE では opaque 型を使用するように宣言された関数を受け入れます。しかし、NOTICE を発行し、正しいデータ型を使用するように関数の宣言を変更します。
新しい基本型を、internallength が正の整数となる固定長として作成することも、internallength を VARIABLE に設定することで示される可変長として作成することもできます。 (内部的には、これは typlen を -1 に設定することで表現されます。) 全ての可変長型の内部表現は、型の値の全長を示す整数値から始まらなければなりません。
データ型が配列であることを示すには、ELEMENT キーワードを使用して配列要素の型を指定して下さい。 例えば、4 バイト整数 ("int4") の配列を定義するには、
ELEMENT = int4
と指定して下さい。 詳細については、後述の配列型で説明します。
この型による配列の外部形式における値間の区切りを示すために、delimiter で特定の文字を設定することができます。デフォルトの区切り文字はカンマ(',')です。 この区切り文字は、配列要素の型に関係するものであり、配列型自体に関係するものでないことに注意して下さい。
ユーザがそのデータ型の列のデフォルトを NULL 以外の何かにしたい場合、デフォルト値を指定することができます。そのデフォルト値を DEFAULT キーワードで指定して下さい。 (この方法で指定されたデフォルト値は、特定の列に付与された、明示的な DEFAULT 句によって上書きされる可能性があります。)
オプションのフラグ PASSEDBYVALUE は、このデータ型の値は参照ではなく値によって渡されることを示します。 (ほとんどのマシンでは 4 バイト、まれに 8 バイトとなる) Datum よりも長い内部表現の型は値によって渡すことができないことに注意して下さい。
alignment キーワードは、そのデータ型に必要とされる格納位置配置を指定します。指定可能な値は、1バイト、2バイト、4バイト、8バイト境界の位置合わせと同等のことを意味します。 可変長型の位置配置は最低でも 4 を持たなければならないことに注意して下さい。 最初の要素として int4 を持たなければならないからです。
キーワード storage を 使用することで、可変長データ型を格納する際の戦略を選択することがで きます。 (固定長の型には plain のみが許されています)。 plain はデータ型に対して TOAST を使えなくします。データは常に一列で格納され、圧縮されません。 extended は TOAST の全ての機能を有効にします。システムはまず長いデータ値を圧縮しようとし、それでもまだ長過ぎる場合は値をメインテーブルの行から削除します。 external はメインテーブルから値を削除することを許しますが、システムはデータを圧縮しようとしません。 main はデータの圧縮を許しますが、値をメインテーブルから削除することを止めます。 (この格納メソッドを持つデータアイテムは、他に行を適合させる方法がない場合にはメインテーブルから削除されてしまうかもしれませんが、extended やexternal が指定されているアイテムよりも優先してメインテーブルに残されます。)
2 つ目の CREATE TYPE の形式を使用すると、複合型を作成できます。 複合型は、列名およびデータ型のリストにより指定されます。 これは、本質的にはテーブルの行型と同じです。しかし、CREATE TYPE を使用すると、データ型を定義するだけであれば実際のテーブルを作成する必要がありません。 スタンドアロンの複合型は、関数の戻り値の型として使用すると有用です。
ユーザ定義の基本データ型が作成されると、PostgreSQL は、自動的に、その名前として基本型名の前にアンダースコアを付けた、関連する配列型を作成します。パーサはこの命名規則を理解し、foo[] 型の列への要求を _foo 型への要求に変換します。 この暗黙的に作成される配列型は可変長で、組み込み入出力関数 array_in と array_out を使用します。
理論的に考えると、「システムが自動的に配列型を正しく作成するのであれば、ELEMENT オプションはどうして存在するのだろう」と不思議に思うでしょう。ELEMENT が意味を持つ、唯一の場合があります。 それは、内部的に N 個の同一のものの配列となり、その N 個に対し、要素番号を指定して直接アクセスでき、さらに、その型全体として、何らかの操作を用意することを予定する、固定長の型を作成する時です。例えば、name 型は、その要素である chars 型のものにこのようなアクセス方法を許可しています。2次元の point 型では、その 2 つの浮動小数点の構成要素に point[0] および point[1] というアクセスを行なうことができます。 この機能は、その内部形式が正確に N 個の同一の固定長フィールドの並びである、固定長の型でのみ動作することに注意してください。要素番号指定が可能な可変長型は、array_in と array_out を使用して、汎化された内部表現を持つ必要があります。 歴史的な理由 (つまり、明らかに間違いなのですが、変更するには遅すぎたため) により、固定長配列型への要素番号指定は 0 から始まり、可変長配列の場合は 1 から始まります。
ユーザ定義型の名前はアンダースコア (「_」) から始めることはできません。また、62 文字 (もしくは一般化した表現で NAMEDATALEN-2) 長までです。 (他の名前の場合は NAMEDATALEN-1 文字長まで許されます。) アンダースコアから始まる型名は、内部的に作成される配列型の名前のために予約されています。
以下の例では、box データ型を作成し、その型をテーブル定義の中で使用しています。
CREATE TYPE box (INTERNALLENGTH = 16, INPUT = my_procedure_1, OUTPUT = my_procedure_2); CREATE TABLE myboxes (id INT4, description box);
box 型の内部構造が float4 型が 4 つ並んだ配列の場合、以下のように書き換えることもできます。
CREATE TYPE box (INTERNALLENGTH = 16, INPUT = my_procedure_1, OUTPUT = my_procedure_2, ELEMENT = float4);
このように記述すると、box 値の浮動小数点要素に要素番号でアクセスできます。 その他は、1 つ目の例と同様の動作をします。
以下の例では、ラージオブジェクト型を作成し、テーブル定義にてそれを使用しています。
CREATE TYPE bigobj (INPUT = lo_filein, OUTPUT = lo_fileout, INTERNALLENGTH = VARIABLE); CREATE TABLE big_objs (id int4, obj bigobj);
また、以下の例では、複合型を作成し、テーブル関数定義にてそれを使用しています。
CREATE TYPE compfoo AS (f1 int, f2 text); CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS 'SELECT fooid, fooname FROM foo' LANGUAGE SQL;