Sql 规范化表数据

Sql 规范化表数据,sql,database-normalization,Sql,Database Normalization,目前,我的表和关系有以下设置: 情况: 有些员工参加课程。他们在该课程独有的名册上签字。这些课程可以由不同的讲师教授多次。每门课程可能有多个名册,不同的学生会有不同的名册。还有其他规范,但在大多数情况下,我关心的是员工/讲师表 我的问题是,有时讲师也是员工。这两个表之间的唯一区别是使用了InstructorID而不是EmployeeID。这会给我的数据带来一些冗余。我希望避免这种情况,并尝试根据最佳实践来构建这种情况。是否有一种方法可以将两个表中的数据组合起来,以便在任何时候,我都可以查询表中所

目前,我的表和关系有以下设置:

情况:

有些员工参加课程。他们在该课程独有的名册上签字。这些课程可以由不同的讲师教授多次。每门课程可能有多个名册,不同的学生会有不同的名册。还有其他规范,但在大多数情况下,我关心的是员工/讲师表

我的问题是,有时讲师也是员工。这两个表之间的唯一区别是使用了InstructorID而不是EmployeeID。这会给我的数据带来一些冗余。我希望避免这种情况,并尝试根据最佳实践来构建这种情况。是否有一种方法可以将两个表中的数据组合起来,以便在任何时候,我都可以查询表中所有与特定员工一起授课的讲师

我想到了一些类似于在Employees表中添加一个带Yes/No的isInstructor字段的内容。然后,我可以检查一个人是否有“是”或“否”。然而,我觉得这是一个糟糕的想法。有人建议在employeeID中添加前缀,以表示他们是讲师。还有人建议,或许我可以添加一个额外的字段,为同样是员工的讲师添加一个标识符


基本上,我想知道解决这个问题的最佳实践方法是什么。我应该将数据分开并放在两个表中,还是应该将它们合并并添加一些内容?对于结构其余部分的任何建议也将不胜感激。这是我在这里的第一个问题,如果需要更多详细信息,请告诉我。

我会断开讲师与部门的连接删除讲师->DeptID并将EmployeeID作为外键放入讲师中。因此,没有EmployeeID的讲师实际上是一个空ID的外部讲师


这仍然会使讲师处于非标准化状态,但就您的目的而言,这应该足够好。

讲师和员工都是人。我故意使用varchar5,所以在生产中使用它时,至少要考虑一下名称

create table people (
  p_id integer primary key,
  first_name varchar(5) not null,
  last_name varchar(5) not null,
  dept_id integer not null references departments
);

insert into people values
(1, 'Robin', 'Mings', 1),
(2, 'Ora', 'Black', 1),
(3, 'Sheri', 'Johns', 2),
(4, 'Dex', 'Sims', 3);
最佳实践:如果要使用复数作为表名,请始终使用复数。如果要对表名使用奇点,请始终使用奇点。我用复数

使用表格获取有关人员是否受雇以及是否为讲师的详细信息。你至少需要知道他们的身份证号码。罗宾·明斯和雪莉·约翰是讲师

create table instructors (
  p_id integer primary key references people
);

insert into instructors values 
(1), (3);
谢丽·约翰斯是一名教师,不是一名雇员。不过,其他人是

create table employees (
  p_id integer primary key references people
);

insert into employees values
(1), (2), (4);
在employees和instructors表中,使用p_id(人名中的列名)或emp_id等列名的选择取决于应用程序

这些课程可以由不同的讲师教授多次

create table instructors (
  p_id integer primary key references people
);

insert into instructors values 
(1), (3);
不,他们不能。您的设计只允许每个课程有一个日期。区分课程和班级。课程是由特定的讲师提供的课程,在特定的日期开始

create table courses (
  course_id integer primary key,
  course_name varchar(5) not null unique,
  course_desc varchar(5) not null,       -- unique?
  course_objectives varchar(5) not null  -- Think about whether this deserves its own table.
);

insert into courses values
(1, 'AP101', 'Desc', 'Obj'),
(2, 'AR101', 'Desc', 'Obj');
最佳实践:不要在表名中使用类似list的单词。没人说,你应该在这个班吗?让我查一下我的名册。此外,语义也很重要。如果您使用的是课程表和课程表,而在您的情况下,它们实际上不是课程或名册的列表,为什么不使用员工列表、部门列表等?这里的列表只是噪音。选择更好的词

create table classes (
  course_id integer not null references courses,
  instructor_id integer not null references instructors (p_id),
  start_date date not null,
  -- I have no idea what completion_time means, so I omitted it.
  primary key (course_id, instructor_id, start_date)
);

insert into classes values
(1, 1, '2015-04-01'),
(2, 3, '2015-04-15');
根据我的经验,员工注册课程,而不是课程。您使用了sessions这个词,但在设计中没有使用它。根据应用程序的不同,您可能需要更多的表

create table class_rosters (
  course_id integer not null,
  instructor_id integer not null,
  start_date date not null,
  employee_id integer not null references employees (p_id)
    on update restrict on delete cascade,
  primary key (course_id, instructor_id, start_date, employee_id),
  foreign key (course_id, instructor_id, start_date)
    references classes (course_id, instructor_id, start_date) 
    on update cascade on delete cascade
);

insert into class_rosters values 
(1, 1, '2015-04-01', 2),
(1, 1, '2015-04-01', 4),
(2, 3, '2015-04-15', 1), -- An instructor is taking this class.
(2, 3, '2015-04-15', 2),
(2, 3, '2015-04-15', 4);
有没有一种方法可以将两个表中的数据组合起来,以便随时 我可以查询所有授课教师的表格 和某些员工


我会断开讲师与部门的连接,删除讲师->DeptID并将EmployeeID作为外键放入讲师中。在EmployeeID中添加前缀是个糟糕的主意。永远不要这样做。这打破了第一个正常形式。感谢您编辑我的问题,我可能应该检查一下教程,以确保在我的问题中正确包含图像。我将尝试您的建议,并在完成后在这里报告。我将如何扩展它,使讲师表保持正常状态?通过您的回答,我可以看出这对我的情况有多大帮助,但重复的名字/姓氏数据是不可取的。在表结构中保留空值不是一种糟糕的做法吗?如果你能提供你的推理,那就太好了。正如我所说的,我不相信你的用例有理由进一步去规范化。 instructor_id -- 3