2016-06-10 71 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定义中。