2014-11-03 34 views
4

使用Firebird 2.1。在現有表上創建外鍵失敗,但找不到孤立記錄

雖然重構一個大的系統,我想創建兩個已填充表之間的外鍵:

ALTER TABLE CMS_ARTRANS 
ADD CONSTRAINT FK_ARTRANS_PRACTITIONER_ID 
FOREIGN KEY (PRACTITIONER_ID) 
REFERENCES CMS_SOLICITORS (RECID); 

這失敗的消息:

違反外鍵約束「的」。 違反表「CMS_SOLICITORS」上的FOREIGN KEY約束「PK_CMS_SOLICITORS」。 外鍵參考目標不存在。

我有點期待在那裏與參照完整性,這就是爲什麼我要在FK擺在首位的問題。所以我去尋找不匹配的記錄:

SELECT 
    * 
FROM CMS_ARTRANS AR 
LEFT OUTER JOIN CMS_SOLICITORS S 
    ON (S.RECID = AR.PRACTITIONER_ID) 
WHERE (AR.PRACTITIONER_ID IS NOT NULL) AND (S.RECID IS NULL) 

而且沒有。 CMS_ARTRANS.PRACTITIONER_ID中有大量NULL。但是沒有與CMS_SOLICITOR記錄不匹配的非NULL值。

爲什麼火鳥不喜歡我的FK?

+0

我不知道你的特定的DBMS,但您可能需要明確指出的的Fkey可以'NULL',仍然是有效的。請參閱:http://stackoverflow.com/questions/2366854/can-table-columns-with-a-foreign-key-be-null – aruisdante 2014-11-03 16:23:47

+0

是否有'PRACTITIONER_ID'現有指數?這可能發生在索引損壞的情況下:查詢使用索引並且看不到某些記錄,而實際創建外鍵確實會看到它們。您可以通過刪除索引或 - 假設這是一個整數字段 - 用'AR.PRACTITIONER_ID + 0'替換**出現的兩個** AR.PRACTITIONER_ID'(這將強制查詢不使用索引)。 – 2014-11-03 18:05:34

+0

我在糾正外鍵字段中的值後不久就發生了這種情況。等待一段時間(讓事務變得比最早的有趣事務更舊),並用gfix -sweep清理數據庫似乎可以解決它。 – nater 2014-11-03 19:12:05

回答

5

最常見的,這種情況發生時,有對不符合主鍵之外的交易可見記錄:也許你刪除例如,所有有問題的記錄,但他們仍然對其他事務可見。因此,解決方案要麼等待比您的更早的交易關閉,要麼迫使他們關閉。

在實踐中,最簡單的方法是使用gfix採取數據庫脫機(如果你能負擔得起)。

+0

是的,我認爲這是我的問題的原因。我沒有想過併發用戶/交易,因爲它發生在數據庫的開發副本上,我希望成爲它的唯一用戶。 我現在懷疑通過在我的DB前端工具(IBExpert)中打開「隱形事務」來阻止我自己。 重新啓動DB服務器服務作爲最殘酷的措施,然後重試添加約束脩復了問題。 就像平常一樣:簡單易懂。 謝謝大家。 – 2014-11-04 14:56:57