2010-03-20 69 views
6

我有一个表中定义了员工关系的表。 即如何从包含自引用外键的表中删除所有数据

EmpID Name SeniorId 
----------------------- 
1   A  NULL 
2   B  1 
3   C  1 
4   D  3 

等等...

其中高级ID是外键,其主键表一样的是refrence列EMPID 我想清楚从这个表中的所有行,而不删除任何约束。我怎样才能做到这一点?

删除需要像执行该 4,3,2,1

我怎样才能做到这一点

编辑:

的Jhonny的答案是为我工作,但它的答案更有效率。

+0

这是很清楚的的Jhonny的是最有效和最好的答案,我只留矿为充当一个提醒,有时候我没有,因为我觉得我聪明。 – 2010-03-20 13:41:18

+0

@Larry。因为它会先更新所有行然后删除它们,因此应该效率更低。而不是直接删除。哪个操作更高效,循环或查询?请让我清楚。我不知道这两个 – 2010-03-20 13:43:57

+0

基于集合的命令的想法可能会比运行在一个循环内众多基于集合的命令,即使在后一种情况下每个命令的影响较少的行得更快。实际结果可能会有所不同,例如,表格索引或参考级别数量;你必须测试以确保你有真正的最佳状况。但是Jhonny的“看起来”更好,而且肯定会更清晰,更容易实施。 – 2010-03-20 13:49:28

回答

13

如果我失去了一些东西,我不知道,但也许你可以试试这个。

UPDATE employee SET SeniorID = NULL 
DELETE FROM employee 
+0

他自己。把事情简单化! :-) – PapillonUK 2014-04-10 23:31:35

1

在循环中,运行一个命令,删除所有具有未引用EmpID的行,直到剩下零行。有多种方式来编写内DELETE命令:

DELETE FROM employee WHERE EmpID NOT IN (SELECT SeniorID FROM employee) 

DELETE FROM employee e1 WHERE NOT EXISTS 
    (SELECT * FROM employee e2 WHERE e2.SeniorID = e.EmpID 

,并使用连接可能是第三个,但我不熟悉的SQL Server语法。

+0

@Larry:Thx回答。我认为这个答案只考虑两个级别的高级。 PLZ检查在DVK的回答我的评论更多细节 – 2010-03-20 13:41:40

+0

这就是为什么你必须做一个循环,直到没有剩下的行。但Jhonny的回答更好。 – 2010-03-20 13:43:43

1

一种解决方法是通过将“高级”关系拆分为单独的表来规范化。为了通用性,使第二个表“empID1 | empID2 | relationship_type”。除了这个,你需要在循环中做到这一点。一种方法是做到这一点:

declare @count int 
select @count=count(1) from table 
while (@count > 0) 
BEGIN 
    delete employee WHERE NOT EXISTS 
     (select 1 from employee 'e_senior' 
     where employee.EmpID=e_senior.SeniorID) 
    select @count=count(1) from table 
END 
+0

组织结构未定义,因此我们无法正常化。即使1名高级也可以有其高级等。即A的高级B,B的高级C,C的高级d等 – 2010-03-20 13:30:29

+0

我不知道我理解为什么不通过反正我加了第二种方法 – DVK 2010-03-20 13:31:47

2

试试这个

DELETE FROM employee; 
3

如果表是非常大的(数以百万计基数),而无需登录的DELETE交易,丢弃约束和TRUNCATEing并重新创建约束是远远最有效的方法。另外,如果在其他表中有外键(并且在这个特定的表设计中它看起来如此),那么在所有情况下也必须首先删除这些行。

规范化没有提及递归/层次/树关系,所以我相信在你回复DVK建议将它分解成它自己的表的时候,它是一个红色的鲱鱼 - 它当然可以对此表进行垂直分区并考虑是否可以利用这一点来获得我在下面列出的任何其他好处。正如DVK所暗示的,在这个特别的设计中,我经常看到一个单独的链接表来记录自我关系和其他类型的关系。这有很多好处:

  • 有很多很多上下,而不是多到一个(不常见,但可能很有用)
  • 跟踪不同类型的直接关系 - 经理,顾问,助理,工资审批,费用审批,技术报告,来 - 与关系和关系型表,而不是在员工表中的新列的行
  • 按部就班地进行,包括活动指标和有效的改变在时间上一致的方式层次结构(包括离职员工层次的历史)关系行上的日期 - 这只有在将关系归一化到其自己的表中时才是完全可能的
  • SeniorID中的NULL(实际上在任一ID上) - 这是避免错误逻辑的明显优势,但NULL通常会出现在视图中,无论如何您必须将关联表左连接到
  • 更好的专用索引策略 - 而不是添加SeniorID到你已经拥有员工的特定索引(尤其是关系类型的数量增长)

当然,与这种关系相关的信息越多,表明关系本身值得一张表(即它是在这个词的真正意义上的“关系”在关系数据库中使用 - 相关数据被存储在一个关系或表 - 与主键),从而为关系的正常形态可能会强烈地表明,关系表在employee表中创建而不是简单的外键关系。

好处还包括其简单的删除场景:

DELETE FROM EmployeeRelationships; 
DELETE FROM Employee; 

您会在这里对SO注意到一个引人注目的等效性接受的答案,因为,你的情况,没有高层关系的员工有一个NULL - 所以在那个答案海报首先设置NULL为消除关系,然后删除员工。

根据约束(EmpployeeRelationships通常能够被TRUNCATEd,因为它的主键通常是一个组合键而不是任何其他表中的外键),可能有适当的TRUNCATE用法。

相关问题