添加两个外键时出现1215错误

1215 error when adding two foreign keys

无法解决这个(希望)最后一个错误

我在创建 tournament_table 时收到 1215 错误,但无法解释,是因为我尝试添加 2 个外键但我做错了吗?那我该怎么做呢?我在互联网上找不到令人满意的遮阳篷。

再不解决,我脑子里的堆栈就要溢出了

create table Poker_event
   (date_time       datetime    not null,
    min_players     int         not null,
    max_players     int         not null,
    house_number    int         not null, 
    postal_code     varchar(6)  not null,
primary key(date_time),
foreign key(house_number, postal_code)   references Location(house_number, postal_code) on delete cascade on update cascade);

create table Tournament
   (date_time   datetime    not null,
    prize       int         not null,
primary key(date_time),
foreign key(date_time)  references Poker_event(date_time) on delete no action on update cascade);

create table Tournament_round
   (round_nr    int       not null,
    date_time   datetime    not null,
primary key(date_time, round_nr),
foreign key(date_time)  references Tournament(date_time) on delete no action on update cascade);

create table Tournament_table
   (winner      int         not null,
    date_time   datetime    not null,
    round_nr    int         not null,
primary key(winner, date_time, round_nr),
foreign key(date_time)  references Tournament(date_time) on delete no action on update cascade,
foreign key(round_nr)   references Tournament_round(round_nr) on delete no action on update cascade)

round_nr 不是 Tournament

中的列

您的 Tournament_table 定义的最后一行:

 foreign key(round_nr) references Tournament(round_nr) 
                                  ^^^^^^^^^^^^^^^^^^^^

引用的列不存在。看起来您打算 Tournament_table 成为 Tournament_round 的 child。并且您在 Tournament_round 上有一个复合主键 (ugghhh),外键约束需要包括这两列:

foreign key(date_time, round_nr) references Tournament_round(date_time,round_nr)

另外,在第一个 table 定义中(Tournament)有一个外键引用 table Poker_event。我们没有看到引用的 table,所以我们不知道这是否是一个问题。除了这两个问题,这看起来应该可行。


跟进

CREATE TABLE Tournament
( date_time   DATETIME    NOT NULL
, prize       INT         NOT NULL
, PRIMARY KEY(date_time)
-- , FOREIGN KEY(date_time) REFERENCES Poker_event(date_time) 
--     ON DELETE NO ACTION ON UPDATE CASCADE
);

CREATE TABLE Tournament_round
( round_nr    INT       NOT NULL
, date_time   DATETIME    NOT NULL
, PRIMARY KEY(date_time, round_nr)
, FOREIGN KEY(date_time) REFERENCES Tournament(date_time) 
    ON DELETE NO ACTION ON UPDATE CASCADE
);

CREATE TABLE Tournament_table
( winner      INT         NOT NULL
, date_time   DATETIME    NOT NULL
, round_nr    INT         NOT NULL
, PRIMARY KEY(winner, date_time, round_nr)
-- , FOREIGN KEY(date_time) REFERENCES Tournament(date_time)
--     ON DELETE NO ACTION ON UPDATE CASCADE
, FOREIGN KEY(date_time,round_nr) REFERENCES Tournament_round(date_time,round_nr) 
    ON DELETE NO ACTION ON UPDATE CASCADE
);

(默认存储引擎为InnoDB)

3 queries executed, 3 success, 0 errors, 0 warnings
Query: create table Tournament ( date_time datetime ...
0 row(s) affected
--------------------------------------------------
Query: create table Tournament_round ( round_nr int ...
0 row(s) affected
--------------------------------------------------
Query: create table Tournament_table ( winner int ...
0 row(s) affected

根据我使用关系数据库(DB2、Oracle、SQL 服务器、MySQL、MariaDB)的经验,我倾向于为每个 "entity" table。 (我区分"entity" tables和其他tables,例如"lookup"(值列表)tables,和"relationship" tables、tables 纯粹是为了解决 many-to-many 关系而添加的。(纯粹的关系 table 不会有 non-key 属性,它本身也不会另一个关系中的实体)。

显然,我还没有针对您正在处理的特定问题域进行数据分析和 entity-relationship 建模。但是根据您显示的 table 定义,这里有一个使用代理键的等效 table 定义的示例。 (在我看来,id 列不违反 3NF 或 BCNF,因为它们将被视为 "candidate keys",而不是 non-key 属性。请注意 non-anonymous 关键属性,例如date_time 已从 child table 中删除,因为这些属性 现在违反 3NF(因为它们不依赖于密钥。 )

CREATE TABLE poker_event
( id             INT UNSIGNED NOT NULL PRIMARY KEY COMMENT 'pk' 
, location_id    INT UNSIGNED NOT NULL COMMENT 'fk ref location.id'
, date_time      DATETIME     NOT NULL COMMENT 'event start time'
, min_players    INT          NOT NULL COMMENT 'minimum number of players'
, max_players    INT          NOT NULL COMMENT 'maximum number of players'
, UNIQUE KEY poker_event_UX1(date_time)
, CONSTRAINT FK_poker_event_location
    FOREIGN KEY (location_id) REFERENCES location(id)
);

CREATE TABLE tournament
( id             INT UNSIGNED NOT NULL PRIMARY KEY COMMENT 'pk'
, poker_event_id INT UNSIGNED NOT NULL COMMENT 'fk ref poker_event.id'
, prize          INT          NOT NULL COMMENT 'prize'
, CONSTRAINT FK_tournament_poker_event
    FOREIGN KEY (poker_event_id) REFERENCES poker_event(id)
);

CREATE TABLE tournament_round
( id             INT UNSIGNED NOT NULL PRIMARY KEY COMMENT 'pk'
, tournament_id  INT UNSIGNED NOT NULL COMMENT 'fk ref tournament.id'
, round_nr       INT          NOT NULL COMMENT 'round number'
, UNIQUE KEY tournament_round_UX1(tournament_id,round_nr)
, CONSTRAINT FK_tournament_round_tournament
    FOREIGN KEY (tournament_id) REFERENCES tournament(id)
);

CREATE TABLE tournament_table
( id                  INT UNSIGNED NOT NULL PRIMARY KEY COMMENT 'pk'
, tournament_round_id INT UNSIGNED NOT NULL COMMENT 'fk ref tournament_round.id'
, winner              INT NOT NULL COMMENT 'winner'
, UNIQUE KEY tournament_table_UX1(tournament_round_id,winner)
, CONSTRAINT FK_tournament_table_tournament_round
    FOREIGN KEY (tournament_round_id) REFERENCES tournament_round(id)
);

问题是

create table Tournament_table
   (winner      int         not null,
    date_time   datetime    not null,
    round_nr    int         not null,
primary key(winner, date_time, round_nr),
foreign key(date_time)  references Tournament(date_time) on delete no action on update cascade,
foreign key(round_nr)   references Tournament_round(round_nr) on delete no action on update cascade)

应该是

create table Tournament_table
   (winner      int         not null,
    date_time   datetime    not null,
    round_nr    int         not null,
primary key(winner, date_time, round_nr),
foreign key(date_time, round_nr)   references Tournament_round(date_time, round_nr) on delete no action on update cascade);

显然,这是一个复合键。