假设我有一个任务和一个日志表:
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
处理此问题的最佳做法是什么?
答案 0 :(得分:2)
在这两个解决方案中,我要保持任务名称是诚实的。如果您只保留ID,那么您将如何知道它的含义?
作为第三个选项但是为什么在tblTasks中没有一个名为Deleted?的附加字段,当删除任务而不是实际删除记录时可以将其设置为true - 有效地进行软删除并维护你的关系? / p>
答案 1 :(得分:0)
使用“name”创建第三个表,并将“可空”FK创建为“tbl_tasks”。
然后让tbl_log引用第三个表。
因此,每当tbl_tasks的行被删除时,对这些行的引用就会变为空(或将它们设置为默认的“不可删除”tbl_tasks行)
答案 2 :(得分:0)
我认为您采取的方法实际上取决于您的要求,而不是最佳做法。
即使在删除任务之后,您仍希望将相应的记录保留在日志表中(这本身并不是很好的做法,保持数据没有任何意义的重点是什么?)。如果是这种情况,那么您可能最好进行软删除(这种方法的优点和缺点在this question的前两个答案中讨论过。)
即。在Tasks
中使用名为“IsDeleted”的BIT列,然后将该字段更新为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
,然后您就知道任何NULL
ProjectID已被“删除”的任务。这意味着您不会失去任务表的参照完整性。
或者,如果您不想使用软删除方法并且不需要保留已删除任务的日志事件,那么您可以将删除从任务表级联到日志表中:
ALTER TABLE tbl_log
ADD CONSTRAINT FK_tbl_log_TaskID FOREIGN KEY (TaskID)
REFERENCES tbl_tasks (ID) ON DELETE CASCADE;
总之,无论选择哪种方式都是一致的,要么删除所有数据(ON DELETE CASCADE),要么都不删除(软删除),不要删除一半,否则就不会出现参考完整性问题。