Rod*_*ton 5 sql sql-server constraints foreign-keys rowdeleting
我有一个SQL 2005表,里面有数百万行,整天都被用户点击.该表由20个左右的具有外键约束的表引用.我需要定期做的是删除此表中"Active"字段设置为false的所有记录,并且在引用父记录的任何子表中没有其他记录.如果没有尝试一次删除每个错误并让它导致违反约束的SQL错误,那么最有效的方法是什么?此外,它不是禁用约束的选项,并且我不能在任何大量时间内导致父表上的锁定.
如果未链接的非活动行不可能链接,则可以运行(甚至基于外键元数据动态构建):
SELECT k.*
FROM k WITH(NOLOCK)
WHERE k.Active = 0
AND NOT EXISTS (SELECT * FROM f_1 WITH(NOLOCK) WHERE f_1.fk = k.pk)
AND NOT EXISTS (SELECT * FROM f_2 WITH(NOLOCK) WHERE f_2.fk = k.pk)
...
AND NOT EXISTS (SELECT * FROM f_n WITH(NOLOCK) WHERE f_n.fk = k.pk)
Run Code Online (Sandbox Code Playgroud)
你可以很容易地把它变成DELETE.但是大型删除可能会占用大量锁,因此您可能希望将其放入表中然后批量删除 - 除非记录已链接,否则批处理不应该失败.
为了提高效率,您确实需要在相关表中的FK列上建立索引.
您也可以使用左连接执行此操作,但是您(有时)必须使用DISTINCT或GROUP BY进行重复数据删除,并且执行计划通常不会更好,并且它不利于代码生成:
SELECT k.*
FROM k WITH(NOLOCK)
LEFT JOIN f_1 WITH(NOLOCK) ON f_1.fk = k.pk
LEFT JOIN f_2 WITH(NOLOCK) ON f_2.fk = k.pk
...
LEFT JOIN f_n WITH(NOLOCK) ON f_n.fk = k.pk
WHERE k.Active = 0
AND f_1.fk IS NULL
AND f_2.fk IS NULL
...
AND f_n.fk IS NULL
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7100 次 |
| 最近记录: |