【发布时间】:2015-12-02 06:51:29
【问题描述】:
我有以下架构:
公司
id (PK)
name
用户
id (PK)
name
dept_id (FK) // references id on Depts table
部门
id (PK)
name
manager_id (FK) // references id on Users table
company_id (FK) // references id on companies table
事实:
- 一个部门属于一个公司
- 一个部门由一个用户管理
- 一个用户属于一个部门
- 一个用户可以管理多个部门
当两个表都需要另一个表的外键时,如何创建用户记录或部门记录?
如果我有一个部门,它必须有一个经理,但如果我有一个用户,他们必须分配到一个部门。例如,如果我首先尝试创建用户,FK dept_id 约束将失败,因为不存在 Dept。如果我首先尝试创建Dept,FK manager_id 约束将失败,因为不存在用户。
***已更新****
如果引入了一些映射表,如果父表使用唯一的 ID 号作为主键,我为什么需要这么多复合主键和外键。
create table companies (
id integer auto_inc primary key,
company_name varchar(50) not null
);
create table departments (
id integer auto_inc primary key
company_id integer not null references id on companies
dept_name varchar(50) not null
);
create table employees (
id integer auto_inc primary key,
company_id integer not null references id on companies,
emp_name varchar(50) not null,
emp_num integer
);
create table managed_departments (
company_id integer not null,
dept_id integer not null,
manager_id integer not null,
foreign key (company_id, dept_id) references departments,
foreign key (manager_id) references employees (id),
primary key (company_id, dept_id)
);
create table department_staff (
company_id integer not null,
dept_id integer not null,
emp_id integer not null,
foreign key (company_id, dept_id) references managed_departments,
foreign key (emp_id) references employees (id),
primary key (company_id, dept_id, emp_id)
);
* 更新 *
架构翻译成 Laravel
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->timestamps();
});
Schema::create('departments', function (Blueprint $table) {
$table->increments('id');
$table->integer('company_id');
$table->string('name');
$table->timestamps();
$table->foreign('company_id')->references('id')->on('companies');
$table->unique(['company_id','name']);
});
Schema::create('employees', function (Blueprint $table) {
$table->increments('id');
$table->integer('company_id');
$table->string('name');
$table->timestamps();
$table->foreign('company_id')->references('id')->on('companies');
});
Schema::create('managed_departments', function (Blueprint $table) {
$table->integer('company_id');
$table->integer('department_id');
$table->integer('manager_id');
$table->timestamps();
$table->primary(['company_id','department_id']);
$table->foreign(['company_id','department_id'])
->references(['company_id','department_id'])
->on('departments');
$table->foreign(['company_id','manager_id'])
->references(['company_id','id'])
->on('employees');
});
Schema::create('department_staff', function (Blueprint $table) {
$table->integer('company_id');
$table->integer('department_id');
$table->integer('employee_id');
$table->timestamps();
$table->primary(['company_id','department_id', 'employee_id']);
$table->foreign(['company_id','department_id'])
->references(['company_id','department_id'])
->on('managed_departments');
$table->foreign(['company_id','employee_id'])
->references(['company_id','id'])
->on('employees');
});
【问题讨论】:
-
在手机上,所以只能发表评论,但您可以在 FK 列中允许
NULL值(不是很好的选择)或将 FK 留在Users中并为manager_id创建映射表来自Depts。 -
根据您的 RDBMS,您可以使外键不是约束,因此不强制存在 FK。但是您可能希望添加自己的检查以确保引用完整性。
-
@JRLambert,映射表也不一定强制引用完整性,例如dept_managers (user_id, dept_id) 仍然意味着我必须自己检查。就像在其中一个表上创建一个可为空的 FK 一样容易,但是是哪一个?
标签: database-design foreign-keys entity-relationship