チェックボックスのセット(いずれかまたはすべてを選択可能)を持つ Web フォームを想像してください。私は、データベース テーブルの 1 つの列に格納される値をコンマで区切ったリストに保存することを選択しました。
今では、正しい解決策は 2 番目のテーブルを作成し、データベースを適切に正規化することであることがわかっています。簡単な解決策を実装する方が早く、そのアプリケーションの概念実証をすぐに、あまり時間をかけずに行いたいと考えていました。
私の状況では、時間の節約とコードの簡素化は価値があると思いましたが、これは妥当な設計上の選択でしょうか、それとも最初から標準化すべきだったのでしょうか?
もう少し詳しく説明すると、これは基本的に共有フォルダに保存された Excel ファイルを置き換える小さな内部アプリケーションです。また、プログラムを整理してメンテナンスしやすくしたいと考えているので、質問しています。完全に満足していない点がいくつかあり、そのうちの 1 つがこの質問のトピックです。
ベストアンサー1
違反に加えて第一正規形カンマ区切りリストでは、単一の列に値の繰り返しグループが格納されるため、他にも多くの実用的な問題があります。
- 各値が正しいデータ型であることを保証できません。1、2、3 、バナナ、5を防ぐ方法はありません。
- 外部キー制約を使用して値を参照テーブルにリンクすることはできません。参照整合性を強制する方法はありません。
- 一意性を強制できない: 1、2、3、3、3、5を防ぐ方法がない
- リスト全体を取得せずにリストから値を削除することはできません。
- 文字列列に収まるよりも長いリストを保存することはできません。
- リスト内の特定の値を持つすべてのエンティティを検索するのは困難です。非効率的なテーブルスキャンを使用する必要があります。たとえば、MySQL では正規表現を使用する必要がある場合があります。
idlist REGEXP '[[:<:]]2[[:>:]]'
または、MySQL 8.0 では正規表現を使用する必要がある場合があります。idlist REGEXP '\\b2\\b'
- リスト内の要素を数えたり、その他の集計クエリを実行したりするのが困難です。
- 参照するルックアップ テーブルに値を結合するのは困難です。
- ソートされた順序でリストを取得するのは困難です。
- 値に表示されないことが保証された区切り文字を選択するのは難しい
これらの問題を解決するには、大量のアプリケーション コードを記述し、RDBMS が既に提供している機能をはるかに効率的に再発明する必要があります。
カンマ区切りのリストは十分に間違っているので、これを私の本の最初の章にしました。SQL アンチパターン、第 1 巻: データベース プログラミングの落とし穴を回避する。
非正規化を採用する必要がある場合もありますが、@OMG ポニーの言及ただし、これらは例外的なケースです。非リレーショナルな「最適化」は、データの他の用途を犠牲にして 1 つのタイプのクエリにメリットをもたらすため、どのクエリを特別に処理して非正規化する必要があるかを必ず把握してください。