2010-09-22 6 views
3

Je suis curieux de savoir comment d'autres personnes ont géré cela. Imaginez un système qui a simplement des produits, des bons de commande et des lignes de commande d'achat. Les bons de commande sont les parents d'une relation parent-enfant avec les bons de commande. Lignes de commande d'achat, référence un seul produit.SQL Server Business Logic: Suppression des données référencées

Cela fonctionne jusqu'à ce que vous supprimiez un produit référencé par une ligne de commande d'achat. Soudainement, la Ligne sait vendre 30 de quelque chose ... mais elle ne sait pas quoi.

Quel est un bon moyen d'anticiper la suppression d'un élément de données référencé comme celui-ci? Je suppose que vous pourriez simplement interdire un produit à supprimer si des lignes de commande le référencent, mais cela semble ... maladroit. J'imagine qu'il est probable que vous conserviez le bon de commande dans la base de données pendant des années, essentiellement en soudant le produit que vous voulez supprimer dans votre base de données.

Répondre

3

Appliquer referential integrity. Cela signifie essentiellement créer des clés étrangères entre les tables et s'assurer que rien ne «disparaît»

Vous pouvez également utiliser cette fonction pour que les éléments référencés soient supprimés lorsque le parent est supprimé (suppression en cascade).

Par exemple, vous pouvez créer une table SQL Server de telle sorte que si PurchaseOrder est supprimé, son enfant PurchaseOrderLines est également supprimé.

Here is a good article qui va dans ce sens.

Il ne semble pas maladroit de conserver ces données (pour moi au moins). Si vous le supprimez, votre commande d'achat n'a plus la même signification que lorsque vous l'avez créée, ce qui est une mauvaise chose. Si vous craignez d'avoir de vieilles données, vous pouvez toujours créer une base de données d'archives ou d'entrepôt qui contient des données depuis plus d'un an ...

+2

Les clés étrangères correctes doivent certainement être créées, mais je ne suis pas un grand fan de l'utilisation des suppressions en cascade. Je préfère gérer cela dans mon propre code. –

+0

Intéressant, une raison particulière? –

+0

Probablement juste ma propre idiosyncrasie personnelle. Je n'aime pas les choses cachées qui se passent dans les coulisses de la DB. Et oui, je réalise que cela arrive tout le temps avec des déclencheurs, des colonnes calculées, etc. mais les suppressions en cascade me font mal. –

2

Pour des données comme celles-ci, certaines parties doivent être conservées pour un inconnu la quantité de temps tandis que d'autres parties ne seront pas, vous devez adopter une approche différente.

Votre table Lignes de commande d'achat (POL) doit contenir toutes les colonnes de la table des produits. Lorsqu'un élément de ligne est ajouté à la commande d'achat, copiez toutes les données du produit dans le POL. Cela inclut le nom, le prix, etc. Si le produit a des options, vous devrez créer une table PurchaseOrderLineOptions correspondante.

Ceci est le seul moyen de vous assurer que vous pouvez recréer le bon de commande à la demande à tout moment. Cela signifie également que quelqu'un peut modifier le prix, le nom, la description et d'autres informations sur le produit à tout moment sans que cela n'affecte les commandes précédentes. Oui, vous vous retrouvez avec BEAUCOUP d'informations en double dans votre tableau d'éléments de ligne. mais ça va.

Pour coups de pied, vous pouvez garder l'identifiant du produit dans le tableau POL pour le référencement de retour, mais vous ne pouvez pas dépendre de la table des produits pour avoir une incidence sur la prime pour le produit ...

+0

La raison d'avoir la clé étrangère dans la table des bons de commande était de référencer directement le produit et d'éviter les doublons. MAIS ce que vous dites a beaucoup de sens, je me sens mieux de l'entendre de quelqu'un d'autre, bien que la conservation de données de cette manière soit acceptable. – instantmusic

+0

Pour réduire les données en double, vous pouvez utiliser une table distincte pour stocker les produits achetés et avoir cette table 100% en lecture seule après l'insertion. Ensuite, vous pouvez vérifier si une ligne existe dans cette table avec toutes les données nécessaires avant d'en créer une nouvelle. Chris a raison de devoir divorcer les données du produit acheté de la table Produits actifs pour garantir la possibilité de recréer des factures à la demande. –

+0

Presque tous les systèmes de point de vente que j'ai vus utilisent cette façon de garder l'historique des commandes intact. – NotMe

4

L'entité mère ne devez JAMAIS être supprimé ou les lignes dépendantes cessent d'avoir du sens, sauf si vous les supprimez aussi. Bien qu'il soit "maladroit" d'afficher les anciens enregistrements aux utilisateurs en tant que sélections valides, il n'est pas évident que votre base de données continue à avoir du sens.Pour résoudre le problème du clunkiness dans l'interface utilisateur, certaines personnes créent une colonne inactive définie sur True lorsqu'un élément n'est plus actif, de sorte qu'il peut être conservé hors des listes déroulantes de l'interface utilisateur. Si la valeur est utilisée dans un champ d'affichage (par exemple un champ en lecture seule), la valeur inactive peut être dénommée d'une manière différente (par exemple, barrage) pour refléter son état de non-activation.

J'ai des colonnes StartDate et ExpiryDate dans toutes les tables d'entités où l'entité peut devenir inactive ou si l'entité deviendra active à un moment donné dans le futur (par exemple une remise promotionnelle).

+0

C'est une excellente idée en général, beaucoup de mes tables sont représentées dans mon application comme Combo Boxes pour la sélection. Je peux simplement ignorer les enregistrements inactifs lorsque je les remplis. Merci! – instantmusic

+0

exactement ce que nous faisons ici – DForck42

Questions connexes