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
を検討してください 代わりに列。参照:- シリアル主キー列を使用してテーブルの名前を安全に変更します
- テーブル列の自動インクリメント
- https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/
製品の名前はほとんど一意ではないため(適切な「自然キー」ではない)、強くお勧めします。また、一意性を強制し、外部キーで列を参照する方が、通常、4バイトの
integer
を使用する方が安価です。 (または8バイトのbigint
)text
として保存された文字列よりも またはvarchar
。 -
date
のような基本的なデータ型の名前は使用しないでください 識別子として 。これは可能ですが、スタイルが悪く、混乱を招くエラーやエラーメッセージが表示されます。正当な小文字の引用符で囲まれていない識別子を使用します。予約語は絶対に使用せず、可能であれば二重引用符で囲まれた大文字と小文字を区別する識別子は避けてください。 -
「名前」は良い名前ではありません。テーブルの列の名前を
product
に変更しましたproduct
になる (またはproduct_name
または類似)。それはより良い命名規則です 。それ以外の場合は、クエリでいくつかのテーブルを結合するときに、多くのを実行します。 リレーショナルデータベースでは、「name」という名前の複数の列ができてしまい、列エイリアスを使用して混乱を整理する必要があります。それは役に立ちません。もう1つの一般的なアンチパターンは、列名としての「id」です。請求書
の名前がわかりません。 だろう。bill_id
この場合はおそらく十分でしょう。 -
価格コード> データ型です
数値
小数を入力どおりに正確に保存する (浮動小数点型ではなく任意精度型)。整数のみを扱う場合は、そのinteger
を作成します 。たとえば、価格をセントで節約できます。 。 -
金額
("Products"
あなたの質問では)リンクテーブルbill_product
に入ります タイプはnumeric
同じように。繰り返しますが、integer
整数のみを扱う場合。 -
外部キーが表示されます
bill_product
で ?変更をカスケードするために両方を作成しました:ON UPDATE CASCADE
。product_id
の場合 またはbill_id
変更する必要がある場合、変更はbill_product
のすべての依存エントリにカスケードされます そして何も壊れません。これらは、それ自体の意味を持たない単なる参照です。
ON DELETE CASCADE
も使用しましたbill_id
の場合 :請求書が削除されると、その詳細は削除されます。
製品の場合はそうではありません:請求書で使用されている製品を削除したくありません。これを試みると、Postgresはエラーをスローします。product
に別の列を追加します 代わりに、廃止された行にマークを付ける( "soft-delete")。 -
この基本的な例のすべての列は、最終的に
NOT NULL
になります 、したがってNULL
値は許可されていません。 (はい、すべて 列-主キー列が定義されていますUNIQUENOT NULL
自動的に。)それはNULL
値はどの列でも意味がありません。それは初心者の生活を楽にします。しかし、あなたはそれほど簡単に逃げることはできません、あなたはNULL
を理解する必要があります とにかく処理します。追加の列により、NULL
が許可される場合があります 値、関数、および結合により、NULL
が導入される可能性があります クエリなどの値 -
CREATE TABLE
の章を読んでください マニュアルで。 -
主キーは、一意のインデックスで実装されます キー列で、PK列の条件を使用したクエリを高速化します。ただし、キー列のシーケンスは複数列のキーに関連しています。
bill_product
のPK以降(bill_id、product_id)
にあります 私の例では、product_id
だけに別のインデックスを追加することをお勧めします または(product_id、bill_id)
特定のproduct_id
を検索するクエリがある場合bill_id
はありません 。参照:- PostgreSQL複合主キー
- 複合インデックスは、最初のフィールドのクエリにも適していますか?
- PostgreSQLでのインデックスの動作
-
マニュアルのインデックスに関する章を読んでください。