我相信標題是不言自明的。你如何在PostgreSQL中創建表結構來建立多對多的關係。如何在PostgreSQL中實現多對多的關係?
我的例子:
Product(name, price);
Bill(name, date, Products);
我相信標題是不言自明的。你如何在PostgreSQL中創建表結構來建立多對多的關係。如何在PostgreSQL中實現多對多的關係?
我的例子:
Product(name, price);
Bill(name, date, Products);
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
列爲代理主鍵。我強烈建議,因爲產品的名稱不是唯一的。此外,在外鍵中強制實施唯一性和引用列對於使用4字節的integer
比使用存儲爲text
或varchar
的字符串要便宜得多。
在Postgres 10或更高版本中,請改爲使用IDENTITY
column。詳細信息:
不要使用基本數據類型的名稱,如date
爲標識符。雖然這是可能的,但它是不好的風格,並導致錯誤和錯誤消息混淆。使用。如果可以的話,切勿使用reserved words並避免使用雙引號混合大小寫標識符。
name
不是一個好名字。我將表product
的name
列重命名爲product
。這是一個更好的命名約定。否則,當你在一個查詢中加入幾個表時 - 你在關係數據庫中做很多 - 你最終會得到多個名爲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
以標記廢棄的行。
在這個基本的例子中的所有列最終是NOT NULL
,所以NULL
值是不允許的。 (是的,全部列 - 主鍵中使用的列自動定義爲UNIQUE NOT NULL
)。這是因爲NULL
值在任何列中都沒有意義。它使初學者的生活更輕鬆。但你不會輕易離開,無論如何你需要了解NULL
handling。附加列可能允許NULL
價值,功能和連接可以查詢等
閱讀CREATE TABLE
in the manual章介紹NULL
值。
主鍵在關鍵列上使用唯一的索引實現,這使得快速查詢PK列中的條件。但是,鍵列的順序與多列鍵相關。由於bill_product
上的PK位於(bill_id, product_id)
,在我的示例中,如果您有查詢給定product_id
和bill_id
的查詢請求,您可能需要在product_id
或(product_id, bill_id)
上添加另一個索引。詳細信息:
主席先生,爲了提高答案的質量,即使在幾周後,你也絕對不會回來多次。我感謝你成爲社區的忠誠貢獻者! – 2014-12-05 12:11:53
@RaduGheorghiu:謝謝。我多次提到這個答案,所以我一直在提煉它。 – 2014-12-05 12:33:37
如何爲映射表「bill_product」創建索引?通常它看起來應該是這樣的:'CREATE INDEX idx_bill_product_id ON booked_rates(bill_id,product_id)'。這是正確的嗎? – codyLine 2015-01-05 23:46:04
查詢不建立m-t-m關係 - 表結構。 – 2012-03-20 15:30:16
我沒有很好地表達自己,我該如何定義我的表格結構? – 2012-03-20 15:32:04
從帳單表中刪除產品,創建一個名爲「bill_products」的新表,其中有兩個字段:一個指向產品,一個指向帳單。使這兩個字段成爲這個新表的主鍵。 – 2012-03-20 15:34:56