关联表的外键

时间:2019-02-20 17:40:39

标签: sql database-design foreign-keys rdbms

可以使用对多对多关联表的引用还是可以使用显式FK更好?

假设我们有一些这样的多对多模型:

CREATE TABLE Project (
  id int NOT NULL,
  ....
  PRIMARY KEY(id)
);
CREATE TABLE Programmer (
  id int NOT NULL,
  ....
  PRIMARY KEY(id)
);
CREATE TABLE Project_Programmer_Association(
  id int NOT NULL,
  project_id int,
  programmer_id int,
  .... (probably some other data)
  FOREIGN KEY (project_id) REFERENCES Project (id),
  FOREIGN KEY (programmer_id) REFERENCES Programmer(id)
);
CREATE TABLE Task (
  id int NOT NULL,
  project_programmer_id int,
  ....
  PRIMARY KEY(id),
  FOREIGN KEY (project_programmer_id) REFERENCES Project_Programmer_Association(id)
);

在Project和Programmer表中,有一些Task所需的数据,因此我需要引用这两个表。我的问题是:我应该在Task中使用此引用

CREATE TABLE Task (
  id int NOT NULL,
  project_programmer_id int,
  ....
  PRIMARY KEY(id),
  FOREIGN KEY (project_programmer_id) REFERENCES Project_Programmer_Association(id)
);

或使用两个显式键会更好(除了缺少额外的联接外)

CREATE TABLE Task (
  id int NOT NULL,
  project_id int,
  programmer_id int,
  ....
  PRIMARY KEY(id),
  FOREIGN KEY (project_id) REFERENCES Project (id),
  FOREIGN KEY (programmer_id) REFERENCES Programmer(id)
);

2 个答案:

答案 0 :(得分:2)

我希望使用以下模式:

df = X_iris.copy()
print(df.columns, df.index[:5], "", sep="\n")
# Index(['sepal_length', 'sepal_width', 'petal_length', 'petal_width'], dtype='object')
# Index(['iris_0', 'iris_1', 'iris_2', 'iris_3', 'iris_4'], dtype='object')


def example(df, index):
    result = df.loc[index,"sepal_length"]
    print("index =", index, "works")
    return result

example(df, "iris_0")
# index = iris_0 works
# 5.1
example(df, None)
# TypeError: cannot use label indexing with a null key

因为它具有以下优点:CREATE TABLE Project ( id int NOT NULL, .... PRIMARY KEY(id) ); CREATE TABLE Programmer ( id int NOT NULL, .... PRIMARY KEY(id) ); CREATE TABLE Project_Programmer_Association( project_id int, programmer_id int, PRIMARY KEY(project_id, programmer_id), FOREIGN KEY (project_id) REFERENCES Project, FOREIGN KEY (programmer_id) REFERENCES Programmer ); CREATE TABLE Task ( id int NOT NULL, project_id int, programmer_id int, PRIMARY KEY(id), FOREIGN KEY (project_id, programmer_id) REFERENCES Project_Programmer_Association ); 没有不必要的密钥,Project_Programmer_Association的引用完整性得到保证;直接将TaskTasksProject_Programmer_AssociationProject加入的可能性。请注意,在每个夫妇编程人员项目都只有一个任务的情况下(并且只有在这种情况下),您还可以删除Task的Programmer并将主键设为其他两个属性。

答案 1 :(得分:1)

正确的问题不是“哪个更好”,而是“哪个代表您的数据”。

如果Project_Programmer_Association不保存自己的任何数据,则保留它可能是多余的,并且您可以摆脱对项目和程序员的外键。

如果它可以保存数据,更具体地说,如果一个项目和一个程序员可以具有多个关联(例如,鲍勃是项目X的首席开发人员,但仅仅是项目Y的顾问),则您绝对需要外键关联本身以正确表示您的数据模型。