2011-11-14 41 views
1

我有兩個實體,每個實體彼此相互引用:A Page實體引用defaultUrlUrl實體引用page使用循環外鍵刪除

這是週期性的,所以一旦我添加一個頁面和一個網址什麼是相互引用,我不能刪除它們。

我可以看到兩種方法來解決它,但我不確定「主義」的方式來做到這一點。

  1. 使關係的一個唯一的指標,而不是一個外鍵約束
  2. 刪除時,關閉外鍵約束檢查

我無法弄清楚如何做任這些......你知道嗎?

謝謝!

回答

2

以下是建立這條信息的原則。如前所述,您需要將至少一個外鍵設置爲空。

另請考慮將onDelete級聯設置爲SET NULL。這將使刪除過程更簡單 - 在刪除記錄之前,您不必將密鑰更新爲NULL。

你的schema.yml看起來是這樣的:

Url: 
    columns: 
    page_id: { type: integer, notnull: true } 
    relations: 
    Page: { local: page_id, foreign: id } 

Page: 
    columns: 
    default_url_id: { type: integer, notnull: false } # ALLOWS NULL foreign key here 
    relations: 
    DefaultUrl: { class: Url, local: default_url_id, foreign: id, onDelete: SET NULL } 
+0

Bam!這很好,謝謝!實際上,我甚至沒有想過在刪除之前將一方設置爲空......所以我反正做錯了。但'onDelete:SET NULL'是關鍵。現在我明白了,它的工作原理! –

+0

@ nick-lang很高興能幫到你! – ybull

1

經驗法則是,在創建外鍵時,總是讓一個爲空或者省略一個外鍵定義。

這允許循環中斷。

最簡單的情況下(SQL語法但SAMPE原則適用):

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1) 
    ManagerId INTEGER NOT NULL 
    --... 
    PRIMARY KEY EmployeeId NONCLUSTERED 
    FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId) 
) 

可以是循環破碎如下:

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1) 
    ManagerId INTEGER NOT NULL 
    --... 
    PRIMARY KEY EmployeeId NONCLUSTERED 
) 

或如下:

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1) 
    ManagerId INTEGER NULL 
    --... 
    PRIMARY KEY EmployeeId NONCLUSTERED 
    FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId) 
) 

我喜歡在聲明外鍵時總是跟蹤圖並確保沒有周期。我將省略最危險的鑰匙,直到所有的週期都被破壞。這可確保所有表可以批量導出,然後批量導入另一個數據庫。

編輯:我發現,當你問書專家這個問題時,你會得到一個答案就像在刪除過程中關閉外鍵。這有兩個原因是錯誤的。首先,正常的事務操作不應該改變模式定義。其次,其餘的代碼需要外鍵在那裏,所以不能在應用程序代碼中處理;然而,架構修改具有跨事務處理或鎖定整個表的流血惡習。

+0

感謝Joshua。我完全明白你在說什麼......但是你知道這是怎麼做到的教義嗎? –

+0

不會學說讓你「忘記」聲明一個外鍵? – Joshua

+0

是的,我在編輯聲明中完全同意你的意見。我寧願通過'忘記'一個外鍵來解決這個問題......我似乎無法找到任何地方的任何文檔,也無法弄清楚。哦,我現在不得不離開那個。謝謝! –