2013-03-25 112 views
0

我對數據庫非常陌生,所以請和我一起裸照。添加外鍵關係是否危險?

作爲一名程序員,添加對象的引用是相當安全的,但添加外鍵關係(我認爲)是非常危險的。通過添加FK關係,必須更新從此外部表中刪除行的所有查詢,以在實際刪除行之前正確刪除與該行關聯的外鍵。如何搜索從外表中刪除行的所有查詢?這些查詢可以隱藏在代碼和存儲過程中。這是維護噩夢的真實生活的例子嗎?有沒有解決這個問題的方法?

+0

我知道如果你嘗試刪除亂序(例如:在FK之前刪除PK),SQL Server實際上會拋出一個錯誤,但我不確定這是否適用於所有SQL。 – 2013-03-25 18:27:15

+3

在RDBMS中強烈建議定義一個外鍵。如果要刪除父表中的記錄,請清除子表中的相關記錄,然後清除父表記錄。 – 2013-03-25 18:27:19

+0

您認爲您瞭解外鍵的一切都是錯誤的。這個問題的答案几乎開始填補你的教育空白。你需要做更多的研究和閱讀。 – 2013-03-25 18:34:37

回答

1

你不應該從一開始就設計一個沒有外鍵的關係型數據庫。這是一段時間內數據完整性不佳的保證。

您可以添加代碼並使用級聯刪除,如其他人所建議的那樣,但這通常也是錯誤的答案。有時您真的希望刪除因爲您有子記錄而停止。例如,假設你有客戶和訂單。如果您刪除了有訂單的客戶,那麼您將失去訂單的財務記錄,這是一場災難。相反,您會希望應用程序發生錯誤,說明此客戶的訂單存在。進一步級聯刪除可能會突然讓您刪除數百萬個子記錄,從而在大量事務發生時鎖定您的數據庫。這是一種危險的做法,應該很少用於生產數據庫。

添加FK(如果您有關係,則需要),然後搜索從該表中刪除並適當調整的代碼。考慮一下軟刪除不是一個更好的選擇。這是您將記錄標記爲已刪除或不活動的位置,因此它不再顯示爲數據輸入選項,但您仍可以看到現有記錄。再次,您可能需要相當嚴格地調整數據庫代碼才能正確實現。有一個從一開始就設計得很差的數據庫並不容易。

如果您認爲您將擁有許多子記錄並且實際上想刪除它們,那麼軟刪除也是一個不錯的選擇。這樣,您可以標記記錄,使其不再顯示在應用程序中,並使用在非高峯時段運行的作業批量刪除記錄。

如果您要添加一個新表並添加一個FK,它肯定會比較容易處理,因爲您會在編寫任何代碼之前創建該表。

1

您的陳述根本不正確。建立外鍵關係時,可以將級聯屬性設置爲cascade delete。一旦完成,子記錄將在刪除父項時被刪除,確保沒有記錄被孤立。

+0

當然,級聯應該很少做,它也是危險的。 – HLGEM 2013-03-25 19:32:25

+0

@HLGEM,我認爲你的陳述有點誤導。有很多完全可以接受的(和安全的)實例級聯刪除應該完成。例如,訂單和訂單明細記錄。如果訂單被刪除(除非您的DBA讚賞孤立記錄),則詳細記錄**必須刪除。當然,訂單記錄可能不應該首先被刪除,但這是另一個問題。 – 2013-03-25 19:47:57

+0

當然,子記錄應該被刪除,它們只是不應該在級聯中自動刪除,或者如果你有太多的話可以鎖定服務器。我不知道很多dbas誰會允許生產數據庫使用級聯刪除。 – HLGEM 2013-03-25 20:41:49

1

如果使用正確的ORM解決方案,正確配置FK和PK,並且啓用級聯刪除,則不應該有任何問題。

1

我不會這麼說(以確認其他人提到的是什麼) - 這通常是通過級聯刪除來處理的。提供你想要的那種方式 - 或者用小心謹慎的程序來清理背後的東西。

更大的系統是您可以看到更多'程序',而不是'自動化'(即級聯刪除)。對於更大的設置 - DBA-s通常更喜歡在數據庫維護階段處理這個問題。通常情況下,通過中間件應用程序代碼不允許刪除記錄 - 但只是將其標記爲「已刪除」或不活動 - 並根據組織中存在的數據庫例程和程序(存檔等)進行處理。 。

除非你有一個非常大的代碼庫,這不是一個大問題。另外,通常,大部分Db代碼都會通過一些可以輕鬆遍歷的DAL層。或者你也可以查詢所有關係和'依賴關係'的系統表,並且許多例程都是爲這樣的代碼維護而編寫的(在'fence'的兩側)。這並不是說這不是一個'問題',只是和普通的Db工作沒什麼不同 - 而且還有比這更糟糕的事情。

So, I wouldn't lose my sleep over that。圍繞使用「太多」參照完整性約束(性能,維護)還存在其他問題 - 但這在DBA-s(以及一般的Db專業人員)中通常是一個非常有爭議的問題,所以我不會深入瞭解:)