Implémentation d'un sous-type d'un sous-type dans un modèle de conception de type / sous-type avec des sous-classes mutuellement exclusives

20

introduction

Pour que cette question soit utile aux futurs lecteurs, j'utiliserai le modèle de données générique pour illustrer le problème auquel je suis confronté.

Notre modèle de données se compose de 3 entités, qui seront étiquetées comme A, Bet C. Afin de simplifier les choses, tous leurs attributs seront de inttype.

Entité Aa les attributs suivants: D, Eet X;

Entité Ba les attributs suivants: D, Eet Y;

L'entité Ca les attributs suivants: Det Z;

Étant donné que toutes les entités partagent un attribut commun D, j'ai décidé d'appliquer une conception de type / sous-type .

Important: les entités s'excluent mutuellement! Cela signifie que l'entité est soit A, soit B, soit C.

Problème:

Entités Aet Bont encore un autre attribut commun E, mais cet attribut n'est pas présent dans l'entité C.

Question:

Je voudrais utiliser la caractéristique décrite ci-dessus pour optimiser davantage ma conception, si possible.

Pour être honnête, je n'ai aucune idée de comment faire cela, ni par où commencer à essayer, d'où ce post.

AlwaysLearningNewStuff
la source

Réponses:

6

Dans la mesure où cette question est une continuation de Est-ce que mon implémentation du modèle de conception de type / sous-type (pour les sous-classes mutuellement exclusives) est correcte? , Qui lui - même est une continuation de Je ne sais pas comment transformer une entité variable dans la table relationnelle , je demande: ce que vous exactement essayez d'optimiser? Espace de rangement? Le modèle objet? Complexité des requêtes? Performances des requêtes? Il existe des compromis lors de l'optimisation d'un aspect par rapport à un autre, car vous ne pouvez pas optimiser tous les aspects en même temps.

Je suis entièrement d'accord avec les points de Remus concernant:

  • Il y a des avantages et des inconvénients à chaque approche (c.-à-d. Le facteur omniprésent "ça dépend"), et
  • La première priorité est l'efficacité du modèle de données (un modèle de données inefficace ne peut pas être corrigé par un code d'application propre et / ou efficace)

Cela dit, le choix auquel vous êtes confronté est entre les éléments suivants, classés par ordre de normalisation le plus faible à la plupart de normalisation:

  • promotion de la propriété Edans la table de type de base
  • le garder dans plusieurs tables de sous-types
  • normalisation Ecomplète vers une nouvelle table de sous-classe intermédiaire au même niveau que Ccelui-ci Aet Bsera directement des sous-classes de ( réponse de @ MDCCL )

Examinons chaque option:

Déplacer la propriété Evers la table de type de base

Avantages

  • Réduction de la complexité des requêtes pour les requêtes qui ont besoin Emais pas X, You Z.
  • Potentiellement plus efficace pour les requêtes qui ont besoin Emais pas X, You Z(en particulier les requêtes agrégées) en raison de l'absence de JOIN.
  • Possibilité de créer un index (D, E)(et si oui, potentiellement un index filtré sur (D, E)où EntityType <> C, si une telle condition est autorisée)

