2016-06-10 114 views
0

我在SSMS中遇到一個奇怪的問題。改變表添加約束與改變表添加檢查約束

我的表設計大量使用組合鍵來在所有傳遞關係中執行嚴格而健壯的參照完整性 - 代價是違反了BCNF,但實際上它證明非常方便,尤其是對於實體框架的自動導航屬性(相關對於我之前發佈的這個問題:How can I enforce second-degree relationships without composite keys?)。

無論如何,我遇到了使用SSMS 2014圖編輯器添加外鍵關係的問題。

這裏是我的問題的一個簡單的例子:

CREATE TABLE Tenants (
    TenantId bigint IDENTITY(1,1) PRIMARY KEY 
) 

CREATE TABLE Shops (
    TenantId bigint, -- Is a FOREIGN KEY(Tenants REFERENCES TenantId) 
    ShopId bigint IDENTITY(1,1) 

    PRIMARY KEY(TenantId, ShopId) 
) 

CREATE TABLE Job (
    TenantId bigint, -- Is a FOREIGN KEY(Tenants REFERENCES TenantId) 
    ShopId bigint, -- Is a FOREIGN KEY(Shops REFERENCES TenantId) 
    JobId bigint IDENTITY(1,1) 

    PRIMARY KEY(TenantId, ShopId, JobId) 
) 

我有這樣的列很多的表,並使用圖表編輯器來創建具有參照完整性複合鍵的關係正常工作(你只需按Ctrl +點擊每個複合FK列,然後用一些時間拖動到主鍵表中,然後單擊確定,這就是它。

然而,它失敗。例如,如果我選擇在JobsTenantIdShopId並拖動到Shops表,它給了我這個e RROR:

The columns in table 'Shops' do not match an existing primary key or UNIQUE constraint.

...儘管這兩列Shops表的主鍵!

我SSMS生成因爲它是試圖添加約束的SQL,它給了我這個(格式化礦,另外TRANSACTION代碼中刪除):

ALTER TABLE 
    dbo.Jobs 
ADD CONSTRAINT 
    FK_Jobs_Shops 
FOREIGN KEY 
    (ShopId, TenantId) REFERENCES dbo.Shops (ShopId, TenantId) 

ON UPDATE 
    NO ACTION 
ON DELETE 
    NO ACTION 

當我直接運行它時,SQL Server給了我這個錯誤:

Msg 1776, Level 16, State 0, Line 1 There are no primary or candidate keys in the referenced table ' dbo.Shops ' that match the referencing column list in the foreign key ' FK_Jobs_Shops '.

Msg 1750, Level 16, State 0, Line 1 Could not create constraint or index. See previous errors.

注意其他表已有的Shops定義的外鍵關係 - 所以我不知道發生了什麼事情。所以我告訴SSMS到腳本來創建看似工作的制約 - 然後我改名的事情,使之創造我本來想(JobsShops之間)的約束,它給了我這個不同輸出(格式化礦):

ALTER TABLE 
    [dbo].Jobs WITH CHECK 
ADD CONSTRAINT 
    [FK_Jobs_Shops] 
FOREIGN KEY 
    ([TenantId], [ShopId]) REFERENCES [dbo].[Shops] ([TenantId], [ShopId]) 
GO 

ALTER TABLE 
    [dbo].[Jobs] 
CHECK CONSTRAINT 
    [FK_Jobs_Shops] 
GO 

當我跑這個它的工作!

注意區別:

  • 添加的WITH CHECK
  • 缺乏ON UPDATE/ON DELETE報表
  • 約束在兩個語句,而不是一個影響。

我的問題:

  • 我有沒有發現在SQL Server中的錯誤?
  • 兩個約束定義語法之間是否存在語義差異?
  • 或者說,爲什麼一個人工作,而不是另一個?
+0

你可以看到http://stackoverflow.com/questions/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint,也許有用 – Kiquenet

回答

2

這兩個腳本之間唯一的重要區別是外鍵字段/引用主鍵字段的順序。

發生故障的腳本使用(ShopId, TenantId)這不是主鍵定義的順序:

PRIMARY KEY(TenantId, ShopId) 

找不到一個正式的參考,但它seems,你必須指定在同一順序的FK領域在PK定義中。