ある有限集合S
の値を持つ列がある場合、たとえばpersons
テーブルのS = { alive, dead, unknown }
列のlife_state
の場合、参照テーブルを追加するのはいつ有益ですか?
オプション:
重複した静的データをlife_state
列に保存する
単純な文字列:SELECT DISTINCT
に一部の値がない可能性があるため、可能なデータ値を取得するには、アプリケーション層レベルのコードが存在する必要があります。
ENUM
:life_state
のすべての可能なデータ値を取得する場合は、SHOW COLUMN..
からINFORMATION_SCHEMA
を実行してすべての可能なデータを取得する必要があります値を設定し、そのデータをアプリケーション層レベルで解析するか、アプリケーション層レベルでコードが重複しています。新しいlife_state値を追加する必要がある場合は、テーブルをALTER
し、変更中のプロセスでテーブル全体をロックする必要があります。必要に応じて、life_state
値ごとに追加のデータを保存することはできません。
Normalized参照テーブルlife_states
と、persons
テーブルに戻るリンクテーブルを作成します。可能な値は、3行を返すSELECT name from life_states;
から導出できます。 persons
インスタンスのlife_state
を取得するには、追加の結合が必要になりました。これは遅いだけでなく、アプリケーション層レベルでより長いクエリ/より多くのコードを必要とします。予期されていませんが、必要に応じて追加の値を簡単に追加できます。さらに、life_stateタイプに他のデータを追加する必要がある場合は、簡単に追加できます。
その他の考慮事項:
関連する議論:
この回答は、MySQLに適用されるENUM
型の使用に主に焦点を当てています。これは、MySQLが使用されているように見えるためです。
あなたはあなた自身の投稿の下部で強調したスレッドを介してあなた自身の質問に答えました-それはすべて説明されています ここ すなわちENUM
sは悪:-)!
データベース内のデータはテーブルに保存する必要があります-データベースの管理に関するデータはシステムテーブル(データディクショナリ)に保存する必要があります。 ENUM
の内容を知りたい場合は、システムテーブルをクエリする必要があります。
私のアドバイスは、2つ以上の値を持つすべてのものにテーブルを使用することです。それでも、この問題を取り巻く性別についての議論を見てください。
あなたが指摘したスレッドで示されているように、VIEW
sを使用して頻繁に使用する参照テーブルのいくつかを事前に結合することにより、結合から手間のかかる作業の一部を取り除くことができます。さらに、参照テーブルには詳細な説明を含めることができます。これらの契約プログラマーは、あいまいなコードの意味について何も覚えておく必要はありません。
基本的に、データベースでENUM
を使用する理由がわかりません。プログラミングしてからしばらく経ちましたので、言語で使用することの長所と短所についてはあまり詳しくありません。 !!
重複データを参照テーブルに移動することが有益なのはいつですか?
参照データが参照データとは独立して存在する場合。この例では、問題のドメインで、persons
に行がない場合でも可能なライフ状態が何であるかを知ることが役立ちます。
値が既知の有限集合からのみ描画できる場合。これはしばしば「参照データ」と呼ばれます。外部キー制約はこれを強制できます。
2つ(またはそれ以上)の正規化されたエンティティ間で参照整合性を維持する必要がある場合。これは、値が事前にわからないトランザクションデータ用です。たとえば、アプリケーションが実行時に新しいユーザーの追加を許可し、各テーブルにlast_updated_userid
がある場合です。この場合も、外部キーがこれを強制します。
Life_stateのみに依存する追加のドメイン値が検出された場合。これは通常のキー依存関係の正規化です。
メタデータが必要な場合(例:システムから値を完全に削除するのではなく、「ソフト削除」の場合はis_active
。
参照テーブルの代理キーを作成するのが通例ですが、必須ではありません。与えられた例では、参照テーブルは3行の単一の7文字の列を持つことができます。人間が読める値は、参照テーブルに表示されます。これにより、参照されるテーブルに結合する必要がなくなります。
ここでの問題は、主に「不明」と「不明であることがわかっている」をどのように区別するかです。誰かがdeath_date
を持っていた場合、
IS NOT NULL
が確実に彼らが死んでいることを知ることができたとき、あなたは実際にwhen彼らが死んだことを知るでしょう。 (これまでの死は日付に起因する可能性があると仮定して)
ただし、IS NULL
の場合、データは2つの方法のいずれかで解釈できます。
それらは意味的に非常に異なります。 これらの若者 死んでいることはわかりませんが、safe彼らが生きていることを伝えることもできません。特に、このデータを使用してリソースを割り当て、それらを見つける場合。
たとえば、ここには多くの虚偽表示があります
ENUM
は標準機能ではなく、一般的な拡張機能です。 PostgreSQLでは、
ENUM
は重複したデータです。」:実際にはそうではないか、そうであるべきではありません。 ENUM
は、ユーザーテーブルへのリンクと同じ方法で、システムテーブル(カタログ)へのリンクを介して実装でき、ユーザーに対して完全に透過的にすることができます。たとえばPostgreSQLでは、ENUMは4バイト(intのサイズ)です。最良の場合のリンクのコストは別のバイトになるため、リンクすると3バイトしか節約できません。SHOW COLUMN
で潜在的な値を取得する」:これも常に必要なわけではありません。可能な enum
とSELECT
の値を取得するのは非常に自然です。あいまいなSHOW
構文は必要ありません。ENUM
を使用する複数のテーブルは、タイプとは関係ありません。タイプitselfは ALTER TYPE
で変更できます。それは即座に値を追加し、それはタイプを使用するすべてのテーブルで有効になります。