2014-10-17 32 views
0

要求你如何強制執行SQL Server可以在2個表中的唯一

  1. 每個員工都有一個唯一的ID。 (EPID)
  2. 一個員工只能是以下任何一個,
    • FT - 全職
    • PT - 兼職
  3. 任何員工都可以永遠都FT和PT。
  4. FT & PT有很多不同的領域來捕捉。

實施

Create Table EmpFT(EPID int primary key, F1, F2, etc) 
Create Table EmpPT(EPID int primary key, P1, P2, etc) 
--This does not prevent same EPID on both EmpFT and EmpPT. 

如何實現數據庫3號?

我正在使用SQL Server 2012標準版。

+0

你應該只有一個表:'創建表EmpFT(EPID int主鍵,IsPTorFT,Col1,Col2等)' – Lamak 2014-10-17 15:04:22

+0

@Lamak,想到了它。但FT和PT有很多不同之處,將它們放在一張桌子上,最後留下很多空白區域。 – Rm558 2014-10-17 15:08:09

+1

@ Sam558然後這是一個3表解決方案。所有員工共用的字段都放在員工表中(EPID,姓名,SSN,僱傭關係等),以及與兼職或全職員工不同的事情進入他們各自的表格,這些表格鏈接到主員工表通過外鍵。 employee_pt(EPID,<兼職字段>)和employee_ft(EPID,<全職字段>) – Greenspark 2014-10-17 15:17:37

回答

4

試試這個方法:

CREATE TABLE Emp(EPID INT PRIMARY KEY, 
    t CHAR(2) NOT NULL, UNIQUE (EPID,t)); 

CREATE TABLE EmpFT(EPID INT PRIMARY KEY, ... other columns 
    t CHAR(2) NOT NULL CHECK (t = 'FT'), 
    FOREIGN KEY (EPID,t) REFERENCES Emp (EPID,t)); 

CREATE TABLE EmpPT(EPID INT PRIMARY KEY, ... other columns 
    t CHAR(2) NOT NULL CHECK (t = 'PT'), 
    FOREIGN KEY (EPID,t) REFERENCES Emp (EPID,t)); 
+0

很好的答案。爲了完整性,我只是在Emp.t('('FT','PT'))中添加一個檢查約束。 – TommCatt 2014-10-21 05:17:25

+0

當唯一性增長到超過2表時,這個答案優雅地縮放。 – Rm558 2014-10-21 23:06:45

0

您可以爲所有員工創建一個組合表。 FT和PT表可以將外鍵用於員工表。

+0

這並不妨礙相同的EPID被插入FT&PT。 – Rm558 2014-10-17 15:15:21

+0

您可以在僱員表上放置一個全職的布爾型字段,並在ft和pt表上插入觸發器,以防止插入在'employee.fulltime'爲false的ft表上或在'employee.fulltime'是真的。可能有一個更優雅的機制,然後觸發完成這一點,但我更習慣於通過前端,然後在數據庫本身接近這些問題。 – 2014-10-17 15:46:47

2

您可以添加檢查約束。事情是這樣的兩個表

ALTER TABLE EmpFT 
ADD CONSTRAINT chk_EmpFT_EPID CHECK (dbo.CHECK_EmpPT(EPID)= 0) 
ALTER TABLE EmpPT 
ADD CONSTRAINT chk_EmpPT_EPID CHECK (dbo.CHECK_EmpFT(EPID)= 0) 

及其功能如下所示:

CREATE FUNCTION CHECK_EmpFT(@EPID int) 
RETURNS int 
AS 
BEGIN 
DECLARE @ret int; 
SELECT @ret = count(*) FROM EmpFT WHERE @EPID = EmpFT.EPID 
RETURN @ret; 
END 
GO 


CREATE FUNCTION CHECK_EmpPT(@EPID int) 
RETURNS int 
AS 
BEGIN 
DECLARE @ret int; 
SELECT @ret = count(*) FROM EmpPT WHERE @EPID = EmpPT.EPID 
RETURN @ret; 
END 
GO 

進一步閱讀這裏:

+0

明白了:在這種情況下,子查詢是不允許的。只有標量表達式是允許的。 – Rm558 2014-10-17 15:37:52

+0

你是對的,忘記了他們需要被打成一個功能。我編輯了我的答案以表明它是如何完成的。 – ChrisStillwell 2014-10-17 15:55:06

+0

它的工作原理。大! – Rm558 2014-10-17 16:04:58

0

你不能有主鍵跨表。所以,一種方法是創建一個帶有適當約束的表employee。這可能看起來像這樣:

create table employee (
    EPID int not null identity(1, 1) primary key, 
    FTID int references empft(empftid), 
    PTID int references emppt(empptid), 
    CHECK (FTID is not null and PTID is null or FTID is null and PTID is not null), 
    UNIQUE (FTID), 
    UNIQUE (PTID) 
    . . . 
); 

create table empft (
    EmpFTId int not null identity(1, 1) primary key, 
    . . . 
); 

create table emppt (
    EmpPTId int not null identity(1, 1) primary key, 
    . . . 
); 

當然,如果您想要,也可以使用觸發器。

相關問題