3

まず、これを正確に検索する方法がわからないので、重複している場合は失礼します。そして、それが他のStackExchangeサイトの1つにより適しているかどうかさえわかりません。もしそうなら、私に知らせてください、そして私は代わりに向こうで尋ねます。いずれかの方法...

プロジェクトの概要

私は、プログラミングとデータベース設計を実践するための趣味のプロジェクト(ある種の作家のノート)に取り組んでいます。基本的な構造は非常に単純です。ユーザーはノートブックを作成でき、各ノートブックの下にそのノートブックに関連付けられたプロジェクトを作成できます。たぶん、ノートブックは一連の短編小説用であり、各プロジェクトは個別の物語用です。

次に、ノートブック内の特定のプロジェクト、またはノートブック自体にアイテム(シーン、キャラクターなど)を追加して、特定のプロジェクトに関連付けられないようにすることができます。このようにして、複数のプロジェクトにまたがるシーンや場所を設定したり、特定のプロジェクトに固有のシーンや場所を設定したりできます。

問題

私は、データベース内、特に可能な限りテーブル構造と制約内に、かなりの量のロジックを保持しようとしています。私が多くのアイテムに対して持っている基本的な構造は基本的に次のようなものです(私はMySqlを使用していますが、これはかなり一般的な問題です-構文について言及するだけです):

CREATE TABLE SCENES(
    ID        BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
    NOTEBOOK  BIGINT UNSIGNED NULL,
    PROJECT   BIGINT UNSIGNED NULL,
    ....
);

問題は、2つの参照、NOTEBOOKおよび/またはPROJECTの少なくとも1つが設定されていることを確認する必要があることです。両方を設定する必要はありません。PROJECTには、それが含まれているノートブックへの参照があります。一般的な「親ID」フィールドを使用できることはわかっていますが、外部キーを使用することはできないと思います。 2つのテーブルの鍵ですよね?追加の相互参照テーブル(つまり、SCENES_X_NOTEBOOKSとSCENES_X_PROJECTS)を追加する可能性もありますが、作業しているさまざまなアイテムタイプごとに同様のテーブルを追加する必要があるため、すぐに手に負えなくなります。と。これは、各アイテムが相互参照テーブルにエントリを持っていることを確認するという問題も引き起こします。

この種のロジックをストアドプロシージャやアプリケーションロジックに配置するのは簡単ですが、ロジックがバイパスされる可能性を排除するために、可能な限り何らかの制約を維持したいと思います。何とかして。

何かご意見は?テーブルの再設計などが含まれている場合でも、私はほとんど何にでも興味があります。

4

2 に答える 2

3

シーンやキャラクターに関する問題は、ライターが現在のプロジェクトからそれらを削除する可能性があることです。その場合、シーンやキャラクターを失いたくはありません。作家数年後にそれらを使用することを決定する可能性があるからです。

最も簡単なアプローチは、これを再定義することだと思います:

次に、アイテム (シーン、キャラクターなど) をノートブック内の特定のプロジェクトに追加するか、ノートブック自体に追加して、特定のプロジェクトに関連付けないようにすることができます。

その代わりに、これを言うことを考えてください。

次に、アイテム (シーン、キャラクターなど) をノートブック内のユーザー定義プロジェクト、または「未割り当て」という名前のシステム定義プロジェクトに追加できます。プロジェクト「未割り当て」は、現在ユーザー定義プロジェクトに割り当てられていないもの用です。

これを行うと、シーンとキャラクターは常にプロジェクトに割り当てられます。つまり、ユーザー定義のプロジェクトか、「未割り当て」という名前のシステム定義のプロジェクトのいずれかに割り当てられます。

于 2012-10-07T01:23:21.107 に答える
2

あなたの要件が正確に何であるかはわかりませんが、少なくともあなたの個々の質問のいくつかに答えてみてください...

問題は、NOTEBOOK と PROJECT の 2 つの参照のうち少なくとも 1 つが設定されていることを確認する必要があることです。

チェック (NOTEBOOK IS NOT NULL または PROJECT IS NOT NULL)

2 つのテーブルへの外部キーを持つことが可能だとは思いませんよね?

理論的には、同じフィールドから 2 つのテーブルを参照できますが、これは、これらのテーブルの両方に一致する行が含まれている必要があることを意味します。これはおそらくあなたが望むものではありません。

あなたはここで正しい道を進んでいます - NOTEBOOK を一方のテーブルへの FK の子エンドポイントとし、もう一方のテーブルへの PROJECT にします。NULL 外部キーは強制されないため、両方を設定する必要はありません。

追加の相互参照テーブル (SCENES_X_NOTEBOOKS と SCENES_X_PROJECTS) を追加する可能性もありますが、作業中のさまざまなアイテム タイプごとに同様のテーブルを追加する必要があるため、すぐに手に負えなくなります。と。

多対多の関係をモデル化するジャンクション (別名リンク) テーブルについて話している場合は、そのような関係にあるテーブルのペアごとにそれらを追加する必要があります。

ただし、継承(別名、カテゴリ、サブクラス化、サブタイプ、汎化階層など)を使用して、そのようなテーブル ペアの数を最小限に抑えることができます。N テーブルの 2 番目のセットに接続する必要がある M テーブルのセットがあるとします。通常、M*N ジャンクション テーブルを作成する必要があります。ただし、共通の親テーブルから最初のセットのすべてのテーブルを継承し、2 番目のセットについても同じことを行うと、これら 2 つの親テーブル間の 1 つのジャンクション テーブルを介してすべてを接続できるようになります。

継承に関する完全な説明はここでは扱いませんが、「ERwin メソッド ガイド」の「サブタイプの関係」の章と、この投稿を参照してください。

この種のロジックをストアド プロシージャまたはアプリケーション ロジックに配置するのは簡単ですが、ロジックがバイパスされる可能性を排除するために、可能であればなんらかの制約を保持したいと考えています。何とかして。

あなたの本能は正しいです - データベースをできるだけ悪いデータから「守る」ようにしてください。データの正確性を確保するための優先順位は次のとおりです。

  • テーブル自体の構造。
  • 宣言型データベースの制約 (ドメインの整合性、キーの整合性、および参照整合性)。
  • トリガーとストアド プロシージャ。
  • 中間層。
  • クライアント。

たとえば、宣言的なデータベース制約を使用するだけで特定のロジックに従う必要があることを確認できる場合は、それをトリガーに入れないでください。

于 2012-10-07T00:39:57.417 に答える