主键(a,b)是否与主键(b,a)不同?

时间:2015-11-09 02:53:41

标签: sql sql-server primary-key

我有一个employee和一个supervisor表。主管是员工。 employee表如下所示:

employee_id | employee_name
1           | Freeman
2           | Manfred

supervisor表看起来像这样(字段是employee表的外键):

supervisor_id | employee_id
1             | 2
2             | 1

我实现了一个复合主键(supervisor_id,employee_id)并且没有阻止更新。

如何防止上述情况发生?员工不能监督他/她的主管。

5 个答案:

答案 0 :(得分:3)

纯粹使用主键或检查约束这是不可能的。

  • 主键是唯一约束,指定没有行可以与任何其他行具有相同的主键。但它没有说某些组合是无效的。
  • 检查约束可以使用更复杂的逻辑,但只涉及要插入的行中列的值。您的问题需要查看其他行。 (但请参阅Gordon Linoff关于如何通过约束来做到这一点的答案 - 即使它有点不透明)。

解决方案是使用触发器。触发器可以检查表中的其他行,以查看员工是否已被监督并取消交易。

从这里开始:https://msdn.microsoft.com/en-us/library/ms189799.aspx

答案 1 :(得分:2)

您可以通过多种方式完成此操作。一种是对值的排序施加检查约束并使用唯一约束(或主键)。这将是:

alter table supervisor add constraint chk_supervisor_employee check (supervisor_id < employee_id);

这会创建功能。但它并没有在语义上做你想做的事情。相反,您可以添加列以获得最小和最大,然后添加唯一约束:

alter table supervisor add minse (case when supervisor_id < employee_id then supervisor_id else employee_id end);
alter table supervisor add maxse (case when supervisor_id < employee_id then employee_id else supervisor_id end);
alter table supervisor add constraint unq_supervisor_employee unique(minse, maxse);

答案 2 :(得分:2)

如果没有需要通知的用户界面,那么验证失败的事件,使用触发器的siride解决方案是一个很好的解决方案,Gordon Linoff解决方案也可以。一个更简单的解决方案,也可以通知用户界面数据验证失败将是使用存储过程更新表....

CREATE PROCEDURE AddSupervisor
(
   @supervisor_id int,
   @employee_id
)
AS
    INSERT INTO supervisor
    SELECT @supervisor_ID, @employee_id
    WHERE
    NOT EXISTS
    (
        SELECT 1 FROM supervisor
        WHERE
            supervisor_id = @employee_id AND
            employee_id = @supervisor_id
    ) AND NOT EXISTS  -- EDIT - Add logic to stop inserts for employees who already have a supervisor
    (
        SELECT 1 FROM supervisor
        WHERE
            employee_id = @employee_id
    )

    SELECT @@ROWCOUNT

如果没有插入行,最后选择@@ ROWCOUNT将返回0,如果插入了行,则返回1。您可能会争辩说,您可以将此答案与触发器或约束相结合,以确保通过使用除存储过程之外的其他内容来更新表来验证验证。

编辑:如果一个员工只能拥有一个主管,而不是拥有一个单独的主管表,那么您应该在employee表中有一个supervisor_id列。拥有一个单独的Supervisor表和一个复合键可以满足多对多的关系,即监督多个员工和有多个监督员的员工。

答案 3 :(得分:0)

当然是。复合键表示您的键是两个值的对。

当a且仅当第一个属性对等于第一个属性对而第二个属性等于第二个属性时,对a等于对b。

您需要的是一个井约束而不是主键。 如果对(b,a)已经在表格中,那么阻止插入(a,b)对的约束将不会解决你的问题,因为监督的传递可以解决你的问题,让我警告你。

我的意思是:让a成为b的b和b的主管。应该能成为一个?

的主管

答案 4 :(得分:0)

  

我如何确保员工只有一名主管?

使employee_id成为主管表中的主键(不是supervisor_id和employee_id)。