27

テーブルの2つのフィールドに一意の制約を作成しようとしています。ただし、nullになる可能性が高くなります。両方がnullでない場合(nullnameになることはありません)にのみ、それらが一意である必要があります。

create unique index "name_and_email" on user(name, email);

テーブル名とフィールド名のセマンティクスを無視し、それが理にかなっているかどうかを無視します。

namenullではない2つの値に一意性を強制するが、nullではなくnullであるエントリが複数ある場合は無視する、これらのフィールドに一意の制約を作成する方法はありemailますか?

この質問はSQLServerに関するものであり、答えが同じではないことを期待してい ます。nullも許可する一意の制約を作成するにはどうすればよいですか。

4

2 に答える 2

37

これは、関数ベースのインデックスを使用して行うことができます。以下NVL2()では、ご存知のように、式がnullでない場合は1つの値を返し、nullの場合は別の値を返します。代わりに使用できますCASE()

SQL> create table blah (name varchar2(10), email varchar2(20))
  2  /

Table created.

SQL> create unique index blah_uidx on blah
  2      (nvl2(email, name, null), nvl2(name, email, null))
  3  /

Index created.

SQL> insert into blah values ('APC', null)
  2  /

1 row created.

SQL> insert into blah values ('APC', null)
  2  /

1 row created.

SQL> insert into blah values (null, 'apc@example.com')
  2  /

1 row created.

SQL> insert into blah values (null, 'apc@example.com')
  2  /

1 row created.

SQL> insert into blah values ('APC', 'apc@example.com')
  2  /

1 row created.

SQL> insert into blah values ('APC', 'apc@example.com')
  2  /
insert into blah values ('APC', 'apc@example.com')
*
ERROR at line 1:
ORA-00001: unique constraint (APC.BLAH_UIDX) violated


SQL>

編集

シナリオでは常に名前が入力されるため、必要なインデックスは次のようになります。

SQL> create unique index blah_uidx on blah
  2      (nvl2(email, name, null), email)
  3  /

Index created.

SQL> 
于 2009-09-03T17:21:56.320 に答える
2

まだこの回答に誘導される人の数はわかりませんが、少なくとも最新バージョンのoracleでは、一意のインデックスにnullを含む複数の行を含めることができ、受け入れられた回答は必要ありません。

于 2018-11-01T19:15:50.503 に答える