Multiple foreign keys from the same table

爷,独闯天下 提交于 2019-12-25 05:53:30

问题


i'm building a DB of a graduation projects management system. Students are divided into groups .There is groups table and faculty table. Each group has an advisor and two examiners. i'm confused here. Should i create 3 FKs from the the faculty table? 2 for examiners and 1 for advisor?

here is the SQL code:

 create table groups
(
    groupID             NUMBER                not null,
    nbStudents          NUMBER                not null,
    avgGPA              DOUBLE                NOT NULL,
    projectName         varchar(50)           not null,
    advisorID           NUMBER                
    examiner1ID         NUMBER  
    examiner2ID         NUMBER  
    primary key (groupID)
);
create table faculty
(
    name                varchar(30)           not null,
    facultyID           NUMBER(10)            not null,
    email               varchar(30)           not null,
    mobile              NUMBER(15)            not null,
    type                varchar               
    primary key (facultyID)
);

alter table groups
    add constraint FK_EX1 foreign key (examiner1ID)
       references faculty (facultyID) ;
alter table groups
    add constraint FK_EX1 foreign key (examiner2ID)
       references faculty (facultyID) ;
alter table groups
    add constraint FK_EX1 foreign key (advisorID)
       references faculty (facultyID) ;

回答1:


EDIT PENDING... see my first comment.

Just state the foreign keys as you find them.

A foreign key says that a value in a column in a table must appear as a value of a column in another (possibly the same) table where corresponding columns form a key. So in the given design just declare the FKs as you find them.

Although these aren't really FKs. First, in SQL a FK declaration actually declares a foreign superkey. Second, because those columns can be NULL. SQL says how it's going to check them, and it doesn't check when columns are NULL, and that's what you want. But that constraint just isn't a foreign (super)key. We just call it that in an SQL database.

Find statements that describe your application situtations then normalize.

It not non-normalized to have multiple columns per se. That is a common misconception.

However its generally contraindicated for at least an ideal design. Just find a parameterized statement parameterized by column names for every thing you need to say about a situation. Each statement gets a table.

// group [groupID] contains [nbStudents] students .... and has advisor [advisorID] and ...
groups(groupID,nbStudents,...,advisorID,examinerID)

The rows that make the statement true go in the table. Find all the statements you need to describe your application situations. Fill the tables with the rows that make their statements true.

Find simple statements and rearrange for NULL later.

Notice that the above statement is only true for rows with no NULLs. But you want to say sometimes that no faculty are in those roles.

Ideally you just want

// group [groupID] contains [nbStudents] students ... [projectName])
groups(groupID,nbStudents,...,projectName)
// [facultyID] advises [groupID]
advises(facultyID,groupID)
// [facultyID] examines [groupID]
examines(faculty,groupID)

With constraints about numbers of faculty per group. If you properly write a relational design without nulls then normalize you will get this sort of simple thing. Don't worry about the number of statements/tables. They just reflect the complexity of the application.

But SQL DBMSs generally don't suport constraints easily. So for certain reasons to do with SQL or performance we might to rearrange. But design null-free first. Ie pick straightforward statements & then normalize. Then rearrange soundly. (SOme rearranging might de-normalize, but not this particular case.)

Nulls complicate.

One problem with nulls is they complicate table meanings. Your design with nulls has table group holding the rows that make this statement true:

//*
    group [groupID] contains [nbStudents] students ....
AND (   [advisorID IS NULL  they have no advisor
    OR [advisorID] IS NOT NULL AND advisor [facultyID] advises them)
AND (   [examiner1ID IS NULL AND [examiner2ID] IS NULL and they have no examiner
    OR [examiner1ID] IS NOT NULL AND [examiner2ID] IS NULL AND [examiner1ID] examines them
    OR [examiner1ID] IS NULL AND [examiner2ID] IS NOT NULL AND [examiner2ID] examines them
    OR [examiner1ID] IS NOT NULL AND [examiner2ID] IS NOT NULL
       AND [examiner1ID] examines them AND [examiner2ID] examines them)
*//
groups(groupID,nbStudents,...,advisorID,examinerID)

Unless you cut out nulls back to the simple tables above when querying, your query meanings are complicated like this too. Ie queries give rows that make statements like that true.

On top of that when nulls are left in SQL gives you complex answers that do not mean "... and faculty unknown".

People have intuitive understanding of such nulls in base tables. But design first simply and soundly. Rearrange later. Be sure you properly cut out null-free parts and leave in null-free parts when you query.



来源:https://stackoverflow.com/questions/24243417/multiple-foreign-keys-from-the-same-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!