16

エンティティ関係図を SQL DDL ステートメントに解釈する方法を学んでいますが、表記の違いに戸惑っています。次の図のように素の関係を考えてみましょう。

これは次のように表されますか。

  1. Vehicle、2WD、および 4WD テーブル (2WD および 4WD は Vehicle の PK を指します)。また
  2. 2WD と 4WD のテーブルのみ (および Vehicle テーブルはありません)、どちらも Vehicle が持っていたであろう属性を複製しますか?

これらは関係を書く他の方法だと思います:

各ダイアグラムで最終的にどのテーブルになるかについて、違いの明確な説明を探しています。

4

4 に答える 4

29

ER表記

いくつかのER表記があります。私はあなたが使用しているものに精通していませんが、サブタイプ(別名、継承、カテゴリ、サブクラス、一般化階層など)を表現しようとしていることは明らかです。これは、OOP継承の関係のいとこです。

サブタイピングを行うときは、通常、次の設計上の決定に関心があります。

  • 抽象的対象と具体的対象:親をインスタンス化できますか?あなたの例では:またはでなくてもVehicle存在できますか?12WD4WD
  • 包括的vs.排他的:同じ親に対して複数の子をインスタンス化できますか?あなたの例では、Vehicleの両方 2WDにすることができます4WDか?2
  • 完全vs.不完全:将来、さらに多くの子供が追加されると思いますか?あなたの例では、BikeまたはPlane(etc ...)が後でデータベースモデルに追加される可能性があると思いますか?

情報工学表記は、包括的サブタイプ関係と排他的サブタイプ関係を区別します。一方、IDEF1X表記は、この違いを(直接)認識しませんが、完全なサブタイプと不完全なサブタイプ(IEは認識しません)を区別します。

ERwinメソッドガイド(第5章、サブタイプの関係)の次の図は、違いを示しています。

ここに画像の説明を入力してください

IEもIDEF1Xも、抽象親と具体的な親を直接指定することはできません。

物理的表現

残念ながら、実際のデータベースは継承を直接サポートしていないため、この図を実際のテーブルに変換する必要があります。これを行うには、一般的に3つのアプローチがあります。

  1. すべてのクラスを同じテーブルに配置し、子フィールドをNULL可能のままにします。次に、チェックを実行して、NULL以外のフィールドの正しいサブセットを確認できます。
    • 長所:結合がないため、一部のクエリにメリットがあります。2WD親レベルのキーを適用できます(たとえば、異なる車両と4WD同じIDを持つ車両を避けたい場合)。包括的子と排他的子、および抽象的親と具体的親を簡単に適用できます(チェックを変更するだけです)。
    • 短所:「興味のない」子を除外する必要があるため、一部のクエリは遅くなる可能性があります。DBMSによっては、子固有の制約が問題になる可能性があります。NULLが多いと、ストレージが無駄になる可能性があります。不完全なサブタイピングにはあまり適していません-新しい子を追加するには、既存のテーブルを変更する必要があります。これは、実稼働環境では問題になる可能性があります。
  2. すべての子を別々のテーブルに配置しますが、親のテーブルはありません(代わりに、すべての子で親のフィールドと制約を繰り返します)。(3)のほとんどの特性を備えていますが、JOINを回避しますが、保守性が低く(これらすべてのフィールドと制約の繰り返しのため)、親レベルのキーを適用したり、具体的な親を表すことができません。
  3. 親と子の両方を別々のテーブルに配置します。
    • 長所:きれい。フィールド/制約を人為的に繰り返す必要はありません。親レベルのキーを適用し、子固有の制約を簡単に追加できます。不完全なサブタイピングに適しています(子テーブルを比較的簡単に追加できます)。特定のクエリは、「興味深い」子テーブルのみを調べることでメリットがあります。
    • 短所:一部のクエリはJOINを多用する可能性があります。包括的vs.排他的子および抽象vs.具体的親を強制するのは難しい場合があります(DBMSが循環および遅延外部キーをサポートしている場合、これらは宣言的に強制できますが、通常、アプリケーションレベルで強制することはそれほど悪いことではないと見なされます)。

ご覧のとおり、状況は理想的とは言えません。どのアプローチを選択しても、妥協する必要があります。アプローチ(3)がおそらく出発点であり、やむを得ない理由がある場合にのみ、選択肢の1つを選択してください。


1これが、図の線の太さを表していると思います。

2これが、図で「互いに素」の有無が表すものだと思います。

于 2012-08-20T12:10:56.060 に答える
3

通常、データベース設計でスーパータイプ/サブタイプの関係を作成する場合は、一般エンティティタイプ(スーパータイプ)用に個別のテーブルを作成し、特殊エンティティバージョン(サブタイプ)用に個別のテーブルを作成する必要があります。ばらばらかどうか。あなたの場合、VEHICLEのテーブルと主キー、およびすべてのサブタイプに共通または共有されているいくつかの属性を作成する必要があります。次に、2WDと4WDに別々のテーブルを作成し、それらのテーブルにのみ固有の属性を作成する必要があります。例えば

