web-dev-qa-db-ja.com

空の文字列への外部キーNULLと外部キー

医薬品カタログの表です。医薬品のブランドを持っているものもあれば、ジェネリックなものもある(つまり、ブランド情報を決して持たない)。

_CREATE TABLE medicine (
   id serial PRIMARY KEY,
   name text NOT NULL,
   brand_id integer
   CONSTRAINT brand_fk FOREIGN KEY (brand_id) REFERENCES brand (id)       
);

CREATE TABLE brand (
  id serial PRIMARY KEY,
  name text NOT NULL
);
_

ジェネリック医薬品の保管用。 abcxyz、2つのオプションがあります:

  1. 外部キーにNULLを使用する_brand_id_

    INSERT INTO medicine (name, brand_id) VALUES ('abc', NULL)
    INSERT INTO medicine (name, brand_id) VALUES ('xyz', NULL)

  2. ブランド名に空の文字列を1つだけ挿入し、それをすべてのジェネリック医薬品のbrand_idに使用します

    INSERT INTO brand (id, name) VALUES (1, '')
    INSERT INTO medicine (name, brand_id) VALUES ('abc', 1)
    INSERT INTO medicine (name, brand_id) VALUES ('xyz', 1)

StackExchangeで読んだことから、_1_がこれを行う一般的な方法のようです。ただし、医薬品名とブランドIDに一意のインデックスが必要な場合は、 部分インデックス を使用する必要があります(つまり、2つのインデックスそれぞれに_brand_id IS NULL_&_brand_id is NOT NULL_)。

2番目の方法を使用すると、単一のインデックスでそれを実現できます。

これらのアプローチのいずれかの他の利点/欠点はありますか? 2番目の方法は型破りだと思いますが、途中で後で発見する問題があるかもしれません。

PS私は自分のクエリを説明するために薬の例を使用しましたが、ソリューションの技術的メリットを純粋にデータベースの観点から理解したいのです。どのアプローチが医学の例に適しているかについての議論に。

4
user4150760

答えはあなたの曖昧さquestionにあります:

ただし、医学に関する一意のインデックスが必要な場合はnamebrand_id ...

「一意のインデックス」は実際には必要ありません。特定のルールを適用したい。一意のインデックスは終わりを意味する;です。 a tool。質問は:あなたは正確に何をしていますかwant

ブランドが不明なnameのインスタンスが1つだけ存在できるようにしますか?または、複数のインスタンスが存在する可能性がありますか?それは、「不明」、「欠落」、「空」、またはNULLがあなたにとって何を意味するかによって異なります。

NULLの標準的な意味は「不明」です。 nothingを含むanything(空の('')は文字列型、0は次のようになります。数値型)。

oneジェネリックブランドを許可する場合は、brandにエントリを含め、「ジェネリック」または「 [〜#〜] acme [〜#〜 ] "など。このようなキャッチオールエントリには、id値0を使用したいと思います。

次に、一意のインデックスまたは制約が想定されていることを実行します。テーブルmedicine(brand_id, name)のインスタンスを1つだけ許可します。ただし、(brand_id, NULL)を使用した複数のエントリは引き続き可能です。必要ない場合は、brand_id NOT NULLを設定します。

最良の解決策は、一般的なクエリと設定の詳細にも依存します。必ず正確に文書化してくださいNULL /空/ 0の意味と、そのように設計した理由。実装した時点では非常に明確に見えるかもしれませんが、後で混乱するかもしれません。

あなたが参照した答えに別のリンクを追加しました:

6