回答

收藏

删除所有没有外键约束的记录

技术问答 技术问答 97 人阅读 | 0 人回复 | 2023-09-12

我有一个SQL
4 ]; B9 U# e2 L. U2005年,有数百万行,整夜被用户击中。大约有20个其他具有外部键约束的手表被引用。我需要定期执行的操作是从此表中删除所有记录,其中活动字段设置为false,在任何引用父记录的子表中都没有其他记录。最有效的方法是什么?试着删除每一个错误,让它违反约束SQL错误吗?同样,禁用约束不是一种选择,并且我不能在任何可观的时间内导致对父表的锁定。
% a7 K3 V- Q/ f3 r/ }                                                               
$ t/ o8 o9 w" k& f    解决方案:                                                               
) s4 B# u% T# B: W( v                                                                如果未链接的非活动行不太可能链接,则可以运行(或根据外键元数据动态构建):
/ ]6 ~0 b) b- F  j' v1 gSELECT k.*FROM k WITH(NOLOCK)WHERE k.Active = 0AND 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)你可以很容易地把它转换成DELETE。但是,大的删除操作可能会持有很多锁,所以你可能想把它放在桌子上,分批删除-批处理不应失败,除非链接记录。* D7 e0 t" j+ c; P& z; h
为了使这种方法有效,您确实需要在相关表中FK列出索引。
. O4 F* @) C  ?' N, {% ~/ F您也可以使用左连接来执行此操作,但(有时)您必须(有时)使用它DISTINCT或GROUP
" S# ~! S  d1 r2 W& U; V7 O9 v- ]BY重复数据删除,实施计划通常不是更好,不利于代码生成:
/ g- W9 o* n& h5 y. V; `+ wSELECT k.*FROM k WITH(NOLOCK)LEFT JOIN f_1 WITH(NOLOCK) ON f_1.fk = k.pkLEFT JOIN f_2 WITH(NOLOCK) ON f_2.fk = k.pk...LEFT JOIN f_n WITH(NOLOCK) ON f_n.fk = k.pkWHERE k.Active = 0    AND f_1.fk IS NULL    AND f_2.fk IS NULL    ...    AND f_n.fk IS NULL
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则