タイトルは一目瞭然だと思います。多対多の関係を作成するには、PostgreSQLでテーブル構造をどのように作成しますか。
私の例:
Product(name, price);
Bill(name, date, Products);
タイトルは一目瞭然だと思います。多対多の関係を作成するには、PostgreSQLでテーブル構造をどのように作成しますか。
私の例:
Product(name, price);
Bill(name, date, Products);
回答:
SQL DDL(データ定義言語)ステートメントは次のようになります。
CREATE TABLE product (
product_id serial PRIMARY KEY -- implicit primary key constraint
, product text NOT NULL
, price numeric NOT NULL DEFAULT 0
);
CREATE TABLE bill (
bill_id serial PRIMARY KEY
, bill text NOT NULL
, billdate date NOT NULL DEFAULT CURRENT_DATE
);
CREATE TABLE bill_product (
bill_id int REFERENCES bill (bill_id) ON UPDATE CASCADE ON DELETE CASCADE
, product_id int REFERENCES product (product_id) ON UPDATE CASCADE
, amount numeric NOT NULL DEFAULT 1
, CONSTRAINT bill_product_pkey PRIMARY KEY (bill_id, product_id) -- explicit pk
);
いくつかの調整を行いました:
N:Mの関係は、通常、別々のテーブルによって実現される- bill_product
この場合には。
代理主キーserial
として列を追加しました。Postgres 10以降では、代わりにカラムを検討してください。見る:IDENTITY
製品の名前はほとんど一意ではないため、これを強くお勧めします(適切な「自然キー」ではありません)。また、一意性の強制と外部キーでの列の参照は、通常、or として格納された文字列よりinteger
も4バイト(または8バイトbigint
)の方が安価です。text
varchar
などの基本データ型の名前を使用しないでくださいdate
としての識別子。これは可能ですが、スタイルが悪いため、エラーとエラーメッセージがわかりにくくなります。正しい、小文字の引用符で囲まれていない識別子を使用してください。予約語は使用せず、可能であれば、二重引用符で囲まれた大文字と小文字の識別子を避けてください。
「名前」は良い名前ではありません。私は、テーブルの列を名前を変更product
するproduct
(またはproduct_name
または類似)。それはより良い命名規則です。それ以外の場合、クエリでいくつかのテーブルを結合すると(リレーショナルデータベースでは多くのことを行います)、 "name"という名前の複数の列ができ、列のエイリアスを使用して混乱を取り除く必要があります。それは役に立ちません。別の広く普及しているアンチパターンは、列名としての「id」だけです。
の名前がどうなるかわかりませんbill
。bill_id
この場合はおそらく十分でしょう。
price
であるデータ・タイプ numeric
分数を格納するために入力した正確(任意精度のタイプの代わりに、浮動小数点型)。整数のみを扱う場合は、そのようにしinteger
ます。たとえば、価格をセントとして保存できます。
amount
("Products"
あなたの質問で)リンクテーブルに入るbill_product
と型であるnumeric
としても。繰り返しinteger
ますが、整数のみを扱う場合。
に外部キーが表示されbill_product
ますか?変更をカスケードするために両方を作成しましたON UPDATE CASCADE
。product_id
またはbill_id
を変更する必要がある場合、変更はすべての依存するエントリにカスケードされbill_product
、何も壊れません。それらは、それら自体の重要性のない単なる参照です。
私はまた使用しON DELETE CASCADE
ましたbill_id
:請求書が削除された場合、その詳細はそれに伴って死にます。
製品についてはそうではありません。請求書で使用されている製品を削除したくない場合。これを試みるとPostgresはエラーをスローします。product
代わりに、もう1つの列を追加して、古い行をマーク(「ソフト削除」)します。
この基本的な例のすべての列はになるNOT NULL
ため、NULL
値は許可されません。(はい、すべての列-主キー列はUNIQUE NOT NULL
自動的に定義されます。)これNULL
は、どの列でも値が意味をなさないためです。初心者の方の生活を楽にします。しかし、それほど簡単に逃げることはできないので、とにかくNULL
取り扱いを理解する必要があります。列を追加すると、NULL
値、関数、結合が許可されNULL
、クエリなどに値が導入される可能性があります。
CREATE TABLE
マニュアルの章をお読みください。
主キーは、キー列に一意のインデックスを使用して実装されるため、PK列の条件を持つクエリが高速になります。ただし、キー列のシーケンスは複数列キーに関連しています。私の例でbill_product
はPK on がオン(bill_id, product_id)
になっているので、単に、product_id
または(product_id, bill_id)
指定されたproduct_id
とnoを検索するクエリがある場合に、別のインデックスを追加することができますbill_id
。見る:
マニュアルの索引に関する章を読んでください。
bill_product
ですか?通常は次のようになりますCREATE INDEX idx_bill_product_id ON booked_rates(bill_id, product_id)
。これは正解?
bill
。で追加したアイテムごとの金額が必要bill_product
です。