我有兩個實體,每個實體彼此相互引用:A Page
實體引用defaultUrl
和Url
實體引用page
。使用循環外鍵刪除
這是週期性的,所以一旦我添加一個頁面和一個網址什麼是相互引用,我不能刪除它們。
我可以看到兩種方法來解決它,但我不確定「主義」的方式來做到這一點。
- 使關係的一個唯一的指標,而不是一個外鍵約束
- 刪除時,關閉外鍵約束檢查
我無法弄清楚如何做任這些......你知道嗎?
謝謝!
我有兩個實體,每個實體彼此相互引用:A Page
實體引用defaultUrl
和Url
實體引用page
。使用循環外鍵刪除
這是週期性的,所以一旦我添加一個頁面和一個網址什麼是相互引用,我不能刪除它們。
我可以看到兩種方法來解決它,但我不確定「主義」的方式來做到這一點。
我無法弄清楚如何做任這些......你知道嗎?
謝謝!
以下是建立這條信息的原則。如前所述,您需要將至少一個外鍵設置爲空。
另請考慮將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 }
經驗法則是,在創建外鍵時,總是讓一個爲空或者省略一個外鍵定義。
這允許循環中斷。
最簡單的情況下(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)
)
我喜歡在聲明外鍵時總是跟蹤圖並確保沒有周期。我將省略最危險的鑰匙,直到所有的週期都被破壞。這可確保所有表可以批量導出,然後批量導入另一個數據庫。
編輯:我發現,當你問書專家這個問題時,你會得到一個答案就像在刪除過程中關閉外鍵。這有兩個原因是錯誤的。首先,正常的事務操作不應該改變模式定義。其次,其餘的代碼需要外鍵在那裏,所以不能在應用程序代碼中處理;然而,架構修改具有跨事務處理或鎖定整個表的流血惡習。
感謝Joshua。我完全明白你在說什麼......但是你知道這是怎麼做到的教義嗎? –
不會學說讓你「忘記」聲明一個外鍵? – Joshua
是的,我在編輯聲明中完全同意你的意見。我寧願通過'忘記'一個外鍵來解決這個問題......我似乎無法找到任何地方的任何文檔,也無法弄清楚。哦,我現在不得不離開那個。謝謝! –
Bam!這很好,謝謝!實際上,我甚至沒有想過在刪除之前將一方設置爲空......所以我反正做錯了。但'onDelete:SET NULL'是關鍵。現在我明白了,它的工作原理! –
@ nick-lang很高興能幫到你! – ybull