限制联结表中的相同行

时间:2016-02-08 08:26:54

标签: sql oracle

我有一个表(oracle数据库),我存储部门及其员工。

表: DepartmentEmployee

╔══════════════╦═══════════╦═════════════╦═══════════════════════════╗
║    Column    ║ Data type ║ Nullability ║        Description        ║
╠══════════════╬═══════════╬═════════════╬═══════════════════════════╣
║ DepartmentID ║ INT       ║ NOT NULL    ║ Foreign Key to Department ║
║ EmployeeID   ║ INT       ║ NOT NULL    ║ Foreign Key to Employee   ║
║ StartDate    ║ DATE      ║ NOT NULL    ║ Date the employee joined  ║
║ EndDate      ║ DATE      ║ NULL        ║ Date the employee left    ║
╚══════════════╩═══════════╩═════════════╩═══════════════════════════╝

员工应该只有一(1)个目前正在工作的部门。 他正在工作的部门没有EndDate(= NULL)。

所以查询将是:

  

SELECT *   来自DepartmentEmployee   WHERE EmployeeID = 1   AND EndDate IS NULL;

如果员工不再在公司工作,他将没有(0)部门使用EndDate。

所以我的问题是: 如何确保表中只有1行或0行的EndDate为EmployeeID设置为NULL? 感谢。

2 个答案:

答案 0 :(得分:1)

以下是一个选项:在没有结束日期的记录上创建唯一索引。这是一个包含CASE WHEN的功能索引。

create unique index idx_OnlyOneNoEndDate on DepartmentEmployee
(
  case when EndDate is null then EmployeeID end
);

当EndDate被填充时,两个表达式都为空,并且Oracle默认情况下不会在空值上创建索引条目,因此不会写入任何条目。但是,如果EndDate为null,那么我们为EmployeeID编写一个条目。如果插入了EndDate NULL员工的第二条记录,那么索引的唯一性就会变得暴力,我们会得到例外。

这也意味着您必须首先为现有记录编写EndDate,然后然后插入新记录。如果你反之亦然,你会得到例外。如果这对您来说是个问题,那么您应该能够通过在case when EndDate is null then EmployeeID end上创建虚拟列来绕过此问题,并在此列上创建可延迟的唯一索引。 (可延迟索引必须仅引用列。不幸的是,它们不能是功能索引。)

答案 1 :(得分:0)

您可以添加唯一索引,确保每个employeedId和endDate最多只有一条记录:

create unique index EmployeeEndDate on DepartmentEmployee
(
     employeeId,
     endDate
);