在SQL Server 2008中创建复合外键

时间:2011-07-11 14:29:01

标签: sql sql-server-2008

我有两个表,我想为它创建一个外键。

主要表格

PK - Key1 - varchar(20)
PK - Key2 - date

辅助表

PK - AutoID
FK - Key1 - varchar(20)
FK - Key2 - date

当我尝试创建主表和辅助表之间的关系时,我不断收到消息

  

主表中的列与主键或唯一列不匹配   约束

辅助表中可能有许多记录具有相同的Key1和Key2,因此我们将主键设置为自动创建的数字。

关于如何在这两个表之间建立外键关系的任何想法?

5 个答案:

答案 0 :(得分:44)

外键必须引用组成具有相同列数,类型和顺序的唯一索引(PK或UK)的列。 E.g:

CREATE TABLE PrimaryTable (
  Key1 varchar(20),
  Key2 date)
GO

ALTER TABLE PrimaryTable ADD CONSTRAINT PK
  PRIMARY KEY (Key1, Key2)
GO

CREATE TABLE SecondaryTable (
  AutoID int IDENTITY,
  Key1 varchar(20),
  Key2 date)
GO

ALTER TABLE SecondaryTable ADD CONSTRAINT FK
  FOREIGN KEY (Key1, Key2) REFERENCES PrimaryTable (Key1, Key2)
GO

答案 1 :(得分:13)

其中一些是重点突出的,其中一些是其他人遇到类似问题的背景(就像任何人实际上先搜索一样?)

检查创建密钥时出现问题的第一件事是确保两个表中的数据类型不匹配。如果你有一个bigint和另一个int,它会打击。所有按键都是如此,但如果使用多个字段,则更有可能突然出现。简单的数学表明了机会增加的原因。

下一个问题是数据。如果由于数据而无法创建密钥,则必须找出子表中父表中不存在的内容。 LEFT JOIN表(在连接的第二个/左侧的辅助表)并且仅包括主表为空的行。您将要么必须在父表中创建这些记录,要么删除它们。

“绕过”的一种方法是在父表上设置一个新的主键。然后,您可以在此新主键上创建外键,并在子表中匹配尽可能多的记录。然后,您可以设置连接,然后可以将清洁作为辅助操作。

哪个更好?新主键还是使用复合键?这实际上取决于数据的性质,但我更喜欢使用自然键或复合键的派生键。但是,有时候获得单个字段派生密钥所需的工作需要做很多工作。

答案 2 :(得分:11)

这将有效:

CREATE TABLE PTable (
     Key1 varchar(20) not null,
     Key2 date not null,
     constraint PK_PTable PRIMARY KEY (Key1,Key2)
)

CREATE TABLE STable (
     AutoID int IDENTITY(1,1) not null primary key,
     Key1 varchar(20) not null,
     Key2 date not null,
     constraint FK_STable_PTable FOREIGN KEY (Key1,Key2) references PTable (Key1,Key2)
)

您需要做的是让Management Studio编写表格脚本并将其与上述内容进行比较。

答案 3 :(得分:7)

这里有一些很好的答案,但我想更进一步 - 为了子孙后代。

外键必须引用另一个表中的Primary key(唯一,聚簇索引)或Unique约束列。基本上,必要的组件是Unique约束。我想补充一点,你的外键中可以有可为空的列,但是如果你在“复合”键中允许空值,那么SQL会跳过外键关系中数据的验证。这是一个要记住的重点,因为我们大多数人使用外键的主要原因是确保数据库中的数据完整性。

最后,我想明确声明我的所有密钥名称。为什么,你可能会问?如果您需要在将来使用“全文索引”以获得更好的搜索功能,则不这样做会强制您引用键的所有“自动生成”名称。对于不需要数据转换或预定的全文索引更新的小型项目来说,这可能不是什么大问题,但如果您编写此功能的脚本,则可能会使您的工作更加困难(例如,必须查找主要的实际名称)密钥的默认名称:pk_someTable_1248594832828495904)。

以下是我在编写SQL时要做的事情,以避免任何未来的陷阱:

  1. 如果可能,请不要在Composite外键上允许NULL。
  2. 使用商定的命名约定明确命名密钥(例如PK_Schema/56_TalbeName_Col1_Col2)。这不仅为您提供了密钥的标准名称,而且您可以从索引中轻松查看引用了哪些列以及按哪种顺序。
  3. 守则:

    CREATE TABLE MySchema.PrimaryTable ( 
      Key1 varchar(20) NOT NULL, 
      Key2 date NOT NULL,
      CONSTRAINT PK_MySchema_PrimaryTable_Key1_Key2 PRIMARY KEY (Key1, Key2)
    )
    GO 
    
    CREATE TABLE MySchema.SecondaryTable ( 
      AutoID int IDENTITY, 
      Key1 varchar(20) NOT NULL, 
      Key2 date NOT NULL,
      CONSTRAINT FK_MySchema_SecondaryTable_Key1_Key2
         FOREIGN KEY (Key1, Key2) REFERENCES PrimaryTable (Key1, Key2)
    )
    GO 
    

    OptillectTeam基本上是他的回答。我只想澄清一些以前没有提到过的重要事情。有关MSDN视频的一个很好的参考讨论了这个以及更多关于外键的信息:Foreign Key Constraint

答案 4 :(得分:1)

添加单独使用以下的单独使用

   ALTER TABLE [TableName] ADD UNIQUE ([Column1], [Column2]);
相关问题