CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name ( { column_name data_type [ DEFAULT default_expr ] [ column_constraint [ ... ] ] | table_constraint | LIKE parent_table [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] ) [ INHERITS ( parent_table [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACE tablespace ] ここで、column_constraintは以下の通りです。 [ CONSTRAINT constraint_name ] { NOT NULL | NULL | UNIQUE [ USING INDEX TABLESPACE tablespace ] | PRIMARY KEY [ USING INDEX TABLESPACE tablespace ] | CHECK (expression) | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] また、table_constraintは以下の通りです。 [ CONSTRAINT constraint_name ] { UNIQUE ( column_name [, ... ] ) [ USING INDEX TABLESPACE tablespace ] | PRIMARY KEY ( column_name [, ... ] ) [ USING INDEX TABLESPACE tablespace ] | CHECK ( expression ) | FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
CREATE TABLEは新しい、空のテーブルを現在のデータベースに作成します。 テーブルはこのコマンドを実行したユーザによって所有されます。
スキーマ名が付けられている場合 (例えば、CREATE TABLE myschema.mytable ...)、テーブルは指定されたスキーマで作成されます。 スキーマ名がなければ、テーブルは現在のスキーマで作成されます。 また、一時テーブルは特別なスキーマに存在するため、一時テーブルの作成時にスキーマ名を与えることはできません。 テーブル名は、同じスキーマ内の他のテーブル、シーケンス、インデックス、もしくはビューとは異なる名前にする必要があります。
CREATE TABLEはまた自動的に、そのテーブルの1行に対応する複合型を表す、データ型を作成します。 従って、テーブルは、同じスキーマ内の既存のデータ型と同じ名前を持つことができません。
省略可能な制約句は、新しい、または、更新された行がその挿入、更新操作を成功させるために満たさなければならない制約(試験項目)を指定します。 制約は、テーブル内で有効な値集合の定義を各種方法で補助するSQLオブジェクトです。
制約の定義にはテーブル制約と列制約という2つの方法があります。 列制約は列定義の一部として定義されます。 テーブル制約定義は特定の列には拘束されず、複数の列を含有することができます。 また、各列制約はテーブル制約として記述することができます。 列制約は、その制約が1つの列にのみ影響する場合の使用についての簡便な記述方法にすぎません。
指定された場合、テーブルは一時テーブルとして作成されます。 一時テーブルは、そのセッションの終わり、場合によっては、現在のトランザクションの終わり(後述のON COMMITを参照)に自動的に削除されます。 一時テーブルが存在する場合、同じ名前を持つ既存の永続テーブルはスキーマ修飾された名前で参照されていなければ、現在のセッションでは非可視です。 一時テーブルで作られるインデックスも全て自動的に一時的のものになります。
GLOBALまたはLOCALをTEMPORARYやTEMPの前に記述することができます(省略可能)。 PostgreSQLでは、これらに違いはありません。 互換性を参照してください。
作成するテーブルの名前です(スキーマ修飾名でも可)。
新しいテーブルで作成される列の名前です。
列のデータ型です。 これには、配列指定子が含まれる場合があります。 PostgreSQLでサポートされるデータ型の情報に関する詳細は第8章を参照してください。
DEFAULT句は、それを記載した列定義の列にデフォルトデータ値を割り当てます。 その値は任意の無変数式です(副問い合わせと現在のテーブル内の他の列へ交差参照は許可されません)。 デフォルト式のデータ型はその列のデータ型と一致する必要があります。
デフォルト式は、その列に値が指定されない、全ての挿入操作において使用されます。 列にデフォルトがない場合、デフォルト値はNULLになります。
省略可能なINHERITS句は、新しいテーブルがその列を全て継承するテーブルの一覧を指定します。
INHERITSを使用して、新しい子テーブルとその親テーブル(複数可)との永続的な関連を作成します。 通常、親へのスキーマ修飾子は子にも同様に伝播され、デフォルトでは、親テーブルの走査結果には子テーブルのデータが含まれます。
複数の親テーブルに同一名の列が存在する場合、そのデータ型も一致していなければ、エラーとして報告されます。 競合がなければ、重複した列は新しいテーブルで1つの列の形に融合されます。 新しいテーブルの列名の一覧に継承された列の名前が含まれる場合、同様にそのデータ型は継承した列のデータ型に一致しなければならず、その列定義は1つに融合されます。 しかし、継承された新しい、同一名称の列宣言に、同一の制約を指定する必要はありません。 任意の宣言で提供される制約は全て、まとめてマージされ、全てが新しいテーブルに適用されます。 新しいテーブルが明示的にその列にデフォルト値を指定していた場合、その列の継承された宣言における全てのデフォルト値は上書きされます。 さもなくば、その列にデフォルト値を指定した親テーブルは全て、同じデフォルト値を持たなければなりません。 この他の場合はエラーになります。
LIKE句は、新しいテーブルが自動的に全ての列名、そのデータ型、および、非NULL制約をコピーするテーブルを指定します。
INHERITSとの違いは、作成した後、新しいテーブルと元のテーブルとの完全に分離されることです。 元のテーブルへの変更は新しいテーブルには適用されませんし、新しいテーブルのデータは元のテーブルを走査しても見つかりません。
コピーされる列用のデフォルト式は、INCLUDING DEFAULTSが指定された場合にのみ含まれます。 デフォルトでは、デフォルト式は含まれず、その結果、新しいテーブルの全ての列はNULLというデフォルトを持つことになります。
この省略可能な句は、新しいテーブルの行にOID(オブジェクト識別子)を割り当てるかどうかを指定します。 WITH OIDSかWITHOUT OIDSのどちらも指定されていない場合、デフォルト値はdefault_with_oids設定パラメータに依存します。 (OIDを持つテーブルを継承する新しいテーブルでは、WITHOUT OIDSを指定したとしても強制的にWITH OIDSとなります。)
WITHOUT OIDSが指定されて場合や暗示された場合、新しいテーブルはOIDを格納せず、また、挿入される行にはOIDが割り当てられません。 これは、OIDの消費を抑え、32ビットのOIDカウンタの回転周期を延長することができますので、価値がある可能性があります。 カウンタが一周すると、OIDの一意性を仮定することができなくなり、その有用性を減少させることになります。 また、OIDをなくすことで、テーブル1行当たり(ほとんどのマシンで)4バイト分そのテーブルをディスクに格納するための容量を軽減でき、多少性能が向上します。
テーブルの作成後にOIDを削除するには、ALTER TABLEを使用してください。
省略可能な列制約、テーブル制約の名前です。 指定されなければ、システムが名前を生成します。
列はNULL値を持つことができません。
列はNULL値を持つことができます。 これがデフォルトです。
この句は非標準的なSQLデータベースとの互換性のためだけに提供されています。 新しいアプリケーションでこれを使用しないでください。
UNIQUE制約は、テーブルの1つ以上の列のグループは一意な値のみを持つことができることを指定します。 一意性テーブル制約の動作は列制約と同様ですが、更に複数列に跨る機能を持ちます。
一意性制約の目的のために、NULL値は等しいとはみなされなせん。
各一意性テーブル制約は、そのテーブルで定義された他の一意性制約もしくはプライマリキー制約によって名付けられた列の集合とは異なるように列の集合を指名しなければなりません。 (さもなくば、同じ制約が2回あらわれるだけになります。)
プライマリキー制約は、テーブルの1列または複数列が一意な(重複が無い)、非NULL値のみを持つことを指定します。 技術的には、PRIMARY KEYは単なるUNIQUEとNOT NULLの組み合わせですが、プライマリキーは、他のテーブルが一意な行の識別子としてこの列集合に依存することができることを意味しますので、プライマリキーとして列の集合を識別することは、スキーマ設計に関するメタデータも提供します。
1つのテーブルには列制約もしくはテーブル制約として1つのプライマリキーのみを指定することができます。
プライマリキー制約は、そのテーブルに定義された他の全ての一意性制約で指名された列の集合とは異なるように、列の集合を指名しなければなりません。
CHECK句は、新しい、または、変更された行が挿入や更新操作が成功するために満たさなければならない、Boolean型の結果を生成する式を指定します。 式の評価がTRUEもしくはUNKNOWNとなれば成功します。 行の挿入、更新操作の結果、式がFALSEとなる場合は、エラー例外が生成され、挿入や更新によるデータベースの変更は行なわれません。 列制約として指定された検査制約は、その列の値のみを参照しなければなりません。 一方、テーブル制約として現れる式は、複数列を参照することができます。
現在、CHECK式には、副問い合わせや現在の行内の列以外の値を含むことはできません。
これらの句は、外部キー制約を指定します。 これは、新しいテーブルの1つ以上の列のグループが被参照テーブルの一部の行の被参照列(複数可)内の値に一致する値のみを持たなければならないことを指定するものです。 refcolumnが省略された場合、reftableのプライマリキーが使用されます。 被参照列は被参照テーブルにおいて、一意性もしくはプライマリキー制約をもった列でなければなりません。
参照列に挿入された値は、被参照テーブルと被参照列の値に指定された照合型で照会されます。 3種類の照合型があります。 MATCH FULL、MATCH PARTIAL、デフォルトでもあるMATCH SIMPLE照合型です。 MATCH FULLは全ての外部キー列がNULLとなる場合を除き、複数列外部キーのある列がNULLとなることを許可しません。 MATCH SIMPLE照合型は、外部キーの他の部分がNULLでない限り、外部キーの一部をNULLとなることを許可します。 MATCH PARTIALはまだ実装されていません。
更に、被参照列のデータが変更された場合、このテーブルの列のデータに何らかの動作が行なわれます。 ON DELETE句は被参照テーブルの被参照行が削除された場合の動作を指定します。 同様にON UPDATE句は被参照テーブルの被参照列が新しい値に更新された場合に行なわれる動作を指定します。 被参照列に実際に変更がないように行が更新された場合は、動作は行なわれません。 制約が遅延可能と宣言されていたとしても、NO ACTION検査以外の参照動作は遅延させられません。 各句について、以下の動作を指定可能です。
削除もしくは更新が外部キー制約違反となることを示すエラーを発生します。 制約が遅延可能な場合、何らかの参照行が存在する限り、このエラーは制約の検査時点で発生します これはデフォルトの動作です。
削除もしくは更新が外部キー制約違反となることを示すエラーを発生します。 この検査が遅延できない点を除き、NO ACTIONと同じです。
削除された行を参照する行を全て削除、もしくは、被参照列の新しい値に、参照する列の値を更新します。
参照する列(複数可)をNULLに設定します。
参照する列(複数可)をそのデフォルト値に設定します。
被参照列が頻繁に更新される場合、外部キー列にインデックスを付け、外部キー列に関連した参照動作がより効率的に実行できるようにする方がいいでしょう。
これは制約を遅延させることが可能かどうかを制御します。 遅延不可の制約は各コマンドの後すぐに検査されます。 遅延可能な制約の検査は(SET CONSTRAINTSコマンドを使用して)トランザクションの終了時まで遅延させることができます。 NOT DEFERRABLEがデフォルトです。 現在、外部キー制約のみがこの句を受け付けることができます。 他の種類の全ての制約は遅延させられません。
制約が遅延可能な場合、この句は制約検査を行なうデフォルトの時期を指定します。 制約がINITIALLY IMMEDIATEの場合、各文の実行後に検査されます。 これがデフォルトです。 制約がINITIALLY DEFERREDの場合、トランザクションの終了時にのみ検査されます。 制約検査の時期はSET CONSTRAINTSコマンドを使用して変更することができます。
ON COMMITを使用して、トランザクションブロックの終了時点での一時テーブルの動作を制御することができます。 以下の3つのオプションがあります。
トランザクションの終了時点での特別な動作は行われません。 これがデフォルトの動作です。
一時テーブル内の全ての行は、各トランザクションブロックの終わりで削除されます。 基本的には、コミットの度に自動的にTRUNCATEが実行されます。
現在のトランザクションブロックの終了時点で、一時テーブルは削除されます。
tablespaceは、新しいテーブルが作成されるテーブル空間名です。 指定されていない場合、default_tablespaceが使用されます。 もしdefault_tablespaceが空文字列であれば、データベースのデフォルトのテーブル空間が使用されます。
この句により、UNIQUEまたはPRIMARY KEY制約に関連したインデックスを作成するテーブル空間を選択することができます。 指定されていない場合、default_tablespaceが使用されます。 もしdefault_tablespaceが空文字列であればデータベースのデフォルトのテーブル空間が使用されます。
新規のアプリケーションではOIDを使用することを勧めません。 できる限り、テーブルのプライマリキーとしてSERIALや他の連番生成器を使用することが好まれます。 しかし、アプリケーションがテーブルの特定の行を識別するためにOIDの使用を行う場合は、そのテーブルのoid列に一意性制約を作成することを推奨します。 これによりカウンタが一周してしまった場合でもテーブル内のOIDで一意に行を識別できることが保証されるからです。 データベース全体の一意な識別子が必要となる場合、OIDがテーブル全体で一意であると仮定することは止めてください。 この場合はtableoidと行のOIDの組み合わせを使用してください。
ティップ: WITHOUT OIDSの使用は、プライマリキーの無いテーブルでは推奨できません。 OIDも一意なデータキーも存在しませんので、特定行の識別を行なうことが難しくなるからです。
PostgreSQLは自動的に各一意性制約とプライマリキー制約に対してインデックスを作成し、その一意性を確実なものにします。 従って、プライマリキーの列に明示的なインデックスを作成することは必要ありません。 (より詳細についてはCREATE INDEXを参照してください。)
現在の実装では、一意性制約とプライマリキーは継承されません。 これは継承と一意性制約の組み合わせはその機能に障害が起こるからです。
テーブルは1600列以上の列を持つことはできません。 (実際は、タプル長の制限により実際の制限はもっと低くなります。)
filmsテーブルとdistributorsテーブルを作成します。
CREATE TABLE films ( code char(5) CONSTRAINT firstkey PRIMARY KEY, title varchar(40) NOT NULL, did integer NOT NULL, date_prod date, kind varchar(10), len interval hour to minute );
CREATE TABLE distributors ( did integer PRIMARY KEY DEFAULT nextval('serial'), name varchar(40) NOT NULL CHECK (name <> '') );
2次元配列をもつテーブルを作成します。
CREATE TABLE array_int ( vector int[][] );
filmsテーブルに 一意性テーブル制約を定義します。 一意性テーブル制約はテーブルの1つ以上の列に定義することができます。
CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT production UNIQUE(date_prod) );
検査列制約を定義します。
CREATE TABLE distributors ( did integer CHECK (did > 100), name varchar(40) );
検査テーブル制約を定義します。
CREATE TABLE distributors ( did integer, name varchar(40) CONSTRAINT con1 CHECK (did > 100 AND name <> '') );
filmsテーブルにプライマリキーテーブル制約を定義します。 プライマリキーテーブル制約はテーブルの1つ以上の列に定義することができます。
CREATE TABLE films ( code char(5), title varchar(40), did integer, date_prod date, kind varchar(10), len interval hour to minute, CONSTRAINT code_title PRIMARY KEY(code,title) );
distributorsテーブルにプライマリキー制約を定義します。 以下の2つの例は同じものです。 前者はテーブル制約構文を使用し、後者は列制約構文を使用します。
CREATE TABLE distributors ( did integer, name varchar(40), PRIMARY KEY(did) );
CREATE TABLE distributors ( did integer PRIMARY KEY, name varchar(40) );
以下は、name列のデフォルト値にリテラル定数を割り当て、did列のデフォルト値をシーケンスオブジェクトの次の値を選択して生成されるように調整しています。 そしてmodtimeのデフォルト値は、その行が挿入された時刻となります。
CREATE TABLE distributors ( name varchar(40) DEFAULT 'Luso Films', did integer DEFAULT nextval('distributors_serial'), modtime timestamp DEFAULT current_timestamp );
2つのNOT NULL列制約をdistributorsテーブルに定義します。 そのうち1つは明示的な名前を付けています。
CREATE TABLE distributors ( did integer CONSTRAINT no_null NOT NULL, name varchar(40) NOT NULL );
name列に対し、一意性制約を定義します。
CREATE TABLE distributors ( did integer, name varchar(40) UNIQUE );
上のコマンドはテーブル制約として指定した以下のコマンドと等価です。
CREATE TABLE distributors ( did integer, name varchar(40), UNIQUE(name) );
diskvol1テーブル空間にcinemasテーブルを作成します。
CREATE TABLE cinemas ( id serial, name text, location text ) TABLESPACE diskvol1;
CREATE TABLEは、以下の一覧を除いて、SQL-92に準拠し、SQL:1999のサブセットとなります。
CREATE TEMPORARY TABLEは標準SQLに類似していますが、その効果は同じではありません。 標準では、一時テーブルは一度のみ定義され、それを必要とするセッション毎に自動的に(空の内容で始まる形で)存在します。 PostgreSQLでは、これと異なり、各セッションで独自に、使用する一時テーブル用のCREATE TEMPORARY TABLEコマンドを発行しなければなりません。 これにより、異なるセッションで同じ名前の一時テーブルを異なる目的で使用することができます。 一方、標準の方法では指定された一時テーブルの名前のインスタンスが全て同一のテーブル構造を持つという束縛があります。
標準における一時テーブルのこの動作定義は大抵無視されています。 この点でのPostgreSQLの動作は、他の多くのSQLデータベースと似ています。
標準における、グローバル一時テーブルとローカル一時テーブルの区別はPostgreSQLにはありません。 この区別はモジュール概念に依存したもので、PostgreSQLにはモジュール概念がないからです。 互換性という目的のため、PostgreSQLは一時テーブルの宣言においてGLOBALとLOCALキーワードを受け付けますが、これらは効果がありません。
一時テーブル用のON COMMIT句もまた、標準SQLに類似していますが、数点の違いがあります。 ON COMMIT句が省略された場合、SQLでは、デフォルトの動作はON COMMIT DELETE ROWSであると規定しています。 しかし、PostgreSQLでのデフォルトの動作はON COMMIT PRESERVE ROWSです。 ON COMMIT DROPはSQLにはありません。
標準SQLでは、CHECK列制約はそれを適用する列のみを参照でき、CHECKテーブル制約のみが複数の列を参照できると言及しています。 PostgreSQLではこの制限を強制していません。 列検査制約とテーブル検査制約を同様のものとして扱っています。
NULL"制約"(実際は非制約です)は標準SQLに対するPostgreSQLの拡張で、他のいくつかのデータベースシステムとの互換性のために含まれています(そしてNOT NULL制約と対称になっています)。 どの列でもこれがデフォルトですので、この存在は邪魔なだけです。
INHERITS句による複数継承はPostgreSQLの言語拡張です。 SQL:1999(SQL-92 ではありませんが)は異なった構文と異なった意味論を使った単一継承を定義しています。 SQL:1999方式の継承はまだPostgreSQLではサポートされていません。