web-dev-qa-db-ja.com

単一のテーブルで複数の一意制約を使用すると、設計が悪いと見なされますか?

私はPostgreSQLのINSERT INTO .. ON CONFLICT (..) DO UPDATE ..構文を見ていましたが、これを使用して複数の一意制約チェックを実行することはできません。つまり、複合一意インデックスを列名ON CONFLICT (Name, Symbol)(これらの2つの列に一意インデックスが定義されている場合)で参照するか、主キーを使用します。列に2つの個別の一意のインデックスを定義する場合、チェックできるのは1つだけです。

CREATE TABLE student
    (Id int primary key, Name varchar(50), Symbol varchar(50),
      CONSTRAINT col1_unique UNIQUE (Name),
      CONSTRAINT col2_unique UNIQUE (Symbol)
    ); 

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (1, 'John', 'J'),
    (2, 'David', 'D'),
    (3, 'Will', 'W');

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (4, 'Jeremy', 'J')
   on conflict(Name) DO UPDATE
   set Name = 'Jeremy';

Jは重複していると言ってエラーをスローする可能性があります。ただし、この例はシンボルが別のテーブルにあり、1対多の関係で生徒のテーブルに接続されている必要があるため、単に悪いデザインです。 これが、PostgreSQLのon conflictは、このように設計されています。これは、常に一意のインデックスが1つしかない方法でテーブルを再構築できるためです。それは本当ですか、それとも別の理由がありますか?

フィドルの例: http://www.sqlfiddle.com/#!17/9c0ce

8
appl3r

常に6番目、つまりドメインキーの正規形があります。ここでは、各非キー列が独自のテーブルになります。したがって、3NFテーブルT(Key、Col1、Col2、..)はT1(Key、Col1)、T2(Key、Col2)などになります。一意性を必要とする新しいテーブルでは、それを宣言できます。

ただし、テーブルに複数の一意の制約を設定しても問題ありません。国の表を例にとってみましょう。これには、たとえば、ID、名前、ISOコード、首都などが含まれます。最初の4つはそれぞれ固有です。さらに、私たちのシステムがそれぞれが一意であることを信頼したい場合、私は信じていますすべきそれぞれに一意の制約を定義します。これにより、すべての消費者が信頼できるデータに関する真実が強制されます。

8
Michael Green