2

假设我有一个任务和一个日志表:

tbl_tasks

Id     Name               ProjectId
-----------------------------------
1      Walk the dog       1
2      Check the mail     1 

tbl_log

Id     TaskId    CreatedDateTime 
--------------------------------
1      1         6/3/13 7:18am    
2      2         6/3/13 7:18am      
3      1         6/3/13 7:18am      

日志表应该是事件的永久记录。但是,当用户删除任务时,我遇到了一个完整性问题,我想到了几个解决方案。

1 . 不要在日志表中使用 TaskIn,而是使用任务名称。我不喜欢这种方法,但它是简单的解决方案。

tbl_log

Id     TaskName           Credits 
---------------------------------
1      Walk the dog       2      
2      Check the mail     1      
3      Walk the dog       2      

2 . 引入另一个表,使任务与项目具有 1:m 关系,但实际上它将是 1:1 并通过将 taskId 作为 pk(唯一约束)来强制执行。而不是删除任务,而是删除任务和项目之间的关系。我不喜欢这留下的所有垃圾,因为所有没有 FK 的任务都被切断了,我猜这将是大多数情况。

tbl_tasksInProject

TaskId     ProjectId    
-------------------
1          1               
2          1                     

处理这个问题的最佳做法是什么?

4

3 回答 3

2

老实说,在这两种解决方案中,我会选择保留任务名称。如果您只保留 ID,那么您将如何知道它指的是什么?

但是,作为第三个选项,为什么不在 tblTask​​s 中有一个名为 Deleted 的附加字段?当删除任务而不是实际删除记录时,可以将其设置为 true - 有效地进行软删除并维护您的关系?

于 2013-06-03T11:35:16.303 回答
0

使用“名称”和可以为空的 FK 为“tbl_tasks”创建第三个表。
然后让 tbl_log 引用第三个表。

因此,每当 tbl_tasks 的行被删除时,对这些行的引用就会变为 null(或将它们设置为默认的“不可删除”tbl_tasks 行)

于 2013-06-03T11:38:59.073 回答
0

我认为您采用的方法实际上取决于您的要求,而不是最佳实践。

即使在任务被删除后,您似乎也希望在日志表中保留相应的记录(这本身并不是很好的做法,保留没有引用的数据有什么意义?)。如果是这种情况,那么您最好进行软删除(此方法的优缺点已在此问题的前两个答案中讨论)。

即有一个名为“IsDeleted”的 BIT 列Tasks,而不是删除,您只需将该字段更新为 1。

此列的替代方法是使ProjectID可空,并更改外键上的引用操作触发器,如下所示:

ALTER TABLE tbl_tasks
ADD CONSTRAINT FK_tbl_Tasks_ProjectID FOREIGN KEY (ProjectID)
REFERENCES tbl_Projects (ID) ON DELETE SET NULL;

这样,如果一个项目被删除,那么任何关联任务中的 ProjectID 变为NULL,那么您就知道任何具有NULLProjectID 的任务已被“删除”。这意味着您不会失去对任务表的引用完整性。

或者,如果您不想要软删除方法并且不需要保留已删除任务的日志事件,您当然可以将删除从任务表级联到日志表:

ALTER TABLE tbl_log
ADD CONSTRAINT FK_tbl_log_TaskID FOREIGN KEY (TaskID)
REFERENCES tbl_tasks (ID) ON DELETE CASCADE;

总而言之,无论您选择哪种方式保持一致,要么删除所有数据(ON DELETE CASCADE),要么不删除所有数据(软删除),不要删除一半,并且不会出现引用完整性问题。

于 2013-06-03T11:50:35.793 回答