Les inconvénients

  • Impossible de marquer EcommeNOT NULL
  • Besoin supplémentaire CHECK CONSTRAINTsur la table de type de base pour s'assurer que E IS NULLlorsque EntityType = C(bien que ce ne soit pas un problème énorme)
  • Besoin d'éduquer les utilisateurs du modèle de données pour savoir pourquoi cela Edoit être NULL, et devrait même être ignoré complètement, lorsque EntityType = C.
  • Un peu moins efficace quand Eest un type de longueur fixe, et une grande partie des lignes sont pour EntityType de C(c. -à ne pas utiliser d' Eoù il est NULL), et ne pas utiliser soit l' SPARSEoption sur la colonne ou la compression des données sur l'index cluster
  • Potentiellement moins efficace pour les requêtes qui n'en ont pas besoin Ecar la présence de Edans la table de type de base augmentera la taille de chaque ligne, ce qui diminuera à son tour le nombre de lignes pouvant tenir sur une page de données. Mais cela dépend fortement du type de données exact de E, le FILLFACTOR, du nombre de lignes dans la table de type de base, etc.

Conserver la propriété Edans chaque table de sous-type

Avantages

  • Un modèle de données plus propre (c.-à-d. Ne pas avoir à se soucier d'éduquer les autres quant à la raison pour laquelle la colonne Edans la table de type de base ne doit pas être utilisée car "elle n'est vraiment pas là")
  • Ressemble probablement plus étroitement au modèle objet
  • Peut marquer la colonne comme NOT NULLs'il s'agissait d'une propriété obligatoire de l'entité
  • Pas besoin de supplément CHECK CONSTRAINTsur la table de type de base pour s'assurer que E IS NULLlorsque EntityType = C(bien que ce ne soit pas un gain énorme)

Les inconvénients

  • Requiert JOIN pour sous-type Table (s) pour obtenir cette propriété
  • Potentiellement légèrement moins efficace en cas de besoin E, en raison de JOIN, selon le nombre de lignes de A+ que Bvous avez par opposition au nombre de lignes C.
  • Un peu plus difficile / complexe pour les opérations qui traitent uniquement avec des entités Aet B(et non C ) comme étant du même "type". Bien sûr, vous pouvez résumer cela via une vue qui fait UNION ALLentre une SELECTdes tables JOINed pour Aet une autre SELECTdes tables JOINed pour B. Cela réduira la complexité des requêtes SELECT mais pas si utile pour les requêtes INSERTet UPDATE.
  • Selon les requêtes spécifiques et la fréquence à laquelle elles sont exécutées, cela pourrait être une inefficacité potentielle dans les cas où avoir un index sur (D, E)aiderait vraiment une ou plusieurs requêtes fréquemment utilisées, car elles ne peuvent pas être indexées ensemble.

Normaliser Evers la table intermédiaire entre la classe de base et A&B

(Veuillez noter que j'aime la réponse de @ MDCCL comme alternative viable, selon les circonstances. Ce qui suit n'est pas censé critiquer strictement cette approche, mais comme un moyen d'ajouter une certaine perspective - la mienne, bien sûr - en évaluant dans le même contexte que les deux options que j'avais déjà proposées. Cela permettra de clarifier plus facilement ce que je considère comme la différence relative entre la normalisation complète et l'approche actuelle de normalisation partielle.)

Avantages

  • le modèle de données est entièrement normalisé (il ne peut y avoir rien de mal en soi, étant donné que c'est ce que les SGBDR sont conçus pour faire)
  • complexité des requêtes réduite pour les requêtes nécessitant Aet B, mais pas C(c.-à-d. pas besoin de deux requêtes jointes via UNION ALL)

Les inconvénients

  • un peu plus d'espace occupé (le Bartableau duplique l'ID, et il y a une nouvelle colonne, BarTypeCode) [négligeable, mais quelque chose à savoir]
  • légère augmentation de la complexité des requêtes car un supplément JOINest nécessaire pour accéder à AouB
  • augmentation de la surface de verrouillage, principalement sur INSERT( DELETEpeut être gérée implicitement via le marquage des clés étrangères comme ON CASCADE DELETE) puisque la transaction sera maintenue ouverte un peu plus longtemps sur la table de la classe de base (c.-à-d. Foo) [négligeable, mais quelque chose à savoir]
  • aucune connaissance directe du type réel - Aou B- dans le tableau de la classe de base Foo; il ne sait de type Brqui peut être Aou B:

    Autrement dit, si vous devez effectuer des requêtes sur les informations de base générales mais que vous devez soit les classer par type d'entité, soit filtrer un ou plusieurs types d'entités, la table de la classe de base n'a pas suffisamment d'informations, auquel cas vous devez LEFT JOINla Bartable. Cela réduira également l'efficacité de l'indexation de la FooTypeCodecolonne.

  • aucune approche cohérente pour interagir avec A& Bvs C:

    Autrement dit, si chaque entité se rapporte directement à la table de classe de base de sorte qu'il n'y a qu'un seul JOIN pour obtenir l'entité complète, alors tout le monde peut acquérir plus rapidement et facilement une familiarité en termes de travail avec le modèle de données. Il y aura une approche commune des requêtes / procédures stockées qui les rend plus rapides à développer et moins susceptibles d'avoir des bogues. Une approche cohérente permet également d'ajouter plus rapidement et plus facilement de nouveaux sous-types à l'avenir.

  • potentiellement moins adaptable aux règles métier qui évoluent dans le temps:

    Cela signifie que les choses changent toujours et il est assez facile de passer Eà la table de classe de base si elle devient commune à tous les sous-types. Il est également assez facile de déplacer une propriété commune vers les sous-types si des changements dans la nature des entités en font un changement valable. Il est assez facile de diviser un sous-type en deux sous-types (il suffit de créer une autre SubTypeIDvaleur) ou de combiner deux ou plusieurs sous-types en un seul. Inversement, que se passerait- Eil si plus tard devenait une propriété commune à tous les sous-types? Ensuite, la couche intermédiaire de la Bartable n'aurait aucun sens et la complexité supplémentaire n'en valait pas la peine. Bien sûr, il est impossible de savoir si un tel changement se produirait dans 5 ou même 10 ans, donc le Bartableau n'est pas nécessairement, ni même très probablement, une mauvaise idée (c'est pourquoi j'ai dit " potentiellement moins adaptable"). Ce ne sont que des points à considérer; c'est un pari dans les deux sens.

  • regroupement potentiellement inapproprié:

    Cela signifie simplement que la Epropriété est partagée entre les types d'entité Aet Bne signifie pas cela Aet B doit être regroupée. Ce n'est pas parce que les choses «se ressemblent» (c'est-à-dire les mêmes propriétés) qu'elles sont identiques.

Sommaire

Tout comme pour décider si / quand dénormaliser, la meilleure façon d'aborder cette situation particulière dépend de considérer les aspects suivants de l'utilisation du modèle de données et de s'assurer que les avantages l'emportent sur les coûts:

  • combien de lignes vous aurez pour chaque EntityType (regardez au moins 5 ans plus tard, en supposant une croissance supérieure à la moyenne)
  • combien de Go chacune de ces tables (type de base et sous-types) sera-t-elle dans 5 ans?
  • quel type de données spécifique est une propriété E
  • est-ce une seule propriété ou y a-t-il quelques, voire plusieurs, propriétés
  • quelles requêtes dont vous aurez besoin Eet à quelle fréquence elles seront exécutées
  • les requêtes dont vous aurez besoin qui n'ont pas besoin Eet à quelle fréquence elles seront exécutées

Je pense que j'ai tendance à rester par défaut Edans les tables de sous-types séparées car c'est, à tout le moins, "plus propre". J'envisagerais de passer Eà la table de type de base IF: la plupart des lignes n'étaient pas pour EntityType de C; et le nombre de rangées était au moins dans les millions; et j'exécute plus souvent qu'autrement les requêtes qui ont besoin Eet / ou les requêtes qui bénéficieraient d'un index lors d' (D, E)une exécution très fréquente et / ou nécessitent suffisamment de ressources système de sorte que l'index réduit l'utilisation globale des ressources, ou du moins empêche des augmentations de la consommation des ressources qui dépassent les niveaux acceptables ou qui durent assez longtemps pour provoquer un blocage excessif et / ou une augmentation des blocages.


MISE À JOUR

OP a commenté cette réponse :

Mes employeurs ont changé la logique commerciale, supprimant complètement E!

Ce changement est particulièrement important car il est exactement ce que je prédites pourrait arriver dans le « Arnaques » du paragraphe « Normaliser Esur le tableau intermédiaire entre la classe de base et A& B» section ci - dessus (6e point). Le problème spécifique est à quel point il est facile / difficile de remanier le modèle de données lorsque de tels changements se produisent (et ils le font toujours). Certains diront que tout modèle de données peut être refactorisé / modifié, alors commencez par l'idéal. Mais s'il est vrai sur le plan technique que tout peut être refactorisé, la réalité de la situation est une question d'échelle.

Les ressources ne sont pas infinies, pas seulement CPU / Disque / RAM, mais aussi les ressources de développement: temps et argent. Les entreprises fixent constamment des priorités sur les projets car ces ressources sont très limitées. Et assez souvent (du moins d'après mon expérience), les projets visant à gagner en efficacité (même à la fois les performances du système ainsi que le développement plus rapide / moins de bugs) sont prioritaires en dessous des projets qui augmentent les fonctionnalités. Bien que cela soit frustrant pour nous, les techniciens, car nous comprenons les avantages à long terme des projets de refactoring, c'est juste la nature de l'entreprise que les gens d'affaires moins techniques ont plus de facilité à voir la relation directe entre les nouvelles fonctionnalités et les nouvelles. revenu. Cela se résume à: "nous reviendrons pour corriger cela plus tard" == "

Dans cet esprit, si la taille des données est suffisamment petite pour que des modifications puissent être apportées très requête, et / ou vous avez une fenêtre de maintenance qui est assez longue pour non seulement apporter les modifications mais aussi pour annuler si quelque chose se passe mal, puis normalisant Evers une table intermédiaire entre la table de classe de base et les A& Btables sous-classe pourrait fonctionner (bien que les feuilles de toujours vous sans connaissance directe du type spécifique ( AouB) dans la table de classe de base). MAIS, si vous avez des centaines de millions de lignes dans ces tables et une quantité incroyable de code référençant les tables (code qui doit être testé lorsque des modifications sont apportées), alors il est généralement plus pragmatique qu'idéaliste de payer. Et c'est l'environnement que j'ai dû gérer pendant des années: 987 millions de lignes et 615 Go dans la table de classe de base, répartis sur 18 serveurs. Et tellement de code a frappé ces tables (tables de classe de base et de sous-classe) qu'il y avait beaucoup de résistance - principalement de la direction mais parfois du reste de l'équipe - à apporter des changements en raison de la quantité de développement et Ressources d'AQ qui devraient être allouées.

Donc, encore une fois, la "meilleure" approche ne peut être déterminée que situation par situation: vous devez connaître votre système (c'est-à-dire la quantité de données et la façon dont les tables et le code sont tous liés), comment effectuer la refactorisation et les personnes avec qui vous travaillez (votre équipe et éventuellement la direction - pouvez-vous obtenir leur adhésion pour un tel projet?). Il y a quelques changements que je mentionnais et planifiais depuis 1 à 2 ans, et j'ai pris plusieurs sprints / versions pour obtenir peut-être 85% d'entre eux implémentés. Mais si vous n'avez que <1 million de lignes et pas beaucoup de code lié à ces tables, vous êtes probablement en mesure de commencer du côté le plus idéal / "pur" des choses.

N'oubliez pas, quelle que soit la voie que vous choisissez, faites attention au moins au fonctionnement de ce modèle au cours des 2 prochaines années (si possible). Faites attention à ce qui a fonctionné et à ce qui a causé la douleur, même si cela semblait être la plus grande idée de l'époque (ce qui signifie que vous devez également vous permettre d'accepter le vissage - nous le faisons tous - afin que vous puissiez évaluer honnêtement les points douloureux. ). Et faites attention aux raisons pour lesquelles certaines décisions ont fonctionné ou non afin que vous puissiez prendre des décisions qui sont plus susceptibles d'être "meilleures" la prochaine fois :-).

Solomon Rutzky
la source
17

Selon Martin Fowler, il existe 3 approches au problème de l'héritage de table:

  • Héritage de table unique : une table représente tous les types. Les attributs inutilisés sont NULL.
  • Héritage de table en béton : une table par type de béton, chaque colonne de table pour chaque attribut du type. Aucune relation entre les tables.
  • Héritage de table de classe : une table par type, chaque table a des attributs uniquement pour les nouveaux attributs non hérités. Les tableaux sont liés, reflétant la hiérarchie d'héritage de type réelle.

Vous pouvez commencer par ceux-ci comme point de départ pour rechercher les avantages et les inconvénients de chaque approche. L'essentiel est que toutes les approches ont des inconvénients majeurs, et aucune n'a un avantage écrasant. Plus connu sous le nom de non - correspondance d'impédance relationnelle des objets , ce problème n'a pas encore trouvé de solution.

Personnellement, je trouve que le type de problèmes qu'une mauvaise conception relationnelle peut entraîner sont des ordres de grandeur plus graves que le type de problèmes résultant d'une mauvaise conception de type . Une mauvaise conception de la base de données entraîne des requêtes lentes, des anomalies de mise à jour, une explosion de la taille des données, des blocages et des applications qui ne répondent pas, et des dizaines à des centaines de gigaoctets de données coulées dans le mauvais format . Une conception de type incorrecte conduit à maintenir et à mettre à jour le code , pas à l'exécution. Par conséquent, dans mon livre, la conception relationnelle correcte l' emporte sur la pureté de type OO encore et encore et encore.

Remus Rusanu
la source
@AlwaysLearningNewStuff Je pense que cette question fait suite à dba.stackexchange.com/questions/139092 , n'est -ce pas? Dans la mise en œuvre il vous faire avoir l' héritage de table.
Remus Rusanu
Oui, avant de poser cette question, je voulais m'assurer d'avoir bien compris comment implémenter la conception de type / sous-type en premier. Maintenant, je fais face au problème décrit ci-dessus lorsque certaines (mais pas toutes!) Sous-classes ont des attributs partagés. Je me demandais s'il y avait quelque chose que je pouvais faire pour optimiser le modèle de données dans ce cas, au lieu de négliger cette nuance ...
AlwaysLearningNewStuff
6

Selon mon interprétation de vos spécifications, vous souhaitez trouver une méthode pour implémenter deux structures supertype-sous-type différentes (mais connectées ) .

Afin d'exposer une approche pour réaliser la tâche susmentionnée, je vais ajouter au scénario en cause les deux types d'entités hypothétiques classiques appelés Fooand Bar, que je détaillerai ci-dessous.

Règles métier

Voici quelques déclarations qui m'aideront à créer un modèle logique:

  • A Foo is either one Bar or one C
  • A Foo is categorized by one FooType
  • A Bar is either one A or one C
  • A Bar is classified by one BarType

Modèle logique

Et puis, le modèle logique IDEF1X [1] résultant est illustré à la figure 1 (et vous pouvez également le télécharger depuis Dropbox au format PDF ):

Figure 1 - Modèle de données de relations hypothétiques de supertype-sous-type

L'ajout de Foo et Bar

Je n'ai pas ajouté Fooet Barpour rendre le modèle plus beau, mais pour le rendre plus expressif. Je considère qu'ils sont importants pour les raisons suivantes:

  • Comme Aet Bpartager l'attribut nommé E, cette fonctionnalité suggère qu'il s'agit de types de sous-entité d'un type distinct (mais lié) de concept , d' événement , de personne , de mesure , etc., que j'ai représenté au moyen du Bartype de superentité qui, à son tour, est un type de sous-entité de Foo, qui contient l' Dattribut en haut de la hiérarchie.

  • Puisqu'il Cne partage qu'un seul attribut avec le reste des types d'entités en discussion, c'est-à-dire que Dcet aspect insinue qu'il s'agit d'un type de sous-entité d'un autre type de concept , événement , personne , mesure , etc., j'ai donc décrit cette circonstance en vertu de le Footype super entité.

Cependant, ce ne sont que des hypothèses, et comme une base de données relationnelle est censée refléter avec précision la sémantique d'un certain contexte commercial , vous devez identifier et classer toutes les choses d'intérêt dans votre domaine spécifique afin que vous puissiez, précisément, capturer plus de sens .

Facteurs importants lors de la phase de conception

Il est très utile d'être conscient du fait que, en mettant toute la terminologie de côté, un cluster exclusif de supertype-sous-type est une relation ordinaire. Décrivons la situation de la manière suivante:

  • Chaque occurrence de type superentité exclusive est liée à un seul complément de type sous-entité .

Ainsi, il y a une correspondance (ou cardinalité) de un à un (1: 1) dans ces cas.

Comme vous le savez d'après vos publications précédentes, l' attribut discriminateur (colonne, lorsqu'il est implémenté) joue un rôle primordial lors de la création d'une association de cette nature, car il indique l'instance de sous-type correcte avec laquelle le supertype est connecté . La migration de la CLÉ PRIMAIRE de (i) le supertype vers (ii) les sous-types est également d'une importance primordiale.

Structure DDL en béton

Et puis j'ai écrit une structure DDL basée sur le modèle logique présenté ci-dessus:

CREATE TABLE FooType -- Look-up table.
(
    FooTypeCode     CHAR(2)  NOT NULL,
    Description     CHAR(90) NOT NULL, 
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_FooType             PRIMARY KEY (FooTypeCode),
    CONSTRAINT AK_FooType_Description UNIQUE      (Description)
);

CREATE TABLE Foo -- Supertype
(
    FooId           INT      NOT NULL, -- This PK migrates (1) to ‘Bar’ as ‘BarId’, (2) to ‘A’ as ‘AId’, (3) to ‘B’ as ‘BId’, and (4) to ‘C’ as ‘CId’.
    FooTypeCode     CHAR(2)  NOT NULL, -- Discriminator column.
    D               INT      NOT NULL, -- Column that applies to ‘Bar’ (and therefore to ‘A’ and ‘B’) and ‘C’.
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_Foo                 PRIMARY KEY (FooId),
    CONSTRAINT FK_from_Foo_to_FooType FOREIGN KEY (FooTypeCode)
        REFERENCES FooType (FooTypeCode)
);

CREATE TABLE BarType -- Look-up table.
(
    BarTypeCode CHAR(1)  NOT NULL,  
    Description CHAR(90) NOT NULL,  
    CONSTRAINT PK_BarType             PRIMARY KEY (BarTypeCode),
    CONSTRAINT AK_BarType_Description UNIQUE      (Description)
);

CREATE TABLE Bar -- Subtype of ‘Foo’.
(
    BarId       INT     NOT NULL, -- PK and FK.
    BarTypeCode CHAR(1) NOT NULL, -- Discriminator column. 
    E           INT     NOT NULL, -- Column that applies to ‘A’ and ‘B’.
    CONSTRAINT PK_Bar             PRIMARY KEY (BarId),
    CONSTRAINT FK_from_Bar_to_Foo FOREIGN KEY (BarId)
        REFERENCES Foo (FooId),
    CONSTRAINT FK_from_Bar_to_BarType FOREIGN KEY (BarTypeCode)
        REFERENCES BarType (BarTypeCode)    
);

CREATE TABLE A -- Subtype of ‘Bar’.
(
    AId INT NOT NULL, -- PK and FK.
    X   INT NOT NULL, -- Particular column.  
    CONSTRAINT PK_A             PRIMARY KEY (AId),
    CONSTRAINT FK_from_A_to_Bar FOREIGN KEY (AId)
        REFERENCES Bar (BarId)  
);

CREATE TABLE B -- (1) Subtype of ‘Bar’ and (2) supertype of ‘A’ and ‘B’.
(
    BId INT NOT NULL, -- PK and FK.
    Y   INT NOT NULL, -- Particular column.  
    CONSTRAINT PK_B             PRIMARY KEY (BId),
    CONSTRAINT FK_from_B_to_Bar FOREIGN KEY (BId)
        REFERENCES Bar (BarId)  
);

CREATE TABLE C -- Subtype of ‘Foo’.
(
    CId INT NOT NULL, -- PK and FK.
    Z   INT NOT NULL, -- Particular column.  
    CONSTRAINT PK_C             PRIMARY KEY (CId),
    CONSTRAINT FK_from_C_to_Foo FOREIGN KEY (FooId)
        REFERENCES Foo (FooId)  
);

Avec cette structure, vous évitez le stockage de marques NULL dans vos tables de base (ou relations ), ce qui introduirait une ambiguïté dans votre base de données.

Intégrité, cohérence et autres considérations

Une fois que vous implémentez votre base de données, vous devez vous assurer que (a) chaque ligne de supertype exclusive est toujours complétée par son homologue de sous-type correspondante et, à son tour, garantir que (b) cette ligne de sous-type est compatible avec la valeur contenue dans la colonne de discrimination de supertype . Par conséquent, il est assez pratique d'utiliser ACID TRANSACTIONSpour vous assurer que ces conditions sont remplies dans votre base de données.

Vous ne devez pas abandonner la solidité logique, l'auto-expressivité et la précision de votre base de données, ce sont des aspects qui rendent décidément votre base de données plus solide.

Les deux réponses précédemment publiées contiennent déjà des points pertinents qui méritent certainement d'être pris en compte lors de la conception, de la création et de la gestion de votre base de données et de ses programmes d'application.

Récupération de données via des définitions VIEW

Vous pouvez configurer certaines vues qui combinent des colonnes des différents groupes de supertype-sous-type , de sorte que vous pouvez récupérer les données à portée de main sans, par exemple, écrire les clauses JOIN nécessaires à chaque fois. De cette façon, vous pouvez sélectionner directement à partir de la VUE (une relation dérivée ou une table ) d'intérêt avec facilité.

Comme vous pouvez le voir, "Ted" Codd était, sans aucun doute, un génie. Les outils qu'il a légués sont assez solides et élégants et, bien sûr, bien intégrés les uns aux autres.

Ressources associées

Si vous souhaitez analyser une base de données étendue qui implique des relations supertype-sous-type, vous trouverez utile les réponses extraordinaires proposées par @PerformanceDBA aux questions de débordement de pile suivantes:


Remarque

1. La définition d'intégration pour la modélisation de l'information ( IDEF1X ) est une technique de modélisation de données hautement recommandable qui a été établie comme norme en décembre 1993 par le National Institute of Standards and Technology ( NIST ) des États-Unis . Il est solidement fondé sur (a) les premiers éléments théoriques rédigés par le Dr EF Codd; sur (b) la vue Entité-Relation des données, développée par le Dr PP Chen ; et aussi sur (c) la technique de conception de bases de données logiques, créée par Robert G. Brown. Il convient de noter que IDEF1X a été formalisé au moyen d'une logique de premier ordre.

MDCCL
la source
Mes employeurs ont changé la logique commerciale, supprimant Ecomplètement! La raison pour laquelle j'accepte la réponse de l' utilisateur srutzky est qu'il fournit de bons points qui m'aident à prendre la décision de choisir l'itinéraire le plus efficace. Sinon, j'accepterais votre réponse. J'ai voté votre réponse plus tôt. Merci encore!
AlwaysLearningNewStuff