Supprimer tous les loggings qui n'ont pas de contraintes de key étrangère

J'ai une table SQL 2005 avec des millions de lignes qui sont touchées par les users toute la journée et toute la nuit. Cette table est référencée par 20 autres tables ayant des contraintes de key étrangère. Ce que je dois faire sur une base régulière est de supprimer tous les loggings de cette table où le champ "Actif" est défini sur false ET il n'y a aucun autre logging dans les tables enfant qui referencent l'logging parent. Quel est le moyen le plus efficace de le faire à court d'essayer de supprimer chacun à la fois et de le laisser provoquer des erreurs SQL sur ceux qui violent les contraintes? De plus, ce n'est pas une option pour désactiver les contraintes et je ne peux pas provoquer de verrous sur la table parent pendant un laps de time significatif.

S'il n'est pas probable que les lignes inactives qui ne sont pas liées soient liées, vous pouvez les exécuter (ou même les build dynamicment, en fonction des métadonnées de key étrangère):

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) 

Et vous pouvez le transformer en un DELETE assez facilement. Mais une grande suppression pourrait contenir beaucoup de verrous, donc vous pourriez vouloir mettre cela dans un tableau et ensuite supprimer en lots – un lot ne devrait pas échouer sauf si un logging est lié.

Pour que cela soit efficace, vous devez vraiment avoir des index sur les colonnes FK dans les tables liées.

Vous pouvez également le faire avec des jointures à gauche, mais vous devez parfois dé-doubler avec un DISTINCT ou un GROUP BY et le plan d'exécution n'est généralement pas meilleur et ce n'est pas aussi propice à la génération de code:

 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 

Laissez-nous nous avons une table parent avec le nom Parent et il a au champ " id " de tout type et un champ " Active " du type bit . Nous avons également une deuxième table Child avec son propre champ " id " et son champ " fk " qui est la reference au champ " id " de la table Parent . Ensuite, vous pouvez utiliser l'instruction suivante:

 DELETE Parent FROM Parent AS p LEFT OUTER JOIN Child AS c ON p.id=c.fk WHERE c.id IS NULL AND p.Active=0 

Un peu confus à propos de votre question. Mais vous pouvez faire un LeftOuterJoin de votre table principale, à une table qu'il devrait avoir une key étrangère. Vous pouvez ensuite utiliser une instruction Where pour vérifier les valeurs NULL dans la table de connection.

Cochez ici pour les jointures externes: http://en.wikipedia.org/wiki/Join_%28SQL%29#Left_outer_join

Vous devriez également écrire des triggersurs pour faire tout cela pour vous quand un logging est supprimé ou mis à faux etc.