ユニークインデックスを作成して
create unique index scott.emp_ename_idx on scott.emp (ename);
確認して、
set pagesize 10000 set linesize 130 col table_name for a10 col index_name for a20 col column_name for a10 col column_position for 9999 select index_name, table_name, column_name, column_position from user_ind_columns where table_name = 'EMP' order by index_name, column_position; INDEX_NAME TABLE_NAME COLUMN_NAM COLUMN_POSITION -------------------- ---------- ---------- --------------- EMP_ENAME_IDX EMP ENAME 1 PK_EMP EMP EMPNO 1
表にはこんなデータが入っているので、
select empno,ename from emp; EMPNO ENAME ---------- ---------- 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER 15 NEO
ename が重複するよう insert してみると、
insert into emp(empno, ename) values(16, 'NEO'); * ERROR at line 1: ORA-00001: unique constraint (SCOTT.EMP_ENAME_IDX) violated
先ほどユニークインデックスを作ったので、一意制約違反になる。
ところで、プライマリキーと NOT NULL 制約をつけたユニークインデックスって何が違うんだろうって思ったんだけど、
プライマリキーとユニークキーの違い
プライマリキーとユニークキーの違いは確実に 識別する(identification) ための主たる制約と NULL 以外の行が 一意であること(uniqueness) を保証する目的のためのその他の制約という違いがある。
さらに原則的にキーの値を変更を許可するかしないかという面もある。 人間にとっては意味論的に異なるものであるが Oracle データベースにしてみれば、その内部の仕組みに大きな差はない。例としては、ある顧客を会員番号を主キーとして管理している場合に (本籍)住所、氏名、生年月日のカラムの組み合わせが一意キーとして考えられる。
整合性制約 - オラクル・Oracleをマスターするための基本と仕組み
通常、この組み合わせのキーは一意である*1が変更可能であることに大きな違いがある。そして、これらの組み合わせを使ったテーブルのリレーションは好ましいものではない。
一方、主キー(会員番号)は退会処理などを特別な処理しない限りは変更されることはない。不可能ではないが原則、変更不可能という位置づけである。
プライマリキーはキー値の変更を許可しないってことか。
たしか、DB2ってプライマリキーってなかった気がする。テーブル定義書でプライマリキーになっているところはDDLを見ると、ユニークインデックス + NOT NULL 制約になっていたような。
追記(2009/09/04):
IBM の sin さん(Unofficial DB2 BLOG)にツッコミを頂きました。
>DB2にも明確にプライマリーキー(PK)という機能はありますよ。
Oracle でユニークインデックスを作ってみる - ablog
失礼しました。
主キー制約は、主キーを構成する列または列の組み合わせに含まれるすべての値がユニーク(固有)であることを保証します。主キーは、表内の特定の行を識別するために使われます。主キーは1つの表に1つしか設定できませんが、ユニーク・キーは複数設定できます。主キー制約はユニーク制約の特別な場合で、1次索引を使って強制されます。
IBM Developer 日本語版 : 大変申し訳ありません。このページは無効です。
ほんとうですね。
違いは、
- 「主キーは1つの表に1つしか設定できません」
- 「1次索引を使って強制されます」
の2点みたい。1次索引ってなんだろ?
>OracleにしてもDB2にしてもPKが変更不可ってことは無いんじゃないでしょうか。
Oracle でユニークインデックスを作ってみる - ablog
これは試してみたら、sim さんのおっしゃる通りだった。
SQL> set pagesize 10000 set linesize 130 col table_name for a10 col index_name for a20 col column_name for a10 col column_position for 9999 select index_name, table_name, column_name, column_position from user_ind_columns where table_name = 'EMP' order by index_name, column_position; SQL> SQL> SQL> SQL> SQL> SQL> 2 3 4 INDEX_NAME TABLE_NAME COLUMN_NAM COLUMN_POSITION -------------------- ---------- ---------- --------------- PK_EMP EMP EMPNO 1 SQL> select empno, ename from emp; EMPNO ENAME ---------- ---------- 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER 15 NEO 15 rows selected. SQL> update emp set empno = 16 where empno = 15; 1 row updated. SQL> commit; Commit complete. SQL> select empno, ename from emp; EMPNO ENAME ---------- ---------- 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER 16 NEO 15 rows selected.