2016-03-30 68 views
1

對我來說,阻止用戶或錯誤代碼插入無效數據似乎是合理的,但我不記得在任何地方看到這個!複雜的mysql約束外鍵

考慮以下表 enter image description here

  • 我怎樣才能確保訂單總是引用由同一用戶創建的地址?
  • 這種約束通常和推薦?我的意思是,我在設計中甚至不得不關心它嗎?
+1

用戶可以插入多個地址? –

+0

@Sougata,是的,只是一個實例!但是讓我們考慮一下,您可以將訂單交付到您的工作場所或家中或...... – azerafati

+0

複雜的「業務邏輯」應該編碼在用戶和數據庫之間的代碼層中。 –

回答

1

因爲我不希望用戶能夠下訂單沒有一個有效的地址,因此我只是將單獨的FK刪除到用戶表,並使用從用戶組合的用戶ID - 地址ID字段地址表作爲外鍵。

CREATE TABLE orders AS (
    --[COLUMN DEFINITIONS] 
    address_id BIGINT NOT NULL, 
    user_id BIGINT NOT NULL, 
    CONSTRAINT fk_usr_addr FOREIGN KEY (user_id, address_id) 
         REFERENCES address(user_id, id) 
) ENGINE=InnoDB; 

如果訂單是不完整的,沒有地址還沒有,那麼這不應該是一個多列外鍵的問題,根據MySQL文檔using foreign keys因爲:

比賽子句在SQL標準中控制 組合(多列)外鍵中的NULL值與主鍵 進行比較時如何處理。 MySQL本質上實現了 MATCH SIMPLE定義的語義,它允許外鍵全部或部分爲NULL。 在這種情況下,包含這種外鍵的(子表)行允許插入 ,並且與引用的 (父)表中的任何行都不匹配。使用 觸發器可以實現其他語義。

+0

不錯的建議!謝謝,但是我還沒有設置地址的未完成訂單,以及如果用戶決定隨時刪除他的某個地址會發生什麼? – azerafati

+0

訂單完成後不應更改。因此,如果用戶想要更改或刪除已完成訂單中的地址,則必須創建一個新地址記錄或將地址標記爲在yor地址表中刪除,但不要實際刪除該地址。另一種解決方案是不使用地址作爲外鍵,而是將其內容複製到訂單中。在這種情況下甚至不會有地址表的外鍵。您可以使用此場景的觸發器來強制執行數據完整性。 – Shadow

+0

明白了,謝謝。 – azerafati