【问题标题】:Writing a table constraint编写表约束
【发布时间】:2015-03-14 23:23:51
【问题描述】:

我有三个表:

学生(snum(主键),sname)

已注册 (snum,tname)

训练(tname(主键),tdate,thour,troom)

我必须对表 Enrolled 设置一个约束,以便学生不能注册同时给出的课程(tname)。

我尝试过这样的事情,但我认为它只是给出了独特时期的教训:

select tname from Training T1 where tdate not in (select tdate from Training T2 where T1.tdate=T2.tdate)

【问题讨论】:

  • 不清楚您希望查询返回什么。您是否只是希望它忽略 Training 中与 Enrolled 中的课程时间相同的课程,并返回所有其他课程?
  • 我想对注册表进行约束,这样当学生选择多门课程时,他或她不会选择同时提供的课程。

标签: mysql sql wamp check-constraints


【解决方案1】:

如果您同意有一些冗余,则可以创建这样的约束。

这就是你要做的:

  1. Training 中对(tname, tdate, thour) 创建唯一约束:

    ALTER TABLE Training ADD CONSTRAINT
      UQ_Training_NameDateHour UNIQUE (tname, tdate, thour);
    
  2. Enrolled 中再添加两列:

    ALTER TABLE Enrolled ADD tdate date NOT NULL;
    ALTER TABLE Enrolled ADD thour int NOT NULL;
    

    我在这里猜测类型。它们需要匹配Training中对应列的类型。

  3. 让新列成为对Training 的引用的一部分:

    ALTER TABLE Enrolled ADD CONSTRAINT
      FK_Enrolled_Training FOREIGN KEY (tname, tdate, thour)
                   REFERENCES Training (tname, tdate, thour);
    

    如果您已经有一个单独指向 tname 的引用,则可以将其删除。

  4. 最后,在Enrolled 中创建一个唯一约束,以确保tdatethoursnum 中是唯一的:

    ALTER TABLE Enrolled ADD CONSTRAINT
      UQ_Enrolled_NumDateHour UNIQUE (snum, tdate, thour);
    

这样您将对Enrolled 表有一个正式的约束,以确保学生不能同时开始接受培训。

当然,当您将行插入Enrolled 时,引用必须包含所有三个组件。如果这对您来说代价太大,那么您可能不得不求助于使用触发器,as suggested by Norbert van Nobelen

【讨论】:

  • 谢谢,但我想如果我在训练表上添加一个唯一约束,那么我将不会有同时开始的课程。我想要同时开始的课程我只是不想要学生在入学时带他们去
  • 不,Training 中的唯一约束仍然允许您在同一时间开始进行培训。 tname 已经是独一无二的,因为它是一个 PK。将tname 包含到另一个唯一键中不会引入更多限制。只有在您能够引用三列时才需要该唯一键(以确保两个表之间的日期和时间没有差异)。
  • 您可能忽略了这样一个事实,即约束不仅在日期和时间上,而且在名称、日期和时间上。所以你可以有像Databases, 2015-03-30, 10Java, 2015-03-30, 10这样的条目——它们是不同的,不会违反唯一约束。
  • 是的,我明白了,你是对的,谢谢你的帮助。
【解决方案2】:

您可能必须在“插入前”和“更新前”编写触发器。 在触发器中获取您要比较的数据,然后当数据不符合您的条件时拒绝插入或更新

【讨论】:

  • 我想学习如何使用表格中的给定值构造数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多