内部キーを自動生成すべくOracleの自動採番機能を試します。11gまでのバージョンでは事前にシーケンスを作成しておいて、insertのタイミングでnextvalしていく方法がオーソドックスでしたが、先日あるトランザクションテーブルを新設する際に実装してみました。create tableで自動採番の定義をするわけですが内部的にはcreate tableのタイミングでシーケンスが作成されてこれがinsertの都度nextvalされていく仕組みです。基本的にはこれまで手動でやっていた方法と変わらないみたいですが、内部的に作成されたシーケンスに対してalter sequenceを発行する事はできないのでalter tableで変更する事となります。
またこの自動採番機能を適用したテーブルに対してinsert allは実質使えなくなる点も注意が必要ですね。こちらご参考にどうぞ。
create table で GENERATED ALWAYS/BY DEFAULT を定義します
IDENTITY列の文 | 説明 |
GENERATED ALWAYS AS IDENTITY | 常にシーケンス・ジェネレータによってIDENTITY値が指定されます。列の値は指定できません。 |
GENERATED BY DEFAULT AS IDENTITY | 列値を指定しないときは常に、シーケンス・ジェネレータによってIDENTITY値が指定されます。 |
GENERATED BY DEFAULT ON NULL AS IDENTITY | NULLの列値を指定すると、シーケンス・ジェネレータによって次のIDENTITY値が指定されます。 |
この表はOracleサイトから引用しています。
https://docs.oracle.com/cd/F37626_01/java-driver-table/creating-tables-identity-column.html
CREATE TABLE EX01 ( SID NUMBER(18,0) --GENERATED ALWAYS AS IDENTITY GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 100 ORDER NOCYCLE NOT NULL ,SNAME VARCHAR2(32 CHAR) ,BIRTHDAY DATE ,NOTE VARCHAR2(256 CHAR) ,PRIMARY KEY (SID) ) ;
DBA_TAB_IDENTITY_COLSでカラム名と対応するシーケンスの関係を確認できます
IDENTITYで定義したカラムとシーケンスの関係はDBA_TAB_IDENTITY_COLSで確認できます。また、sequenceに関する情報を変更するにはalter sequenceではなく、alter tableでの変更になります。
select * from DBA_TAB_IDENTITY_COLS ;
SQL> select t.COLUMN_NAME,t.SEQUENCE_NAME from DBA_TAB_IDENTITY_COLS t
2 where t.OWNER='SOONI' and t.TABLE_NAME='EX01'
3 ;
COLUMN_NAME SEQUENCE_NAME
______________ ________________
SID ISEQ$$_100050
SQL> select s.MIN_VALUE,s.MAX_VALUE,s.INCREMENT_BY,s.LAST_NUMBER,s.CACHE_SIZE,s.ORDER_FLAG,s.CYCLE_FLAG
2 from dba_sequences s where s.SEQUENCE_NAME='ISEQ$$_100050'
3 ;
MIN_VALUE MAX_VALUE INCREMENT_BY LAST_NUMBER CACHE_SIZE ORDER_FLAG CYCLE_FLAG
____________ _____________________ _______________ ______________ _____________ _____________ _____________
1 999999999999999999 1 1 100 Y N
SQL>
SQL> alter SEQUENCE ISEQ$$_100050 cache 40
2 ;
次のコマンドの開始中にエラーが発生しました : 行 1 -
alter SEQUENCE ISEQ$$_100050 cache 40
エラー・レポート -
ORA-32793: システム生成の順序は変更できません
32793.0000 - "cannot alter a system-generated sequence"
*Cause: An attempt was made to alter a system-generated sequence.
*Action: A system-generated sequence, such as one created for an
identity column, cannot be altered.
SQL> alter table ex01 MODIFY ( SID GENERATED BY DEFAULT AS IDENTITY CACHE 40 )
2 ;
Table EX01が変更されました。
SQL> select s.MIN_VALUE,s.MAX_VALUE,s.INCREMENT_BY,s.LAST_NUMBER,s.CACHE_SIZE,s.ORDER_FLAG,s.CYCLE_FLAG
2 from dba_sequences s where s.SEQUENCE_NAME='ISEQ$$_100050';
MIN_VALUE MAX_VALUE INCREMENT_BY LAST_NUMBER CACHE_SIZE ORDER_FLAG CYCLE_FLAG
____________ _____________________ _______________ ______________ _____________ _____________ _____________
1 999999999999999999 1 1 40 Y N
SQL>
DBA_SEQUENCESと結合するとシーケンス情報を確認できます
select t.OWNER,t.TABLE_NAME,t.SEQUENCE_NAME,s.CACHE_SIZE,s.LAST_NUMBER from DBA_TAB_IDENTITY_COLS t inner join DBA_SEQUENCES s on t.OWNER = s.SEQUENCE_OWNER and t.SEQUENCE_NAME= s.SEQUENCE_NAME where t.TABLE_NAME ='EX01' and t.OWNER='SOONI' ;
GENERATED ALWAYS の場合、「カラム値」を指定したINSERTはできない。
ALTER TABLE SOONI.EX01 MODIFY (SID GENERATED ALWAYS AS IDENTITY (START WITH 1000000000)) ;
GENERATED BY DEFAULT の場合、「カラム値」を指定したINSERTが可能
ALTER TABLE SOONI.EX01 MODIFY (SID GENERATED BY DEFAULT AS IDENTITY (START WITH 1000000000)) ;
SQL> select t.OWNER,t.TABLE_NAME,t.GENERATION_TYPE
2 from DBA_TAB_IDENTITY_COLS t
3 where t.OWNER='SOONI' and t.TABLE_NAME='EX01'
4 ;
OWNER TABLE_NAME GENERATION_TYPE
________ _____________ __________________
SOONI EX01 ALWAYS
SQL>
SQL> insert into EX01
2 (sid,SNAME, BIRTHDAY, NOTE)
3 values(10,'西川','2001/01/08','一番の長身')
4 ;
次のコマンド行の開始中にエラーが発生しました : 1 -
insert into EX01
(sid,SNAME, BIRTHDAY, NOTE)
values(10,'西川','2001/01/08','一番の長身')
コマンド行 : 2 列 : 2 でのエラー
エラー・レポート -
SQLエラー: ORA-32795: GENERATED ALWAYSで作成されたアイデンティティ列には挿入できません
32795.0000 - "cannot insert into a generated always identity column"
*Cause: An attempt was made to insert a value into an identity column
created with GENERATED ALWAYS keywords.
*Action: A generated always identity column cannot be directly inserted.
Instead, the associated sequence generator must provide the value.
SQL> alter table ex01 MODIFY (SID GENERATED BY DEFAULT AS IDENTITY)
2 ;
Table EX01が変更されました。
SQL> insert into EX01
2 (sid,SNAME, BIRTHDAY, NOTE)
3 values(10,'西川','2001/01/08','一番の長身')
4 ;
1行挿入しました。
SQL>
自動採番カラムの追加
以下DDLでカラムの追加と、既存レコードが存在する場合自動採番した値を入れてくれます。
ALTER TABLE SOONI.EX01 add (SID NUMBER(18,0) GENERATED BY DEFAULT AS IDENTITY (START WITH 1000000000)) ;
シーケンスキャッシュ値を変更する例
割り当たっているシーケンスのシーケンスキャッシュ値を変更する場合以下のようになります。
ALTER TABLE SOONI.EX01 modify (SID GENERATED BY DEFAULT AS IDENTITY (CACHE 300)) ;