10
votes

Conception de la base de données: dépendance circulaire

Imaginez la base de données suivante:

Table 'Sociétés' a des champs ID, Nom et Flagship_Product_ID. Table 'Produits' a des champs ID, Nom et Company_id.

Une entreprise doit avoir un produit phare (relation 1: 1) et tous les produits ont une entreprise (1: N relation).

Lorsque vous utilisez un moteur de stockage tel que le myisme, il ne devrait y avoir aucun problème avec le scénario ci-dessus, mais lors de l'utilisation d'un moteur tel que InnoDB, des problèmes résultent lors de l'insertion de nouvelles données.

Quelle est une bonne solution, sauf indication d'une relation nulle pour l'insert initial?

Résumer, une entreprise doit avoir un produit phare .


1 commentaires

J'ai un problème très similaire bien que Innodb n'est pas un facteur. La dépendance circulaire dans le schéma est le problème.


7 Réponses :


2
votes

Je ne connais pas ce moteur de base de données, mais recherchez un moyen de suspendre temporairement les contrôles de cohérence des données ou l'intégrité référentielle lors de vos opérations d'insertion atomique et de mise à jour.


9 commentaires

Sur MySQL, c'est SET FORET_KEY_CHECKSS = 0 , mais est-ce le seul moyen?


Je suis sûr que c'est la route, si vous vous tenez à cette conception. Si vous ne l'avez fait que pendant la durée de l'opération, pourquoi serait-ce indésirable? Je pense que je sais ce qui vous dérange - vous voulez que ce soit plus propre. Malheureusement, je pense que ces bases de données relationnelles ne sont pas bonnes pour exprimer ce type de relation.


Certaines choses doivent être appliquées dans la couche d'application. :-)


Je pense que c'est mon seul choix alors, j'ai besoin de faire respecter cette relation et je ne trouve aucune autre solution. J'ai choisi celui-ci parce que c'est le seul qui me permet de conserver une relation sain de "drapeaux" où l'erreur de programme peut casser des choses.


Il n'y a rien d'esprit d'esprit ... en règle générale, si vous devez suspendre les chèques, votre modèle est cassé. Je ne dis pas que cela ne fonctionnera pas, mais une fois que vous avez suspendu le chèque de l'insert, rien ne forçant ce champ à régler à quoi que ce soit ... Vous avez les mêmes problèmes de programme que vous avez si vous définissez un drapeau dans votre Table de produit.


Vous restaurez les chèques à la fin de l'opération, échec si les données ne sont finalement cohérentes - et d'autres opérations de ce type continuent d'être cohérentes individuellement. Devrait être bien. RDBMS est un outil puissant, mais il n'aura pas de primitif propre pour chaque situation de niveau d'application. Vous pourriez simplement considérer cela une optimisation des sortes, enfoncées du niveau d'application.


C'est l'une de ces choses qui sont mieux faites dans le code de la demande. C'est un système très étrange qui configurerait la société et les produits dans une seule transaction! Le problème est que vous configurez une nouvelle entreprise et suspendez le chèque pour le faire. Ensuite, vous devez entrer et créer les produits immédiatement, avant de pouvoir associer le "produit phare". Tout le temps, vous devez laisser les règles dans un état suspendu.


Je suis d'accord, dans ce scénario, suspendre les chèques est une mauvaise idée. La suspension de l'intégrité ne doit être effectuée que pendant la durée de la transaction - non laissée ouverte. Dans ce cas, l'autorisation de NULLS serait beaucoup mieux.


C'est la pire chose à faire.



2
votes

Pourquoi ne pas mettre un champ de produit phare dans la table des produits en tant que booléen ... vous pouvez indexer cela et comprendre et avoir une jolie recherche rapide


1 commentaires

Un index n'a aucun impact sur les règles d'entreprise - qui ont voté pour cela ?!



5
votes

Vous allez devoir autoriser des nulls dans le produit phare_product ou reconsidérer comment vous modélisez cette situation. Envisager de mettre le produit phare comme un champ booléen sur le produit à la place. Ensuite, vous n'avez pas de dépendance circulaire. Ou avoir un champ de type_TYPE sur le produit pouvant avoir des valeurs telles que phares ou normales ou obsolètes ou autre. Bien sûr, vous devez faire respecter cela, mais dans le passé, j'ai trouvé une solution plus propre à ce type de problème.


11 commentaires

Vous pouvez facilement prendre cette étape plus loin et avoir une table de produit_attributes qui répertorie les attributs associés à un produit - dont l'un pourrait être «phare». Cela permet de multiples attributs si nécessaire.


Mais alors cela signifie qu'il pourrait y avoir plusieurs produits phares pour une entreprise, qui n'est pas souhaité.


Comme je l'ai dit, il doit être exécuté.


Comment diriez-vous-tu? Les contraintes de contrôle ne fonctionneront ni une clé unique.


Vous l'exécutez au niveau de l'application (ma préférence) ou avec des déclencheurs sur la table.


Mais c'est une relation simple pour modéliser - vérifier ma réponse pour un exemple. Le niveau d'application peut avoir des problèmes s'il s'agit d'une application de bureau.


@Rexem: C'est une solution valide mais comme indiqué qui n'applique pas qu'une entreprise a un produit phare, seulement qu'elle n'a pas de 2+.


@cletus: C'est une hypothèse incorrecte. La relation n'est que celle-là exister pour une entreprise lors de la définie.


Sinon, le premier produit ajouté pour une entreprise devra être connecté en tant que phare puis mis à jour lorsque le phare a été ajouté.


@Rexem: Vous pouvez appliquer avec une clé unique sur les champs Société_id et Flagship_Product. Mais je suis d'accord avec le clétus qu'il serait mieux appliqué au niveau de l'application.


