我有以下架构:
公司
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)
);
*更新*
Schema翻译成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');
});
答案 0 :(得分:1)
当你发现自己被绑在这样的结上时,你通常需要更多的桌子。
公司很容易。为了便于阅读,我几乎完全省略了id号。
create table companies (
company_name varchar(45) primary key
);
insert into companies values
('Vandelay, Inc'), ('Vertigenous, Inc');
将“部门”视为组织结构图中的部门。这不是全部故事。
create table departments (
company_name varchar(45) not null references companies,
dept_name varchar(30) not null,
primary key (company_name, dept_name)
);
insert into departments values
('Vandelay, Inc', 'Human resources'),
('Vertigenous, Inc', 'Personnel'),
('Vandelay, Inc', 'Information Technology'),
('Vertigenous, Inc', 'Information Systems');
公司需要一些员工。员工获得一个身份证号码,因为他们的名字在公司内部不一定是唯一的。
create table employees (
company_name varchar(45) not null references companies,
emp_id integer not null,
emp_name varchar(25) not null,
primary key (company_name, emp_id)
);
insert into employees values
('Vandelay, Inc', 1, 'Steven McGuire'),
('Vertigenous, Inc', 1, 'Michael McDonald'),
('Vandelay, Inc', 2, 'Rosalie Jimenez'),
('Vandelay, Inc', 3, 'Phil Roberson'),
('Vandelay, Inc', 4, 'Sylvester Davis');
现实世界中的部门(即组织结构图上的部门)有一名经理。重叠的外键约束保证了经理和部门属于同一家公司。
-- Assumes one current manager per department.
create table managed_departments (
company_name varchar(45) not null,
dept_name varchar(30) not null,
foreign key (company_name, dept_name) references departments,
manager_id integer not null,
foreign key (company_name, manager_id) references employees (company_name, emp_id),
primary key (company_name, dept_name)
);
insert into managed_departments values
('Vandelay, Inc', 'Human resources', 1),
('Vertigenous, Inc', 'Personnel', 1),
('Vandelay, Inc', 'Information Technology', 2);
要完成工作,请将员工分配到某个部门。同样,重叠的外键实现了业务需求 - 员工和管理的部门属于同一家公司。
create table department_staff (
company_name varchar(45) not null,
dept_name varchar(30) not null,
foreign key (company_name, dept_name) references managed_departments,
emp_id integer not null,
foreign key (company_name, emp_id) references employees,
primary key (company_name, dept_name, emp_id)
);
insert into department_staff values
('Vandelay, Inc', 'Human resources', 1),
('Vandelay, Inc', 'Information Technology', 2),
('Vandelay, Inc', 'Information Technology', 3),
('Vandelay, Inc', 'Information Technology', 4);
这允许员工“进入”多个部门,这在我的经验中实际上很常见。如果您希望每个员工只在一个部门“进入”,请为DDL添加一个约束“department_staff”。
unique (company_name, emp_id)