3

うまくいけば、誰かが例、またはおそらくいくつかの提案された読書を通じて、この問題に光を当てることができます. クラス階層の等価性の後にテーブルをモデル化するための最良の設計アプローチは何だろうと思っています。これは、例を通して最もよく説明できます。

abstract class Card{
    private $_name = '';
    private $_text = '';
}

class MtgCard extends Card{
    private $_manaCost = '';
    private $_power = 0;
    private $_toughness = 0;
    private $_loyalty = 0;
}

class PokemonCard extends Card{
    private $_energyType = '';
    private $_hp = 0;
    private $_retreatCost = 0;
}

さて、このクラス階層と同期するためにテーブルをモデル化するとき、私は非常に似たものを使いました:

TABLE Card
  id            INT, AUTO_INCREMENT, PK
  name          VARCHAR(255)
  text          TEXT

TABLE MtgCard
  id            INT, AUTO_INCREMENT, PK
  card_id       INT, FK(card.id)
  manacost      VARCHAR(32)
  power         INT
  toughness     INT
  loyalty       INT

TABLE PokemonCard
  id            INT, AUTO_INCREMENT, PK
  card_id       INT, FK(card.id)
  hp            INT
  energytype    ENUM(...)
  retreatcost   INT

私が抱えている問題は、各Cardレコードを、対応するテーブルの詳細を含むレコードに関連付ける方法を見つけようとすることです。具体的には、どのテーブルを調べる必要があるかを判断する方法です。

関連するテーブルの名前を保持するためにVARCHAR列を追加する必要がありますか? Cardそれが私の仲間と私が到達した唯一の解決策ですが、それはあまりにも「汚い」ようです. ここでは、設計を拡張可能に保つことが重要であり、新しいサブクラスを簡単に追加できるようにします。

誰かがクラス/テーブル階層をミラーリングするクリーンな方法を示す例またはリソースを提供できれば、それは最も高く評価されます.

4

2 に答える 2

7

Google の「汎化特化リレーショナル モデリング」。リレーショナル テーブルを使用して gen-spec パターンをモデル化する方法に関する優れた記事がいくつかあります。これと同じ質問がSOで何度も尋ねられましたが、詳細はわずかに異なります。

これらの記事の最良の部分は、一般化されたデータ用に 1 つのテーブルを作成し、特殊なデータ用に別のテーブルを作成するという決定を確認するものです。最大の違いは、主キーと外部キーの使用を推奨する方法です。基本的に、特殊なテーブルには、2 つの役割を果たす単一の列を含めることをお勧めします。特殊化されたテーブルの主キーとして機能しますが、汎用化されたテーブルの PK を複製する外部キーでもあります。

これは維持するのが少し複雑ですが、参加時に非常に便利です。

また、新しいクラスが階層に追加されたときに DDL が必要になることにも注意してください。

于 2010-11-10T11:01:18.180 に答える
3

基本的にはしないでください。

クラス階層、ストレージモデル、およびアプリと特定のアプリ言語に固有のものはすべて忘れてください。RDbをファイルの単なる保存場所として使用したい場合を除いて、依存スレーブ。

リレーショナルデータベースのパワーと柔軟性(特に拡張性)が必要な場合は、アプリから独立して、アプリの言語要件ではなくRDbの原則を使用してデータベースをモデル化する必要があります。アプリのコンテキストをしばらく残し、データベースをデータベースとして設計します。それらについて学びます。正規化(すべての重複を排除)。構造とルールについて学び、それらを実装します。これを行うと、クエリと「マッピング」が簡単になります。「インピーダンス」はありません。正しいデータ型を使用すると、不一致は発生しません。

必要な構造は通常のサブタイプ-スーパータイプです。これらは、RMで30年以上、リレーショナルデータベース製品で23年以上存在しているリレーショナルデータベースの用語です。それらを面白い新しい名前と呼ぶ必要はありません。ウィキペディアは学術的な参考資料ではありません。

開始点として非常に正しい(自動的に正規化された)テーブルを考えると、次のものが必要です。

  • Card.Idの名前をCard.CardIdに変更します

  • サブタイプのIDを削除します。これらは100%冗長です。CardIdはPKとFKの両方です。

  • 識別子Card.CardTypeCHAR(1)またはTINYINTを追加します。これにより、CardTypeが不明な場合に、結合するサブタイプが識別されます。

  • 外部キーの概念を完全には理解していないようですので、最初に準備しておくとよいでしょう。ここでは、単純で通常の形式で実装されています。

    ALTER TABLE MtgCard
        ADD CONSTRAINT Card_MtgCard_fk
        FOREIGN KEY (CardId)
        REFERENCES Card(CardId)

  • CardとMtgCardまたはPokemonCardの関係は常に1::1です。スーパータイプは、カードと{MtgCard | 同じCardIdを持つPokemonCard}。あなたの場合、サブタイプは1つだけであり、単純なCHECK制約で簡単に適用できます。

    • その他の場合、複数のサブタイプが非常に合法です。

    • あるサブタイプは、Person IsaTeacherまたはPersonIsStudent

  • リレーショナルデータベースには、「from」または「to」(または上/下または左/右)を結合するという概念はありません。これらの概念は、私たち人間を支援するためだけにあります。持っている任意のテーブル/キーから始めて、必要な任意のテーブルに移動できます。中間のテーブルは、リレーショナル識別子がない場合にのみ要求されます(つまり、意味のある自然キーの代わりに追加のサロゲート、ID列がPKとして使用される場合)。

    • この例では、用語を使用して、中間テーブルにアクセスしなくても、登録から個人(たとえば、LastNameを取得)またはコース(名前を取得)直接移動できます。関係線は実線です。 。
  • 現在、クラス階層("Is"または"Is a")やその他のものは、単純で簡単です。

標準のリレーショナルデータベース図へのクイックリファレンス。

于 2010-11-11T03:24:33.477 に答える