PostgreSQL 8.0.0 文書
前のページ | 巻戻し |  | 早送り | 次のページ

# CREATE TABLE

## 名前

CREATE TABLE -- 新しいテーブルの定義

## 概要

    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つの列にのみ影響する場合の使用についての簡便な記述方法にすぎません。

## パラメータ

`TEMPORARY` or `TEMP`

  指定された場合、テーブルは一時テーブルとして作成されます。 一時テーブルは、そのセッションの終わり、場合によっては、現在のトランザクションの終わり(後述の`ON COMMIT`を参照)に自動的に削除されます。 一時テーブルが存在する場合、同じ名前を持つ既存の永続テーブルはスキーマ修飾された名前で参照されていなければ、現在のセッションでは非可視です。 一時テーブルで作られるインデックスも全て自動的に一時的のものになります。

  `GLOBAL`または`LOCAL`を`TEMPORARY`や`TEMP`の前に記述することができます(省略可能)。 PostgreSQLでは、これらに違いはありません。 互換性を参照してください。

`table_name`

  作成するテーブルの名前です(スキーマ修飾名でも可)。

`column_name`

  新しいテーブルで作成される列の名前です。

`data_type`

  列のデータ型です。 これには、配列指定子が含まれる場合があります。 PostgreSQLでサポートされるデータ型の情報に関する詳細は第8章を参照してください。

`DEFAULT `default_expr``

  `DEFAULT`句は、それを記載した列定義の列にデフォルトデータ値を割り当てます。 その値は任意の無変数式です(副問い合わせと現在のテーブル内の他の列へ交差参照は許可されません)。 デフォルト式のデータ型はその列のデータ型と一致する必要があります。

  デフォルト式は、その列に値が指定されない、全ての挿入操作において使用されます。 列にデフォルトがない場合、デフォルト値はNULLになります。

`INHERITS ( `parent_table` [, ... ] )`

  省略可能な`INHERITS`句は、新しいテーブルがその列を全て継承するテーブルの一覧を指定します。

  `INHERITS`を使用して、新しい子テーブルとその親テーブル(複数可)との永続的な関連を作成します。 通常、親へのスキーマ修飾子は子にも同様に伝播され、デフォルトでは、親テーブルの走査結果には子テーブルのデータが含まれます。

  複数の親テーブルに同一名の列が存在する場合、そのデータ型も一致していなければ、エラーとして報告されます。 競合がなければ、重複した列は新しいテーブルで1つの列の形に融合されます。 新しいテーブルの列名の一覧に継承された列の名前が含まれる場合、同様にそのデータ型は継承した列のデータ型に一致しなければならず、その列定義は1つに融合されます。 しかし、継承された新しい、同一名称の列宣言に、同一の制約を指定する必要はありません。 任意の宣言で提供される制約は全て、まとめてマージされ、全てが新しいテーブルに適用されます。 新しいテーブルが明示的にその列にデフォルト値を指定していた場合、その列の継承された宣言における全てのデフォルト値は上書きされます。 さもなくば、その列にデフォルト値を指定した親テーブルは全て、同じデフォルト値を持たなければなりません。 この他の場合はエラーになります。

`LIKE `parent_table` [ { INCLUDING | EXCLUDING } DEFAULTS ]`

  `LIKE`句は、新しいテーブルが自動的に全ての列名、そのデータ型、および、非NULL制約をコピーするテーブルを指定します。

  `INHERITS`との違いは、作成した後、新しいテーブルと元のテーブルとの完全に分離されることです。 元のテーブルへの変更は新しいテーブルには適用されませんし、新しいテーブルのデータは元のテーブルを走査しても見つかりません。

  コピーされる列用のデフォルト式は、`INCLUDING DEFAULTS`が指定された場合にのみ含まれます。 デフォルトでは、デフォルト式は含まれず、その結果、新しいテーブルの全ての列はNULLというデフォルトを持つことになります。

`WITH OIDS`
`WITHOUT OIDS`

  この省略可能な句は、新しいテーブルの行に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を使用してください。

`CONSTRAINT `constraint_name``

  省略可能な列制約、テーブル制約の名前です。 指定されなければ、システムが名前を生成します。

`NOT NULL`

  列はNULL値を持つことができません。

`NULL`

  列はNULL値を持つことができます。 これがデフォルトです。

  この句は非標準的なSQLデータベースとの互換性のためだけに提供されています。 新しいアプリケーションでこれを使用しないでください。

`UNIQUE` (column constraint)
`UNIQUE ( `column_name` [, ... ] )` (table constraint)

  `UNIQUE`制約は、テーブルの1つ以上の列のグループは一意な値のみを持つことができることを指定します。 一意性テーブル制約の動作は列制約と同様ですが、更に複数列に跨る機能を持ちます。

  一意性制約の目的のために、NULL値は等しいとはみなされなせん。

  各一意性テーブル制約は、そのテーブルで定義された他の一意性制約もしくはプライマリキー制約によって名付けられた列の集合とは異なるように列の集合を指名しなければなりません。 (さもなくば、同じ制約が2回あらわれるだけになります。)

`PRIMARY KEY` (column constraint)
`PRIMARY KEY ( `column_name` [, ... ] )` (table constraint)

  プライマリキー制約は、テーブルの1列または複数列が一意な(重複が無い)、非NULL値のみを持つことを指定します。 技術的には、`PRIMARY KEY`は単なる`UNIQUE`と`NOT NULL`の組み合わせですが、プライマリキーは、他のテーブルが一意な行の識別子としてこの列集合に依存することができることを意味しますので、プライマリキーとして列の集合を識別することは、スキーマ設計に関するメタデータも提供します。

  1つのテーブルには列制約もしくはテーブル制約として1つのプライマリキーのみを指定することができます。

  プライマリキー制約は、そのテーブルに定義された他の全ての一意性制約で指名された列の集合とは異なるように、列の集合を指名しなければなりません。

