這不是一個好的設計,如果可以的話,最好將它改爲@VojtěchDohnal已經建議的。
如果你不能改變它,你可以在插入後使用觸發器來檢查Reference
的對應值是否來自正確的表,取決於RefersTo
的當前值,如果不是,則停止插入並拋出一些錯誤,但使用觸發器也不是性能最好的方式。
你不能使用索引視圖(這將是最好的,因爲它會被模式綁定,它會從你的項目或組中獲得所有新值/刪除的值),因爲你的源是兩個不同的視圖,你會需要一個工會來生成一個可用值的完整列表,並且在索引視圖中存在一個限制The SELECT statement in the view definition must not contain UNION 。
最後一個選項:您可以使用一個附加表格,您可以在其中保留所有數據(Type('I', 'G'), Value (Id's from ItemTable for 'I', Id's from ItemGroup for 'G'))
,併爲每個表格添加可能的Id,然後使您的組合外鍵引用此新表格。
缺點是,在這種情況下,您需要跟蹤ItemTable
和ItemGroup
表中的更改,並相應地更新新創建的表(對於新插入的值或刪除的值),但它不太好維護。
對於這最後的場景代碼將是這樣的:
CREATE TABLE ItemTable (Id INT PRIMARY KEY IDENTITY(1,1), ItemName VARCHAR(100))
CREATE TABLE ItemGroup (Id INT PRIMARY KEY IDENTITY(1,1), GroupName VARCHAR(100))
CREATE TABLE Settings (Id INT PRIMARY KEY IDENTITY(1,1), RefersTo CHAR(1), Reference int)
INSERT INTO ItemTable (ItemName) values ('TestItemName1'), ('TestItemName2'), ('TestItemName3'), ('TestItemName4')
INSERT INTO [ItemGroup] (GroupName) values ('Group1'), ('Group2')
SELECT * FROM ItemTable
SELECT * FROM ItemGroup
SELECT * FROM Settings
CREATE TABLE ReferenceValues (Type char(1), Val INT, PRIMARY KEY (Type, Val))
INSERT INTO ReferenceValues
SELECT 'I' as Type, i.Id as Val
FROM dbo.ItemTable i
UNION
SELECT 'G' as Type, g.Id as Val
FROM dbo.ItemGroup as g
ALTER TABLE dbo.Settings
ADD FOREIGN KEY (RefersTo, Reference) REFERENCES dbo.ReferenceValues(Type, Val);
INSERT INTO Settings (RefersTo, Reference)
VALUES ('I', 1) -- will work
INSERT INTO Settings (RefersTo, Reference)
VALUES ('G', 4) -- will not work
爲什麼不用referenceI和referenceG列代替? – jarlh
你當然不能這樣做 – Rahul
這不是一個好的方法,可以使用兩個FKs,其中一個可能是已經建議的allways null,或者使用COMPOSITE OOP模式 - 這意味着該組可能是一種特殊類型的Item。 –