# 発番列仕様

    [ GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
    [ ( START WITH 定整数
    [ ,INCREMENT BY 定整数] ) ]  ]  ]

#### 識別子列属性

SMALLINT、INT、BIGINT型の列に識別子属性があると、Derbyは自動的に列の値に、増加する整数値をあてます。挿入文で列の値が指定されない場合、識別子列属性は既定値と同様に振る舞い、Derbyは列に自動的に値を与えます。 しかしながら、その値は定数ではありません。Derbyは行に挿入する時、自動的に既定値へ加算してゆきます。

IDENTITYというキーワードは列のデータ型が次のいずれの整数である場合にのみ指定可能です。

- SMALLINT
- INT
- BIGINT

Derbyには二種類の識別子列があります。ひとつはGENERATED ALWAYSで、もう一つはGENERATED BY DEFAULTです。

GENERATED ALWAYS
  GENERATED ALWAYSの識別子列は列の既定値を、挿入が行われるときごとに増加させて、その増加された値を列に記録します。他の既定値とは違い、GENERATED ALWAYSの識別子列に値を直接挿入したり、その値を変更したりすることはできません。その代わりに識別子列の値にはDEFAULTというキーワードを与えるか、識別子列を挿入する列の一覧からはずすかします。 例を挙げます。

      create table greetings
      	(i int generated always as identity, ch char(50));
      insert into greetings values (DEFAULT, 'hello');
      insert into greetings(ch) values ('bonjour');

  GENERATED ALWAYSな識別子列に自動的に発番された値は一意です。また識別子列を作成しても、列に索引は作られません。
GENERATED BY DEFAULT

  GENERATED BY DEFAULTの識別子列は、挿入時に列へ明示的な値が与えられなかった場合のみ、既定値を増加させて使います。GENERATED ALWAYSの列とは違い、挿入文にて明示的な値を既定値の変わりに与えることができます。

  生成された既定値を使うためには、挿入時にDEFAULTというキーワードを使うか、識別子列を挿入列リストから外します。挿入する値を指定するには、その値を挿入文に含めます。例を挙げます。

      create table greetings
      	(i int generated by default as identity, ch char(50));
      -- "1"を指定する:
      insert into greetings values (1, 'hi');
      -- 生成された既定値を使う
      insert into greetings values (DEFAULT, 'salut');
      -- 生成された既定値を使う
      insert into greetings(ch) values ('bonjour');

  GENERATED ALWAYS列とは異なり、GENERATED BY DEFAULTの列では一意性は保障されません。したがって、上記の例では`hi`および`salut`の行はどちらも同じ"1"という識別値を取ります。なぜなら、生成された列の値は"1"から始まり、ユーザが指定した値も"1"だったからです。重複を避けるために、情報のロードやインポートを行うときにテーブルを作成して、システムが自動生成するためのSTART WITHの値を与えてください。このような状況をチェックして、起きないようにするために、主キーや一意性制約をGENERATED BY DEFAULTの識別子列に使うことができます。

既定では識別子列の初期値は1です。さらに増分値は1です。 列を定義するとき、初期値と増分値の両方に、START WITHとINCREMENT BYというキーワードを使って、明示的な値を指定することができます。さらに増分値に負の値を与えると、挿入毎にDerbyは値を減じてゆきます。 もし値が正の値であれば、挿入毎にDerbyは値を増加させてゆきます。 値に0を与えると例外が発生します。

識別子列にて可能な最大値と最小値は、列のデータ型によります。データ型で採ることのできる範囲外の値を挿入しようとすると、例外が発生します。

Table 1. 発番列仕様にて、列でとることが可能な最大値と最小値
データ型 | 最大値 | 最小値
--- | --- | ---
SMALLINT | 32767 (java.lang.Short.MAX_VALUE) | -32768 (java.lang.Short.MIN_VALUE)
INT | 2147483647 (java.lang.Integer.MAX_VALUE) | -2147483648 (java.lang.Integer.MIN_VALUE)
BIGINT | 9223372036854775807 (java.lang.Long.MAX_VALUE) | -9223372036854775808 (java.lang.Long.MIN_VALUE)

識別子列にて自動的に生成された値は一意です。主キー制約や一意性制約を列に定義することで、一意性を保障する事ができます。識別子列を定義しても、列の索引は作られません 。

`IDENTITY_VAL_LOCAL`関数は、非決定性の関数で最後に識別子列に与えられた値を返します。詳細については、IDENTITY_VAL_LOCAL関数を参照してください。

Note: スキーマ・表・列の名前はデリミトされた識別子を使わない限り、常にシステム表にて大文字で記録されます。

Derbyは列に対して最後に発番された値をキャッシュに残しています。また、ディスク上では、SYS.SYSCOLUMNSというシステム表のAUTOINCREMENTVALUEという列に、次の値を記録しています。 トランザクションをロールバックしてもこの値は取り消されません。したがって、トランザクションがロールバックされると、識別子列に挿入される自動生成値には、空きが発生することとなります。 Derby はこのように動作することで、SYS.SYSCOLUMNSの行をトランザクションの期間中ロックし続けることを回避して、高い平行性を保っています。

トリガされたSQL文にて識別子列に値が挿入された場合、そのSQL文で挿入された値は、トリガのコード内でのみConnectionInfoから取得可能です。 また、トリガのコードはトリガをひいた文が挿入した値を取得することもできます。 しかし、トリガをひいた文は、トリガされたSQL文が識別子列に挿入した値を知ることができません。 さらにトリガは入れ子(再帰)の場合も同じようなこととなります。 SQL文によりT1というトリガが発火され、次にT1の実行したSQLによりT2というトリガが発火されたとします。ここでT1もT2も表に識別子列に値がある行を挿入した場合、T1はT2が挿入した値を見ることはできませんが、T2はT1が挿入した値を見ることができます。それぞれの入れ子になったトリガは自分自身と、再帰的なトリガを開始したSQLを含めて、入れ子のレベルが前の処理にて生成された値を見ることができます。 なおトリガの再帰は16まで可能です。

#### 例

    create table greetings
      (i int generated by default as identity (START WITH 2, INCREMENT BY 1),
      ch char(50));
    -- 1を指定する。
    insert into greetings values (1, 'hi');
    -- 生成された既定値を使う
    insert into greetings values (DEFAULT, 'salut');
    -- 生成された既定値を使う
    insert into greetings(ch) values ('bonjour');

Parent topic: CREATE TABLE 文
Related reference
列定義