2010-02-05 39 views
2

我面臨的情況是,我有兩個表:A和B. B有一個外鍵到A.爲了強制執行檢查約束,在表中複製列是否是個好主意?

A有一個「Detailed」列,用於標識其B子項中是否需要其「細節「部分填寫。

如果我有我的精益結構,我無法確定B中的記錄是否需要填寫其「詳細信息」部分,即不爲空,而不加入A.因此,唯一的方法是爲我爲了防止有人插入或更新這些記錄到一個無效的狀態是有一個觸發器加入A並檢查其「詳細」列。

我的感覺是,約束優於觸發器,因爲除了過濾器外,它們更像數據的事實,而觸發器只是過濾器。

我能得到這個通過複製B中的「詳細」欄,然後有一個檢查約束(詳細=「Y」和細節IS NOT NULL)OR(詳細=「N」)

思考解決這個問題的最好方法是?

+0

如果您將列複製到表B中,將使其與表A同步嗎?將它留在A中並使用觸發器。 – 2010-02-05 16:43:32

+0

如果我要走這條路線,我會強制從B到A的外鍵的同步性。 – 2010-02-05 16:47:00

+0

與FK之間的二者,那麼將不可能改變「詳細」的值。 – 2010-02-05 18:12:46

回答

3

您提到的所有工具(約束和觸發器)只是一種強制數據庫中數據一致性的方法。

簡單的業務規則,如「始終有一個參考」,「沒有NULL」等是強制執行的約束。

更復雜的商業規則,像你在這裏提到的那樣,應該使用觸發器強制執行。

約束條件不比觸發條件「更好」或「更差」:它們只是您需要經常實施的規則的捷徑。

爲了您的任務,只需實施一個觸發器。

但是,在Oracle中,約束和觸發器都不是以純集合方式實現的。對於受DML操作影響的每個記錄,它們被稱爲循環。

最有效的方法是創建一個包裝,作爲所有DML的單一入口點,並檢查包裝中的Details

+0

好的建議...我已經在使用所有DML操作的軟件包,但由於我不是PL/SQL的專家,但我覺得在將我的理解鎖定的情況下添加這些約束作爲備份是非常合適的機制和隔離水平並不密切。除了甲骨文的指南和谷歌搜索,掌握這些主題的資源的任何建議?謝謝。 – 2010-02-05 16:39:55

0

我會在UI中執行這樣的規則。如果您的業務規則變得更加複雜,那麼您需要在模型中填充大量冗餘列,以便強制執行數據庫模式中的所有規則。

+0

然後應用程序錯誤,不同的流氓應用程序,手動數據更新或錯誤的腳本進行更改可能會破壞數據。 – 2010-02-05 16:42:35

+0

我目前在幾個地方(客戶端,服務器,數據庫)執行這些規則,但由於我正在使用的應用程序有很多併發用戶可能影響相同的數據,我試圖消除兩個同時請求傳遞應用層檢查,然後將這些記錄更改爲無效狀態。我想我需要鎖定數據庫記錄才能達到這個安全級別,而不是增加額外的列。 – 2010-02-05 16:45:00

+0

只要性能不成問題,在數據庫中執行此操作就沒有問題,並且會讓您放心,您的數據不會被損壞。 – 2010-02-05 17:22:36

2

在數據庫級別執行此操作並且Quassnoi的要點都很好,這是正確的。另外,您可能想要調查讓此操作的API引用兩個表的updatable join view並通過該約束實現約束。

2

在一個理想的世界,Oracle等數據庫管理系統將支持「斷言」:

create assertion no_more_than_50_per_user as 
check(not exists(select null 
       from a join b on ... 
       where a.detailed = 'Y' 
       and b.details is null 
); 

他們沒有,但(而不是沒有很好的理由:這將是很難實現它們性能的方式!)

正如Quassnoi所說,可以使用觸發器代替 - 但您需要了解多用戶環境中的危險。爲確保執行一致性,您需要在檢查數據時取出鎖定以確保不會發生這種情況:

(假定當前記錄1有詳細='N',但所有關聯的B記錄都有詳細信息不爲空)。

user1> Update A set detailed = 'Y' where a_id=1; 

這是有效的,因爲所有關聯的B行都有非空的細節。

user2> Update B set details = null where a_id=1; 

這有效,因爲user1還沒有提交,所以user2的觸發器看到詳細='N'。

user1> commit; 
user2> commit; 

現在你已經損壞了數據。爲了防止這種情況,B上的觸發器需要選擇「更新」行。

0

如果要在B上覆制Detailed字段,則可以使用外鍵來強制執行它,例如, (B.KEYFIELD,B.詳細)參考文獻(A.KEYFIELD,A.DETAILED)。我並不是瘋狂地重複B上的字段,但另一方面,您似乎有與A上存在的B相關的數據。如果您可以從A中移除DETAILED並將其壓入B,則設計可能是清潔器。一些額外的細節可能有幫助

分享和享受。

相關問題