@Jeff: Vous ne pouvez pas mettre une clé unique sur le Company_id et phare - alors vous avez besoin de valeurs phares différentes pour chaque société_id.



3
votes

Je recommande d'utiliser le modèle de données suivant:

entreprises

  • société_id pk

    Produits

    • produit_id (pk)
    • Société_id (FK)

      flagship_products

      • société_id (pk, fk)
      • produit_id (fk)

        Création d'une colonne phare dans la table ne garantira qu'un seul produit est le produit phare de la société donnée car:

        • Une clé unique sur la colonne phare nécessite que les valeurs soient différentes les unes des autres
        • Une contrainte de contrôle n'est qu'une liste de valeurs acceptables

13 commentaires

Ce modèle nécessite unique (société_id, produit_id) sur flagship_products , non? Donc, c'est fondamentalement une table de pivot 1: 1 (bizarre ...).


@strager: parce que le pc est société_id , vous ne pouvez avoir une seule entrée pour une entreprise - il n'y a pas besoin d'une clé unique sur produit_id


Comment puis-je Appliquer qu'une entreprise a un produit phare, alors?


@rexem, ah, vrai. @Liranuna, aucune idée. Cette solution n'applique qu'un ou aucun. Hmm...


La relation serait appliquée lorsqu'un utilisateur tente d'ajouter un produit indiqué comme le produit phare quand on existe déjà pour cette entreprise. La clé principale arrêterait les doublons de la valeur company_id .


@Remex, mais que l'ajout n'est pas appliquée. Vous pourriez avoir une entreprise sans produit phare. Ce n'est pas ce que veut @liranuna.


Et il vaut mieux assumer que tous les produits sont le système phare, sauf indication contraire? C'est ce que la valeur de la valeur défaillante fera, sans la capacité d'assurer une existence. Qu'en est-il des entreprises qui n'ont pas de produits?


Je m'attendrais à ce que le produit phare soit exposé / surligné dans l'application si elle est si importante.


C'est toujours une relation circulaire ... Vous venez d'ajouter une autre table au mélange.


Le tableau "Extra" applique la règle commerciale selon laquelle il ne peut y avoir qu'un seul produit phare pour une entreprise tout en permettant une entreprise d'être ajoutée sans produit existant. En venant de l'affiche qui a recommandé un index, pourquoi vous sentez-vous la nécessité de commenter quelque chose que vous savez rien?


@strager: En supposant que vous signiez société.flagship_product_id , oui - cette colonne devrait autoriser null lors de la création d'une entreprise compte tenu des règles de gestion. Mais ce serait mieux que d'avoir une colonne indicatrice dans la table Produits - En plus de la gaspillage, il n'y a aucun moyen d'appliquer la règle de produit phare.


Je suis tout à fait d'accord que cela oblige la relation 1-1, mais cela n'exige pas qu'il y ait un produit phare en premier lieu, ce qui doit être fait au niveau de l'application. Peu importe ce que vous faites, vous ne pouvez pas vous éloigner de la vérification de l'application!


N'AVEZ JAMAIS SAI N'AVAI N'A PAS - Avoir toute la validation que vous souhaitez dans l'application, mais le modèle de données ne doit pas compter sur la validation de l'application pour appliquer l'intégrité des données.



1
votes

Les seuls produits suffisamment puissants et suffisamment puissants pour faire face à de telles situations sont correctement des systèmes qui embrassent / implémentent le concept de mission multiple.

Il n'y a pas un seul système SQL joue dans cette ligue.

Modifier

Les systèmes SQL ont une vérification de contrainte différée, mais en utilisant cela peut devenir désordonné.


0 commentaires

0
votes

Voici un aperçu d'un travail possible. Je ne sais pas à quelle hauteur de l'échelle de Kudge que cela convient, mais c'est là-haut.

  • créer une base de données
  • Créer des clients et des tables de produits
  • Insérez un espace réservé ou une ligne "factice" dans chacun, configuré pour se référer mutuellement
  • établir des contraintes FK entre le Tables

    Par la suite, chaque fois qu'un client ou un produit est créé, si le produit / entreprise référencée correctement n'a pas encore été créé, vous initialisez le nouvel élément à pointer vers le PLACHOLDER DUMMY. Ensuite, vous entrez cet élément et vous avez terminé en mettant à jour la première entrée.

    La hausse est, vous avez une intégrité référentielle absolue une fois que votre routine d'initialisation de la base de données est terminée - et vous ne courez qu'une fois sous lesquelles des circonstances contrôlées très , regardez-la de près et assurez-vous que cela ne le fait pas. t échoue! Le non-inconvénient est que vous avez maintenant un article "supplémentaire" de chaque table encombrant votre système.


2 commentaires

Est-ce que c'est mieux que de laisser NULLS - NULL Être votre espace réservé réservé invisible?


Référencement d'une ligne mannequin ou d'espace réservé est une alternative standard (the?) À avoir une référence de clé étrangère nulle. C'est comme "null" = nous ne savons pas ce que c'est et "Placholder" = Nous savons que nous n'avons pas les données, et nous gérons de manière proactive la situation avec des données délibérément inscrites. L'inconvénient est que vous devez gérer / code délibérément pour l'espace réservé ... mais vous devriez alors faire la même chose avec NULLS aussi, alors pourquoi ne pas le rendre un peu plus évident ce qui se passe?



0
votes

Vous aurez besoin de casser le cycle par Referrant une de vos contraintes d'intégrité référentielle jusqu'à la fin de la transaction.

veuillez s'il vous plaît google pour "initialement différé différé".

(pas sûr si InnoDB soutient cela)


0 commentaires