Cela s'appelle Entité-Attribut-Valeur (parfois aussi des "paires nom-valeur") et c'est un cas classique de "cheville ronde dans un trou carré" quand les gens utilisent le modèle EAV dans une base de données relationnelle.
Voici une liste des raisons pour lesquelles vous ne devriez pas utiliser EAV:
- Vous ne pouvez pas utiliser les types de données. Peu importe que la valeur soit une date, un nombre ou de l'argent (décimal). Il sera toujours contraint de varchar. Cela peut aller d'un problème de performance mineur à un mal de ventre énorme (avez-vous déjà dû chasser une variation d'un cent dans un rapport de synthèse mensuel?).
- Vous ne pouvez pas (facilement) appliquer des contraintes. "Tout le monde doit avoir une hauteur comprise entre 0 et 3 mètres" ou "L'âge ne doit pas être nul et> = 0", par opposition à la ligne 1-2 que chacune de ces contraintes serait dans un système correctement modélisé.
- En relation avec ce qui précède, vous ne pouvez pas facilement garantir que vous obtenez les informations dont vous avez besoin pour chaque client (l’âge pourrait manquer à l’un, puis le suivant pourrait ne pas être à la hauteur, etc.). Vous pouvez le faire, mais c'est beaucoup plus difficile que ça
SELECT height, weight, age FROM Client where height is null or weight is null
.
- De nouveau liés, les données en double sont beaucoup plus difficiles à détecter (que se passe-t-il si elles vous donnent deux âges pour un client? Si vous supprimez les données, comme ci-dessous, vous obtiendrez deux lignes de résultats si vous avez un attribut doublé. Si un client a deux entrées distinctes pour deux attributs, vous obtiendrez quatre lignes de la requête ci-dessous).
- Vous ne pouvez même pas garantir la cohérence des noms d'attributs. "Age_yr" peut devenir "AGE_IN_YEARS" ou "age". (Certes, le problème est moins grave lorsque vous recevez un extrait que lorsque des personnes insèrent des données, mais quand même.)
- Toute sorte de requête non triviale est un désastre complet. Pour relationaliser un système EAV à trois attributs afin de pouvoir l'interroger de manière rationnelle, il faut trois jointures de la table EAV.
Comparer:
SELECT cID.ID AS [ID], cH.Value AS [Height], cW.Value AS [Weight], cA.Value AS [Age]
FROM (SELECT DISTINCT ID FROM Client) cID
LEFT OUTER JOIN
Client cW ON cID.ID = cW.ID AND cW.Metric = "Wt_kg"
LEFT OUTER JOIN
Client cH ON cID.ID = cH.ID AND cW.Metric = "Ht_cm"
LEFT OUTER JOIN
Client cA ON cID.ID = cA.ID AND cW.Metric = "Age_yr"
À:
SELECT c.ID, c.Ht_cm, c.Wt_kg, c.Age_yr
FROM Client c
Voici une liste (très courte) des cas où vous devriez utiliser EAV:
- Lorsqu'il n'y a absolument aucun moyen de le contourner et que vous devez prendre en charge des données sans schéma dans votre base de données.
- Lorsque vous avez juste besoin de stocker des "choses" et que vous ne vous attendez pas à en avoir besoin sous une forme plus structurée. Attention, le monstre a appelé "les exigences changeantes".
Je sais que je viens de passer tout ce message à expliquer en détail pourquoi EAV est une idée terrible dans la plupart des cas - mais il existe quelques cas où cela est nécessaire / inévitable. Cependant, la plupart du temps (y compris l'exemple ci-dessus), cela va être beaucoup plus compliqué que ça n'en vaut la peine. Si vous avez besoin d'une prise en charge étendue de la saisie de données de type EAV, vous devez envisager de les stocker dans un système de valeurs-clés, par exemple Hadoop / HBase, CouchDB, MongoDB, Cassandra, BerkeleyDB.
Entité Attribut Value (EAV)
Il est considéré comme un anti-modèle par beaucoup, y compris par moi.
Voici vos alternatives:
utiliser l' héritage de table de base de données
utiliser des données XML et des fonctions SQLXML
utiliser une base de données nosql, comme HBase
la source
Dans PostgreSQL, un module très utile pour gérer les structures EAV est le module supplémentaire
hstore
, disponible à partir de la version 8.4. Je cite le manuel:Depuis Postgres 9.2, il existe aussi le
json
type et une foule de fonctionnalités qui vont avec (la plupart d’entre elles ont été ajoutées avec 9.3 ).Postgres 9.4 ajoute le type de données (largement supérieur!) "JSON binaire"
jsonb
à la liste des options. Avec des options d'index avancées.la source
Si votre base de données utilise la structure EAV, il est possible d'interroger les données de différentes manières.
La réponse de @ Simon montre déjà comment effectuer une requête en utilisant plusieurs jointures.
Exemple de données utilisées:
Si vous utilisez un SGBDR ayant une
PIVOT
fonction ( SQL Server 2005+ / Oracle 11g + ), vous pouvez interroger les données de la manière suivante:Voir SQL Fiddle avec Demo
Si vous n'avez pas accès à une
PIVOT
fonction, vous pouvez utiliser une fonction d'agrégat avec uneCASE
instruction pour renvoyer les données:Voir SQL Fiddle avec Demo
Ces deux requêtes renverront des données dans le résultat:
la source
C'est drôle de voir comment le modèle EAV db est critiqué et même considéré comme un "anti-motif" par certains.
En ce qui me concerne, les principaux inconvénients sont:
Cependant, vous ne devez absolument pas écarter cette solution, et voici pourquoi:
la source