【问题标题】:Foreign key referencing a 2 columns primary key in SQL Server引用 SQL Server 中的 2 列主键的外键
【发布时间】:2011-03-11 20:37:04
【问题描述】:

这个问题与this one 非常相似,但针对的是 SQL Server 2005:

我的数据库中有 2 个表:

--'#' denotes the primary key
[Libraries]
#ID   #Application  Name
 1     MyApp        Title 1
 2     MyApp        Title 2


[Content]
#ID   Application  LibraryID  Content
 10    MyApp       1          xxx
 11    MyApp       1          yyy

(数据库显然要复杂得多,拥有这个双键是有意义的)

每个库都由其唯一的 ID 和应用程序名称标识。我正在努力确保每个内容都正确引用了现有库。

当创建约束(使用向导)时

Primary key table            Foreign key table
[Libraries]                  [Content]
ID                  --->     LibraryID
Application         --->     Application

我有以下错误:

表“库”中的列 与现有主键不匹配或 唯一约束

你知道发生了什么吗?以及是否有可能使用 SQL Server? (我根本无法修改 [Library] 表)

非常感谢您的帮助!

【问题讨论】:

    标签: sql sql-server-2005 foreign-key-relationship


    【解决方案1】:

    当然,可以创建与复合(多于一列)主键的外键关系。您没有向我们展示您用来尝试建立这种关系的语句 - 它应该类似于:

    ALTER TABLE dbo.Content
       ADD CONSTRAINT FK_Content_Libraries
       FOREIGN KEY(LibraryID, Application)
       REFERENCES dbo.Libraries(ID, Application)
    

    这是你用的吗??如果(ID, Application) 确实是dbo.Libraries 的主键,那么这个语句肯定可以工作。

    Luk:只是检查一下 - 你能在你的数据库中运行这个语句并报告输出是什么吗??

    SELECT
        tc.TABLE_NAME,
        tc.CONSTRAINT_NAME, 
        ccu.COLUMN_NAME
    FROM 
        INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
    INNER JOIN 
        INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu 
          ON ccu.TABLE_NAME = tc.TABLE_NAME AND ccu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
    WHERE
        tc.TABLE_NAME IN ('Libraries', 'Content')
    

    【讨论】:

    • 我当时直接使用 UI,但使用您的语法会引发以下错误:“引用的表 'dbo.Libraries' 中没有与引用列列表匹配的主键或候选键在外键...
    • 好吧,在这种情况下,这对 (Id, Application) 是不是库表上的主键。您只能引用父表上的主键 - 或作为唯一索引一部分的列(或列集)。检查您的Libraries 表!
    • 这也是我的第一个想法,但是 SQL 脚本指定了CREATE TABLE [Libraries] (...` CONSTRAINT [PK_sf_Libraries] PRIMARY KEY CLUSTERED ([Application] ASC, [ID] ASC) WITH (PAD_INDEX = OFF , STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]`...(抱歉在这里倾倒了所有的 SQL)
    • @Luk:添加了一条您可以在您的数据库上为我运行的语句 - 只是为了检查.....
    • 嗯,有人在下面的“2014 年 3 月 18 日 14:43”回答中考虑过“威尔罗素”的理论吗?我知道 Luk 说他让它在“新数据库”中工作,但如果他“正在使用 UI”(与修改自动生成的脚本相比),因为他承认至少在他最初的 FK 添加尝试中这样做了至少一次,很有可能他也在“新数据库”中这样做了,因此很有可能在“新数据库”中,他意外得到了一致的列顺序(两者都在Create Table 中的 PK def 和 A​​lter Table 中的 FK def)。
    【解决方案2】:

    请注意,字段的顺序必须相同。如果您引用的主键指定为 (Application, ID),那么您的外键必须引用 (Application, ID) 而不是 (ID, Application),因为它们被视为两个不同的键。

    【讨论】:

    • 我怀疑这也是问题,尤其是。因为他在他的“2010 年 7 月 5 日 15:07”评论接受的答案(“marc_s's在“2010 年 7 月 5 日 10:26”),但在他的 OP 中的两个示例中都首先出现“ID”。我很惊讶没有其他人(包括 500 个(小指到嘴唇)千人以上"marc_s") 在您之前的 4 年 8 个月中指出了这一点。
    • 天哪,我花了好几个小时试图弄清楚这一点,结果证明这就是答案。谢谢!!!!
    【解决方案3】:

    关键是“列的顺序应该相同”

    例子:

    create Table A (
        A_ID char(3) primary key,
        A_name char(10) primary key,
        A_desc desc char(50)
    )
    
    create Table B (
        B_ID char(3) primary key,
        B_A_ID char(3),
        B_A_Name char(10),
        constraint [Fk_B_01] foreign key (B_A_ID,B_A_Name) references A(A_ID,A_Name)
    )
    

    表 A 上的列顺序应该是 --> A_ID 然后是 A_Name;定义外键也应该遵循相同的顺序。

    【讨论】:

      【解决方案4】:

      Content 表可能有多个无法映射到 Libraries 的重复 Application 值。是否可以从Libraries 主键索引中删除Application 列并将其添加为唯一键索引?

      【讨论】:

      • 是的,Application 可能是重复的,但这从来不需要是唯一的。 (LibraryID, Application) 对甚至可以有多个值 - 这不是 Content 表上的 PK - 它是 Libraries 表上的 PK!
      • 好的,那么当您从内容中获得的 (LibraryID, Application) 与库上的 (ID, Application) 不对应时会发生什么?截至目前,没有强制执行该限制。如果 OP 不想更改当前结构,我建议他尝试在 (LibraryID, Application) 上创建唯一键索引,看看是否可以成功创建。只有这样,再次尝试创建关系。
      • 很遗憾,我根本无法触摸Libraries。这两个表甚至应该具有 1-1 关系,因为我无法向Libraries 添加新列。你是对的,那里需要一个唯一索引(但这并没有解决问题)
      • 我是否错误地认为我只能引用外键中的列?
      • Luk:您可以在 FK 中引用两列。您是否检查过 Contents 中的所有行是否都可以映射到 Libraries? (一个简单的 LEFT JOIN 将确定您是否可以这样做)
      【解决方案5】:

      我有同样的问题,我想我有解决办法。

      如果表 Library 中的字段 Application 具有引用另一个表中的字段的外键(我敢打赌命名为 Application),那么表 Library 中的字段 Application 必须具有表 Application 的外键也是。

      之后你就可以做你的组合外键了。

      请原谅我的英语不好,如果我错了,请见谅。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-21
        • 2014-12-24
        • 1970-01-01
        • 1970-01-01
        • 2016-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多