2014-08-27 3 views
0

나는 다음과 같은 SQL 테이블이 있습니다방지 사이클과 여러 캐스케이드 경로

create table dbo.Companies (
    Id int identity not null constraint primary key clustered (Id), 
); 

create table dbo.Workers (
    Id int identity not null constraint primary key clustered (Id), 
    CompanyId int not null, 
); 

create table dbo.Evaluations (
    Id int identity not null constraint primary key clustered (Id),  
    CompanyId int not null, 
    WorkerId int not null 
) 

그리고 다음과 같은 제약 조건 :

alter table dbo.Workers 
add constraint FK_Workers_CompanyId foreign key (CompanyId) references dbo.Companies(Id) on delete cascade on update cascade; 

alter table dbo.Evaluations 
add constraint FK_Evaluations_CompanyId foreign key (CompanyId) references dbo.Companies(Id) on delete cascade on update cascade, 
    constraint FK_Evaluations_WorkerId foreign key (WorkerId) references dbo.Workers(Id) on delete no action on update no action; 

내가 얻을 레코드를 삽입 할 때 내가 엔티티 프레임 워크를 사용 오전 오류 :

Additional information: Introducing FOREIGN KEY constraint 'FK_dbo.Workers_dbo.Companies_CompanyId' on table 'Workers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. 

데이터베이스 디자인을 변경해야합니까?

내 데이터베이스 이런 식으로 디자인 된 이유를 설명해 드리죠 :

1

이 - 노동자 테이블에있는 회사 ID는 노동자 는 현재 작동 회사를 표시합니다.

2 - 평가의 CompanyId는 평가가 이루어질 때 작업자가 근무한 위치를 나타냅니다 ... 그리고 WorkerId는 평가 된 작업자를 분명히 나타냅니다.

+0

계단식 설정에는 dbo.Companies의 dbo.Evalutations에 대한 두 개의 경로가 있습니다. 회사 관계로부터 노동자를 분리하는 디자인을 제안하고 타임 스탬프가 적용된 테이블에 이러한 관계를 기반으로하고 평가는 동일한 타임 스탬프가 적용된 테이블의 하위 클래스로 평가하여 "EventType"열을 평가 또는 작업에 대해 평가할 수 있습니다. 새 회사 및 주어진 평가 중 작업자가 작업 한 위치에 대한 뷰는 평가 전의 첫 번째 "변경"레코드로서 타임 스탬프 내림차순으로 정렬됩니다. CompanyID는 FK와 같이 타임 스탬프 테이블에 있어야합니다. –

+0

@JaazCole, 죄송 합니다만 타임 스탬프에 대한 귀하의 제안을 이해하지 못합니다. 코드 예제를 제공해 주시겠습니까? 이해하기 쉽습니다. 고맙습니다. –

답변

1

더 명시 나 모든이 말이하지만 어쩌면 내가 잘못

은 ... :

CREATE TABLE dbo.EventTypes (
     EID INT PRIMARY KEY IDENTITY(1,1) 
    , EventDescription VARCHAR(40) 
); 
INSERT INTO dbo.EventTypes (EventDescription) VALUES ('Hired'); 
INSERT INTO dbo.EventTypes (EventDescription) VALUES ('Evaluated'); 

이 사용하고 무슨 일이 있었는지 결정하기 위해 평가 될 것이라고는 경우 다음과 같습니다.

CREATE TABLE dbo.Companies (
     CID INT PRIMARY KEY IDENTITY(1,1) 
    /* ... */ 
); 
CREATE TABLE dbo.Workers (
     WID INT PRIMARY KEY IDENTITY(1,1) 
    /* ... */ 
); 

CREATE TABLE dbo.History (
     HistID INT PRIMARY KEY IDENTITY(1,1) 
    , TS DATETIME NOT NULL DEFAULT GETDATE() 
    , CompanyID INT NOT NULL FOREIGN KEY REFERENCES dbo.Companies(CID) ON UPDATE CASCADE ON DELETE CASCADE 
    , WorkerID INT NOT NULL FOREIGN KEY REFERENCES dbo.Workers(WID) ON UPDATE CASCADE ON DELETE CASCADE 
    , EventTypeID INT NOT NULL FOREIGN KEY REFERENCES dbo.EventTypes(EID) ON UPDATE CASCADE ON DELETE CASCADE 
    /* ...other generic history-traits... */ 
); 
CREATE NONCLUSTERED INDEX Idx_History_TS ON dbo.History (TS) INCLUDE (CompanyID, WorkerID, EventTypeID) WITH (FILLFACTOR = 90); 
CREATE NONCLUSTERED INDEX Idx_History_CompanyID ON dbo.History (CompanyID) WITH (FILLFACTOR = 90); 
CREATE NONCLUSTERED INDEX Idx_History_WorkerID ON dbo.History (WorkerID) WITH (FILLFACTOR = 90); 
CREATE NONCLUSTERED INDEX Idx_History_EventTypeID ON dbo.History (EventTypeID) WITH (FILLFACTOR = 90); 

여기에는 여러 가지 이벤트가 포함되어 있으며 원하는대로 이벤트를 하위 클래스로 분류 할 수 있습니다. 관련 EventDescription이 = '평가되는'때 코드는, 예를 들어, 여기에 볼 수 있었다 :

이 그냥 모델로 제공되었다
CREATE TABLE dbo.Evaluations (
     EvalID INT NOT NULL PRIMARY KEY FOREIGN KEY REFERENCES dbo.History(HistID) ON UPDATE CASCADE ON DELETE CASCADE 
    /* ...Eval columns... */ 
); 

CREATE TABLE dbo.EvaluationItems (
     ID INT PRIMARY KEY IDENTITY(1,1) 
    , EvalID INT NOT NULL FOREIGN KEY REFERENCES dbo.Evaluations (EvalID) 
    /* ...item details... */ 
); 
GO 

, 평가 항목 그렇게 될 필요가 없습니다.

다음, 가장 최근의 고용주 :

CREATE VIEW dbo.WorkersLastEmployer AS 
    SELECT W.*, C.* 
    FROM dbo.Workers W 
     INNER JOIN (
      SELECT H.HistID, H.TS, H.CompanyID, H.WorkerID, MAX(TS)OVER(PARTITION BY H.WorkerID) AS LastHired 
      FROM dbo.History H 
       INNER JOIN dbo.EventTypes E ON E.EID = H.EventTypeID 
      WHERE E.EventDescription = 'Hired' 
     ) Hi ON Hi.WorkerID = W.WID 
      AND Hi.TS = Hi.LastHired 
     INNER JOIN dbo.Companies C on C.CID = Hi.CompanyID 
GO 

그리고 회사 ID 이후

가 역사로 마이그레이션하고, 평가는 이제 직접 서브 클래스, 회사 Y에서 작업자 X의 평가에 대한이보기 :

CREATE VIEW dbo.WorkerEvalutations AS 
    SELECT E.*, W.*, C.* 
    FROM dbo.Evaluations E 
     INNER JOIN dbo.History H on E.EvalID = H.HistID 
     INNER JOIN dbo.Workers W on W.WID = H.WorkerID 
     INNER JOIN dbo.Companies C on C.CID = H.CompanyID 
GO 

이 구조체는 경고없이 실행되며보다 쉽게 ​​확장 할 수있는 프레임 워크를 제공합니다.