2015-11-09 67 views
2

我有一個employee和一個supervisor表。主管是一名僱員。該employee表看起來像這樣:是與主鍵(b,a)不同的主鍵(a,b)?

employee_id | employee_name 
1   | Freeman 
2   | Manfred 

supervisor表看起來像這樣(字段外鍵employee表):

supervisor_id | employee_id 
1    | 2 
2    | 1 

我實現了一個複合主鍵(supervisor_id,EMPLOYEE_ID)和並未阻止更新。

如何防止上述情況發生?員工不能監督他/她的主管。

+0

您需要爲表格添加一個約束。主鍵不能這樣工作 – Rob

+0

因此刪除複合主鍵? –

+0

@ F.Hall:您仍然需要某種主鍵,但它無法滿足您的所有需求。 – siride

回答

1

如果有需要在驗證失敗時要通知沒有用戶界面,使用觸發器siride的解決方案一個好的,戈登Linoff解決方案也將工作。一個更簡單的解決方案,也能夠通知用戶界面數據驗證失敗將是使用存儲過程更新表...如果沒有行被插入或1如果一個連續被插入

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。您可能會爭辯說,您可以將此答案與觸發器或約束條件結合使用,以確保驗證不會通過使用存儲過程以外的其他方法更新表來進行循環。

編輯:如果一個員工只能有一個主管,而不是有一個單獨的主管表,那麼您應該只在employee表中有一個supervisor_id列。擁有一個單獨的主管人表和複合關鍵字可以滿足多方關係,即主管人員監督多名僱員和擁有多名主管人員的僱員。

+0

但這允許一個員工擁有多個主管......我如何確保員工只有一個主管? –

+0

@ F.Hall我已經更新了答案,添加了一個子句,該子句將排除已經擁有主管的員工的插入。相應觸發器中的邏輯非常相似。 – Mick

+0

a監督b和b監督c,我如何防止c監督? –

0

當然是了。複合鍵意味着你的鑰匙是兩個值的組合。

配對a等於配對b僅當且僅當配對第一屬性等於配對b第一屬性且配對第二屬性等於配對b第二屬性時。

你需要的是一個良好的約束而不是主鍵。 並且讓我警告你,以防止如果pair(b,a)已經在表中的情況下阻止插入(a,b)對的約束將無法解決您的問題,因爲監督權關的過渡性。

我的意思是:讓我成爲b和b的主管監事。應該能夠成爲一名監督員嗎?

+0

沒有。 c不能監督一個。 –

2

純粹使用主鍵或檢查約束是不容易的。

  • 主鍵是唯一約束,它指定沒有行可以具有與任何其他行相同的主鍵。但並不是說某些組合是無效的。
  • 檢查約束可以使用更復雜的邏輯,但僅限於要插入的行中列的值。您的問題需要查看其他行。 (但請參閱Gordon Linoff的答案,即如何在約束下做到這一點 - 即使它有點不透明)。

解決方案是使用觸發器。觸發器可以檢查表中的其他行,以查看該員工是否已受到監督並取消該交易。

從這裏開始:https://msdn.microsoft.com/en-us/library/ms189799.aspx

1

您可以通過兩種方式做到這一點。一種是對值的排序施加檢查約束並使用唯一約束(或主鍵)。這將是:

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); 
0

我如何確保員工有一個且只有一個主管?

製作EMPLOYEE_ID在主管表的主鍵(非supervisor_id和僱員標識)。

相關問題