Programmingバックエンドデベロッパー

SQLにおける複雑なビジネスキーの例を用いたデータのユニーク性を確認し保証するための効果的なメカニズムをどのように実装しますか?特にNULL値が許可されている場合です。

Hintsage AIアシスタントで面接を突破

回答。

リレーショナルデータベースでは、ユニーク性の確保はしばしばUNIQUE制約に依存しています。しかし、ビジネスの実務には、NULL値を含むフィールドの組み合わせに対してユニーク性が求められる状況があります(たとえば、emailと電話のユニークな組み合わせ。ただし、電話は不明である可能性があります)。

問題の歴史: SQLの標準的なUNIQUE制約は、列の1つがNULLである場合にはユニーク性を保証しません。仕様では、これらの値は相互に排除されるとされています。

問題: NULL値を含む複雑なキーのため、標準的な制約は重複を引き起こすことがあります。これは、データの整合性が必要である場合(インポート、マイグレーション、大規模な更新時)には特に深刻です。

解決策: すべての値(NULLを含む)を考慮する計算列を使用し、その列にユニーク性を制約するか、トリガーロジックを使用します。

コードの例:

ALTER TABLE my_table ADD computed_uniqueness AS ( ISNULL(email, '') + '#' + ISNULL(phone, '') ); CREATE UNIQUE INDEX idx_my_table_computed_uniqueness ON my_table(computed_uniqueness);

または(NULLが異なるものとして扱われるインデックス式をサポートしているPostgreSQL用):

CREATE UNIQUE INDEX idx_unique_email_phone ON my_table ((COALESCE(email, '##')),(COALESCE(phone, '##')));

主な特徴:

  • NULLを含む組み合わせのユニーク性ルールの明示的な管理。
  • DBレベルでの自動化とサポートの可能性。
  • 複雑で変更可能なスキーマのサポート。

ヒントのある質問。

部分的にNULLが許可される列に対して通常のUNIQUEインデックスを使用してユニーク性を保証できますか?

いいえ。ANSI SQLに従うと、UNIQUEインデックスは、組み合わせの中にNULLを含む場合には、複数の行を許可します。なぜなら、NULLは他のいかなる値とも等しくなく、NULLを含むことがあるからです。

式に対するユニークインデックスと、ユニーク性をチェックするためのBEFORE INSERTトリガーの使用の違いは何ですか?

ユニークインデックスはサポートが簡単で、動作が速いですが、複雑なビジネスルール(例:例外やカスタムの組み合わせ)を実装できるとは限りません。トリガーは柔軟ですが、遅く、メンテナンスが難しくなります。

例:

CREATE OR REPLACE FUNCTION check_custom_unique() RETURNS TRIGGER AS $$ BEGIN IF EXISTS ( SELECT 1 FROM my_table WHERE COALESCE(NEW.email, '##') = COALESCE(email, '##') AND COALESCE(NEW.phone, '##') = COALESCE(phone, '##') ) THEN RAISE EXCEPTION 'Duplicate found'; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trg_custom_unique BEFORE INSERT OR UPDATE ON my_table FOR EACH ROW EXECUTE FUNCTION check_custom_unique();

ユニーク性の問題をアプリケーションレベルで解決するためにSELECTでDISTINCTを使用できますか?

できますが、選択のみに対してであり、データの変更時に重複を防ぐものではなく、テーブルレベルでの制約の代わりにもなりません。

よくある誤りとアンチパターン

  • NULLを含む組み合わせがキーである場合にUNIQUE制約を使用しようとすること。
  • アプリケーションレベルでのユニーク性を確認するのみ(DBを回避して)。
  • 明示的なインデックスなしでのトリガーの過度な複雑性 — パフォーマンスの損失。

実例

ネガティブケース

企業がUNIQUE(email, phone)を介してemailと電話のユニーク性を実装します。電話がNULLの場合、データベースにemailの重複が現れます。

利点:

  • 実装の簡易さ。

欠点:

  • 整合性の喪失、重複。
  • 分析において追跡が困難な暗黙のエラー。

ポジティブケース

計算列(COALESCE(email, '##') + '#' + COALESCE(phone, ''))を使用し、それにユニークインデックスを設定します。

利点:

  • データベースは重複を排除し、任意の操作(UPDATE、INSERT)が即座に処理されます。

欠点:

  • 大量のデータの場合、再インデックス化に時間がかかることがあります。
  • インデックスのサイズに影響を与えます。