【问题标题】:unique index across join?跨连接的唯一索引?
【发布时间】:2011-12-02 03:49:46
【问题描述】:

三个表。

赛事有很多比赛

种族有很多注册

Registrations 上有一个整数 'bib_number'

我需要确保活动号码布是唯一的。

我拥有的最佳解决方案是将 event_id 非规范化到注册中...然后我可以为注册添加一个唯一键:

UNIQUE KEY `index_bib_number_event_id` (`bib_number`, `event_id`)

....但如果可能的话,我宁愿避免这种情况

这是表格:

CREATE TABLE `registrations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `race_id` int(11) NOT NULL,
  `bib_number` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
)

CREATE TABLE `races` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
}

CREATE TABLE `events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
}

【问题讨论】:

  • 不确定这是否可能(这就是为什么这是评论而不是答案)但您是否尝试过在视图上创建唯一索引?
  • 号码布号码是赛事独有的,而不是比赛?
  • @Catcall,OP 希望确保号码布号码对于整个赛事是唯一的,而不是只是比赛。
  • @MarkBannister:我知道他说了什么。我怀疑他是否真的是这个意思。
  • @MarkBannister:是的。我的思想和写作从相反的方向朝着同一点前进。我根据事件的独特性来回答。

标签: mysql sql ruby-on-rails


【解决方案1】:

你看.. 你已经对你的registration 表进行了非规范化,因为bib_number 不依赖于 PK (id)。因此,您可以随意将event_id 移动到registration,但我宁愿再次查看db 模型并尝试找出是否可以。可能是您在设计数据库时遗漏了什么。

【讨论】:

    【解决方案2】:

    这些方面的东西应该可以工作。我相信您可以修复 MySQL 的语法。

    我省略了自动编号,因为它们可以隐藏真正发生的事情。所有表都至少为 5NF,如果您使用自动递增数字,您可能会忽略这一事实。

    create table events (
      event_id integer primary key
    );
    
    create table races (
      event_id integer not null references events (event_id),
      race_id integer not null,
      primary key (event_id, race_id)
    );
    
    create table registrations (
      event_id integer not null,
      race_id integer not null,
    
      foreign key (event_id, race_id) 
        references races (event_id, race_id),
    
      registration_id integer not null,
      primary key (event_id, race_id, registration_id),
    
      bib_number integer not null,
    
      unique (event_id, bib_number)
    );
    

    这里有一些示例数据可供使用。

    -- Two events.
    insert into events values (1);
    insert into events values (2);
    
    -- Three races in each event.
    insert into races values (1,1);
    insert into races values (1,2);
    insert into races values (1,3);
    insert into races values (2,1);
    insert into races values (2,2);
    insert into races values (2,3);
    
    -- Some registrations.
    insert into registrations values (1, 1, 1, 51);
    insert into registrations values (1, 1, 2, 52);
    insert into registrations values (1, 1, 3, 53);
    insert into registrations values (1, 1, 4, 54);
    insert into registrations values (1, 2, 1, 61);
    insert into registrations values (1, 2, 2, 62);
    insert into registrations values (1, 2, 3, 63);
    insert into registrations values (1, 2, 4, 64);
    insert into registrations values (1, 3, 1, 71);
    insert into registrations values (1, 3, 2, 72);
    insert into registrations values (1, 3, 3, 73);
    insert into registrations values (1, 3, 4, 74);
    
    -- These bib numbers were already used, but not in event 2.
    insert into registrations values (2, 1, 1, 51);
    insert into registrations values (2, 1, 2, 52);
    insert into registrations values (2, 1, 3, 53);
    insert into registrations values (2, 1, 4, 54);
    

    【讨论】:

    • primary key (event_id, race_id, registration_id) 似乎是多余的。 (event_id, race_id) 或 (registration_id) 可以是 registrations 表的主键。它是 OP 架构中的后者,但是,当您将 event_id 列添加到 registrations 表中时,可能完全不需要专用的 ID 列。你怎么看?
    • @AndriyM:很难确定,因为除了参赛号码,我们没有任何真实数据。规范化、候选键的识别、功能依赖——这些都与真实属性和真实数据有关,而不是与代理 ID 号有关。就目前而言, {event_id, race_id} 不足以识别注册中的一行,但 {event_id, race_id, bib_number} 是。 (此外,您可以将其他真实属性添加到“事件”中,使其仅在 2NF 中而不是在 5NF 中。)
    • 嗯,你当然是对的,我想知道我是怎么想出这个愚蠢的主意的。我可能有不同的想法,但是,如果是这样,我现在不记得是什么了。也许我在想race_id 是多余的而不是registration_id,但我不确定。无论如何,很抱歉打扰您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2020-10-21
    • 2016-03-15
    • 1970-01-01
    相关资源
    最近更新 更多