1

Railsを使用して新しいアプリを作成しているので、すべてのテーブルにid列があります。外部キーを使用してドメイン制約を適用するためのベストプラクティスは何ですか?私の考えと欲求不満の概要を説明します。

これが私が「TheRailsWay」として想像するものです。それは私が始めたものです。

Companies:
    id: integer, serial
    company_code: char, unique, not null

Invoices:
    id: integer, serial
    company_id: integer, not null

Products:
    id: integer, serial
    sku: char, unique, not null
    company_id: integer, not null

LineItems:
    id: integer, serial
    invoice_id: integer, not null, references Invoices (id)
    product_id: integer, not null, references Products (id)

これに伴う問題は、ある会社の製品が別の会社の請求書に表示される可能性があることです。LineItemsに(company_id:整数、nullではない)を追加しました。これは、自然キーとシリアルのみを使用する場合と同じように、複合外部キーを追加しました。

LineItems (product_id, company_id) references Products (id, company_id)
LineItems (invoice_id, company_id) references Invoices (id, company_id)

これにより、LineItemsは単一の会社に適切に制約されますが、過剰に設計されており、間違っているように見えます。LineItemsのcompany_idは、代理外部キーが外部テーブルですでに一意であるため、無関係です。Postgresでは、参照される属性に一意のインデックスを追加する必要があるため、idは単純に一意ですが、Products and Invoicesの(id、company_id)に一意のインデックスを作成しています。

参照される列はすでに自然キーであり、一意のインデックスがすでにあるため、自然キーとシリアル請求書番号を含む次の表では、このような複雑さは増していません。

LineItems:
    company_code: char, not null
    sku: char, not null
    invoice_id: integer, not null

LineItemsテーブルの代理キーは無視できますが、これも間違っているようです。使用する整数がすでにあるのに、なぜデータベースをcharで結合させるのですか?また、上記とまったく同じように行うには、製品と請求書に自然外部キーであるcompany_codeを追加する必要があります。

妥協...

LineItems:
    company_id: integer, not null
    sku: integer, not null
    invoice_id: integer, not null

他のテーブルに自然外部キーは必要ありませんが、使用可能な整数がある場合は、charで結合されます。

スキーマとインデックスを複雑な混乱に変えることなく、神が意図したような外部キーを使用してドメイン制約を適用するクリーンな方法はありますか?

4

1 に答える 1

1

上記でidはすでに一意であると述べていますが、id、company_idを一意にする必要があります。これは、1つの一意のアイテムのみを参照し、他のものを参照しないようにする必要があるFK参照で使用しているためです。

データを「保護」したいことは理解していますが、これは過度に設計されており、同意します。このデータを使用し、適切に機能しないシステム (会社の正しい製品をプルアップする) はすぐにわかります。プログラミングするときに、より多くのデータを処理する負担がかかり、混乱を招く可能性があります。

データを保護する努力は好きですが、より多くのデータを取得するにつれてコストが非常に高くなる可能性があり、より複雑なデータ モデルの追加の負担が確実にあります。

アプリでの「自然な」使用を通じて、データは十分に保護されていると思います。新しい請求書を作成し、請求書に記載する製品を探している場合、請求書の作成に使用しているものと同じ会社 ID を使用して製品を検索します。何らかの方法で間違った ID を取得した場合 (悪いコード、ユーザーが DB に直接)、悪い結果がすぐにわかります。

あなたの投稿の2番目の部分がよくわかりません。シンプルで正規化されたスキーマを作成するのではなく、複雑な道をたどろうとしているようです。

意味のない鍵が入れられることをなぜそんなに心配しているのですか?非標準的な方法でこのデータにアクセスするユーザーがいますか?

于 2010-04-02T19:12:47.593 に答える