`CHECK (`expression`)`

  `CHECK`句は、新しい、または、変更された行が挿入や更新操作が成功するために満たさなければならない、Boolean型の結果を生成する式を指定します。 式の評価がTRUEもしくはUNKNOWNとなれば成功します。 行の挿入、更新操作の結果、式がFALSEとなる場合は、エラー例外が生成され、挿入や更新によるデータベースの変更は行なわれません。 列制約として指定された検査制約は、その列の値のみを参照しなければなりません。 一方、テーブル制約として現れる式は、複数列を参照することができます。

  現在、`CHECK`式には、副問い合わせや現在の行内の列以外の値を含むことはできません。

`REFERENCES `reftable` [ ( `refcolumn` ) ] [ MATCH `matchtype` ] [ ON DELETE `action` ] [ ON UPDATE `action` ]` (column constraint)
`FOREIGN KEY ( `column` [, ... ] ) REFERENCES `reftable` [ ( `refcolumn` [, ... ] ) ] [ MATCH `matchtype` ] [ ON DELETE `action` ] [ ON UPDATE `action` ]` (table constraint)

  これらの句は、外部キー制約を指定します。 これは、新しいテーブルの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`

    削除もしくは更新が外部キー制約違反となることを示すエラーを発生します。 制約が遅延可能な場合、何らかの参照行が存在する限り、このエラーは制約の検査時点で発生します これはデフォルトの動作です。

  `RESTRICT`

    削除もしくは更新が外部キー制約違反となることを示すエラーを発生します。 この検査が遅延できない点を除き、`NO ACTION`と同じです。

  `CASCADE`

    削除された行を参照する行を全て削除、もしくは、被参照列の新しい値に、参照する列の値を更新します。

  `SET NULL`

    参照する列(複数可)をNULLに設定します。

  `SET DEFAULT`

    参照する列(複数可)をそのデフォルト値に設定します。

  被参照列が頻繁に更新される場合、外部キー列にインデックスを付け、外部キー列に関連した参照動作がより効率的に実行できるようにする方がいいでしょう。

`DEFERRABLE`
`NOT DEFERRABLE`

  これは制約を遅延させることが可能かどうかを制御します。 遅延不可の制約は各コマンドの後すぐに検査されます。 遅延可能な制約の検査は(SET CONSTRAINTSコマンドを使用して)トランザクションの終了時まで遅延させることができます。 `NOT DEFERRABLE`がデフォルトです。 現在、外部キー制約のみがこの句を受け付けることができます。 他の種類の全ての制約は遅延させられません。

`INITIALLY IMMEDIATE`
`INITIALLY DEFERRED`

  制約が遅延可能な場合、この句は制約検査を行なうデフォルトの時期を指定します。 制約が`INITIALLY IMMEDIATE`の場合、各文の実行後に検査されます。 これがデフォルトです。 制約が`INITIALLY DEFERRED`の場合、トランザクションの終了時にのみ検査されます。 制約検査の時期はSET CONSTRAINTSコマンドを使用して変更することができます。

`ON COMMIT`

  `ON COMMIT`を使用して、トランザクションブロックの終了時点での一時テーブルの動作を制御することができます。 以下の3つのオプションがあります。

  `PRESERVE ROWS`

    トランザクションの終了時点での特別な動作は行われません。 これがデフォルトの動作です。

  `DELETE ROWS`

    一時テーブル内の全ての行は、各トランザクションブロックの終わりで削除されます。 基本的には、コミットの度に自動的にTRUNCATEが実行されます。

  `DROP`

    現在のトランザクションブロックの終了時点で、一時テーブルは削除されます。

`TABLESPACE `tablespace``

  `tablespace`は、新しいテーブルが作成されるテーブル空間名です。 指定されていない場合、default_tablespaceが使用されます。 もし`default_tablespace`が空文字列であれば、データベースのデフォルトのテーブル空間が使用されます。

`USING INDEX TABLESPACE `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` "制約"

`NULL`"制約"(実際は非制約です)は標準SQLに対するPostgreSQLの拡張で、他のいくつかのデータベースシステムとの互換性のために含まれています(そして`NOT NULL`制約と対称になっています)。 どの列でもこれがデフォルトですので、この存在は邪魔なだけです。

### 継承

`INHERITS`句による複数継承はPostgreSQLの言語拡張です。 SQL:1999(SQL-92 ではありませんが)は異なった構文と異なった意味論を使った単一継承を定義しています。 SQL:1999方式の継承はまだPostgreSQLではサポートされていません。

### オブジェクト ID

PostgreSQLのOIDという概念は標準にはありません。

### 無列のテーブル

PostgreSQLでは、列を持たないテーブルを作成することができます。 (例えば、`CREATE TABLE foo();`) これは標準SQLからの拡張です。 標準SQLでは列を持たないテーブルは許されません。 列を持たないテーブルはそれ自体は役に立ちませんが、これを無効とすると、`ALTER TABLE DROP COLUMN`に奇妙で特殊な状態を生成してしまいます。 ですので、この仕様上の制限を無視する方が簡潔であると考えます。

### テーブル空間

PostgreSQLのテーブル空間の概念は標準には全くありません。 従って、`TABLESPACE`と`USING INDEX TABLESPACE`は拡張です。

## 関連項目

ALTER TABLE, DROP TABLE, CREATE TABLESPACE

前のページ | ホーム | 次のページ
CREATE SEQUENCE | 上に戻る | CREATE TABLE AS