次に、SQL結合を使用してこれらのテーブルをクエリできます

于 2012-08-20T12:30:18.003 に答える
2

他のレスポンダーが言ったことに加えて、サブクラステーブルの主キーに入る次のこと。

あなたのケースは、「Generalization Specialization」、または略してGen-Specとして知られているデザインパターンのインスタンスのように見えます。データベーステーブルを使用してgen-specをモデル化する方法の問題は、SOで常に発生します。

JavaなどのOOPLでgen-specをモデル化する場合は、サブクラス継承機能を使用して詳細を処理します。一般化されたオブジェクトを処理するクラスを定義してから、特殊なオブジェクトのタイプごとに1つずつ、サブクラスのコレクションを定義するだけです。各サブクラスは、一般化されたクラスを拡張します。それは簡単で簡単です。

残念ながら、リレーショナルデータモデルにはサブクラスの継承が組み込まれておらず、SQLデータベースシステムにはそのような機能はありません。しかし、あなたは運が悪いわけではありません。OOPのクラス構造に対応する方法で、gen-specをモデル化するようにテーブルを設計できます。次に、新しいアイテムが一般化されたクラスに追加されたときに、独自の継承メカニズムを実装するように調整する必要があります。詳細は以下の通りです。

クラス構造はかなり単純で、genクラス用に1つのテーブル、specサブクラスごとに1つのテーブルがあります。これは、マーティンファウラーのウェブサイトからの素敵なイラストです。 クラステーブル継承。 この図では、Cricketerはサブクラスとスーパークラスの両方であることに注意してください。どの属性をどのテーブルに入れるかを選択する必要があります。この図は、各テーブルの1つのサンプル属性を示しています。

トリッキーな詳細は、これらのテーブルの主キーをどのように定義するかです。genクラステーブルは通常の方法で主キーを取得します(このテーブルがクリケット選手のようなさらに別の一般化の特殊化である場合を除く)。ほとんどの設計者は、主キーに「Id」などの標準名を付けます。自動番号機能を使用して、Idフィールドに入力します。スペッククラステーブルは「Id」という名前の主キーを取得しますが、自動番号機能は使用されません。代わりに、各サブクラステーブルの主キーは、一般化されたテーブルの主キーを参照するように制約されます。これにより、特殊な主キーのそれぞれが、主キーだけでなく外部キーにもなります。クリケット選手の場合、IdフィールドはプレーヤーのIdフィールドを参照しますが、ボウラーのIdフィールドはクリケット選手のIdフィールドを参照することに注意してください。

これで、新しいアイテムを追加するときに、参照整合性を維持する必要があります。方法は次のとおりです。
最初に新しい行をgenテーブルに挿入し、主キーを除くすべての属性のデータを提供します。自動番号メカニズムは、一意の主キーを生成します。次に、主キーを含むすべての属性のデータを含む、新しい行を適切なスペックテーブルに挿入します。使用する主キーは、生成されたばかりの新しい主キーのコピーです。この主キーの伝播は、「貧乏人の相続」と呼ぶことができます。

これで、すべての一般化されたデータと1つのサブクラスからのすべての特殊化されたデータが必要な場合、必要なのは、共通のキーを介して2つのテーブルを結合することだけです。問題のサブクラスに関係しないすべてのデータは、結合から除外されます。それは滑らかで、簡単で、そして速いです。

于 2012-08-20T17:01:26.933 に答える
1

特定のデータモデルを実装する方法は常に1つだけではありません。多くの場合、論理モデルから物理モデルに移動するときに発生する変換があります。

標準SQLには、互いに素なサブタイプ制約 を適用するためのクリーンな方法がありません。

スキーマを使用してモデルのルールをできるだけ多く適用することが目標である場合、モデルを実装するための標準的なアプローチは、スーパータイプとサブタイプごとに1つのテーブルを使用することです。これにより、各エンティティに適用可能な属性のみが使用されるようになります。

互いに素な制約を適用するための多かれ少なかれ標準的なSQLトリックがあります。重要でない方法で正規化ルールに違反しているため、一部の人を先送りにします。それでも、2NFの技術的違反があるため、この技術は審美的に不快であると感じる人もいます。

この手法では、スーパータイプにパーティショニング属性を追加し、このパーティショニング属性を各サブタイプに含めて、サブタイプの主キーに追加します。パーティショニング属性に特定の値を課すチェック制約に加えて、これにより、各エンティティが最大で1つのサブタイプを持つことができるようになります。この手法は、このブログなど、多くの場所で詳細に文書化されています。

于 2012-08-20T12:30:23.093 に答える