[ GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( START WITH 定整数 [ ,INCREMENT BY 定整数] ) ] ] ]
SMALLINT、INT、BIGINT型の列に識別子属性があると、Derbyは自動的に列の値に、増加する整数値をあてます。挿入文で列の値が指定されない場合、識別子列属性は既定値と同様に振る舞い、Derbyは列に自動的に値を与えます。 しかしながら、その値は定数ではありません。Derbyは行に挿入する時、自動的に既定値へ加算してゆきます。
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 ALWAYSの列とは違い、挿入文にて明示的な値を既定値の変わりに与えることができます。
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を与えると例外が発生します。
データ型 | 最大値 | 最小値 |
---|---|---|
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関数を参照してください。
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');