私はマイクロソフトの施設の近くに住み、働いています。そのため、現在の従業員の多くは、SQLServerのバックグラウンドを持つ元Microsoftの従業員です。 SQL Serverでは、IDENTITY列を持つテーブルを作成できます。 Oracle 12cでは、同じことができるようになりました。これは、SQLServerからOracleに移行する人に役立つはずです。また、企業はSQLServerまたはIDENTITY列を許可するその他のデータベースからOracleにアプリケーションをより簡単に移植できます。
まず、IDENTITY列を含むテーブルを作成し、データの行をいくつか入力します。
SQL> create table test_tab ( 2 id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY, 3 val VARCHAR2(20)); Table created. SQL> insert into test_tab (val) values ('my first row'); 1 row created. SQL> insert into test_tab (val) values ('my second row'); 1 row created. SQL> commit; Commit complete.
ID列に値を挿入しなかったことに注意してください。次に、テーブルにクエリを実行しましょう。
SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row
ご覧のとおり、私のID値は予想どおりに追加されています。テーブルの作成では、このIDENTITY列を次のように定義しました:GENERATED BY DEFAULT ON NULL
BY DEFAULT句は、INSERTステートメントで次の値を省略すると、Oracleがシーケンス内の次の値を自動的に割り当てることを意味します。これを含めると、Oracleは指定された値を使用します。これを考慮してください:
SQL> insert into test_tab values (4,'specified ID=4'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4
ご覧のとおり、ID =4と明示的に述べたため、Oracleはその値を渡しました。次の値(3にする必要があります)を挿入しようとするとどうなりますか?
SQL> insert into test_tab (val) values ('my row after ID=4'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4 3 my row after ID=4上記は期待通りに機能しました。次に使用可能なID値が使用されました。ただし、次の挿入では「4」または「5」を使用しますか?
SQL> insert into test_tab (val) values ('my fifth row'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4 3 my row after ID=4 4 my fifth rowええとああ!重複する値が許可されました。 「アイデンティティ」値の概念を適用するために主キー制約が作成されることを期待していましたが、それは起こりません。どのような制約がありますか?
SQL> select constraint_name,constraint_type,table_name,search_condition from user_constraints; CONSTRAINT_NAME C TABLE_NAME ------------------------------ - ------------------------------ SEARCH_CONDITION -------------------------------------------------------------------------------- SYS_C004978 C TEST_TAB "ID" IS NOT NULLしたがって、唯一の制約はNOTNULLチェック制約です。次に、最後の行を削除してPK制約を追加しましょう。
SQL> delete from test_tab where val='my fifth row'; 1 row deleted. SQL> commit; Commit complete. SQL> alter table test_tab add constraint test_tab_pk primary key (id); Table altered.ここで、テストするデータがあることを確認します。
SQL> insert into test_tab (val) values ('after pk constraint'); 1 row created. SQL> insert into test_tab (id,val) values (6,'explicitly set id=6'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4 3 my row after ID=4 5 after pk constraint 6 explicitly set id=6 6 rows selected.そこで、ID=6を明示的に追加しました。これがID=4を明示的に追加したときのように、次の挿入ではID =6を使用しようとし、PK制約が設定されていると、例外がスローされます。
SQL> insert into test_tab (val) values ('after ID=6'); insert into test_tab (val) values ('after ID=6') * ERROR at line 1: ORA-00001: unique constraint (PEASLAND.TEST_TAB_PK) violatedしたがって、この話の教訓は、ON DEFAULTを使用する場合、ID値の衝突を処理する準備をすることです。デフォルトは、ONDEFAULTではなくALWAYSです。 ALWAYSでは、Oracleは常にシーケンス番号ジェネレータを使用します。 id値を指定しようとすると、例外が発生します。
SQL> create table test_tab2(id number generated always as identity, val varchar2(20)); Table created. SQL> insert into test_tab2(id,val) values (1,'first row'); insert into test_tab2(id,val) values (1,'first row') * ERROR at line 1: ORA-32795: cannot insert into a generated always identity columnビュー*_TAB_COLUMNSは、テーブル内のどの列がIDENTITY列であるかを示します。
SQL> select column_name,identity_column from user_tab_columns where table_name='TEST_TAB'; COLUMN_NAME IDE --------------- --- ID YES VAL NOテーブルでIDENTITY列を使用する場合は、テストを慎重に行って、アプリケーションで正しく機能することを理解していることを確認してください。 PKまたはUNIQUE制約が自動的に含まれず、重複する値を追加できることに驚きました。