2010-09-02 3 views
2

Disons que j'ai une base de données similaire à ce qui suit:Comment gérer les données de mise à jour dans un schéma de base de données de relations un-à-plusieurs?

Table: People 

id | name | age 
---+------+----- 
1 | dave | 78 

Table: Likes 

id | userid | like 
---+--------+------- 
1 | 1 | apples 
---+--------+------- 
2 | 1 | oranges 
---+--------+------- 
3 | 1 | women 

Quelle serait la meilleure façon de gérer la mise à jour des données daves? À l'heure actuelle, je fais ce qui suit:

Update his age 
UPDATE People SET age = 79 WHERE id = 1; 

Update his likes 
DELETE FROM Likes WHERE userid = 1; 
INSERT INTO LIKES (userid, like) VALUES (1, 'new like'); 
INSERT INTO LIKES (userid, like) VALUES (1, 'another like'); 

supprimer toutes les données des utilisateurs de la table, puis readd leur nouveau genre de choses. Cela semble inefficace. Y a-t-il un meilleur moyen?

+0

Vous dites "Je supprime toutes les données des utilisateurs de la table, puis réintègre leurs nouvelles données." impliquant que vous ne connaissez que la liste complète des choses qu'ils aiment et non ce que votre DB détient. Sans interroger la base de données et comparer les listes, comment pouvez-vous savoir quoi supprimer? (c'est-à-dire des objets individuels que la personne n'aime pas). Si vous ne souhaitez pas effectuer de comparaison, la suppression de tous et l'insertion est une méthode valide. Assurez-vous simplement de reconstruire les index et de mettre à jour les statistiques de temps en temps, car ils seront fragmentés. – Tony

+1

C'est une mauvaise idée de stocker l'âge - beaucoup mieux de stocker la date de naissance. –

Répondre

0

Vous pouvez ajouter une nouvelle colonne à Likes en stockant l'âge réel. En faisant cela, vous obtenez une fonctionnalité d'histoire et vous pouvez déterminer ses goûts en demandant ceux qui ont l'âge le plus élevé comme:

SELECT * FROM Likes WHERE userid = 1 AND age = (SELECT MAX(age) FROM Likes WHERE userid = 79 GROUP BY userid); 

Lorsque vous voulez être en mesure de passer outre certains autres vous pourriez également ajouter une colonne « overriden_by » contenant le id du nouveau Like. Cela entraînerait une requête plus simple:

SELECT * FROM Likes WHERE userid = 1 and overriden_by is null; 
+0

Vous recommandez donc de ne pas supprimer les anciennes valeurs, mais de créer un moyen de reconnaître les dernières données de la table? Cela ne pourrait-il pas mener à une base de données potentiellement énorme? – dave

+0

Oui, vous avez raison. Cela conduira à remplir la base de données. Si vous n'avez pas besoin d'historique et que vous voulez garder la base de données petite, je ne recommanderais pas cette solution. Comment déterminez-vous ce que sont les nouveaux goûts? Est-ce que l'utilisateur l'entrera dans une interface graphique ou remplira-t-il quelque chose comme un formulaire qui sera traité plus tard? –

+0

L'ajout de 'AGE' à la table' LIKES' est une dénormalisation inutile. En outre, @ Chuck n'a pas exprimé le désir de maintenir une histoire de Likes, mais même s'ils avaient eu ce n'est pas la façon de le faire. – APC

1

Selon le SGBD, vous pouvez utiliser « Merge » « REMPLACER » « INSERT ou REPLACE », la plupart DBMSes prennent en charge cette fonctionnalité, mais la syntaxe varie énormément de sorte que vous devrez RTFM pour savoir comment faire cela avec la base de données que vous utilisez.

+0

Ceci est un kluj. MERGE est destiné à l'importation de données d'une table dans une autre table, par exemple dans un scénario ETL ou de migration de données. Étant donné que les données existent déjà dans notre tableau, notre application peut - ou devrait au moins être capable de - suivre quels enregistrements ont changé. – APC

+0

La fusion est également bonne pour ce type d'insertion ou de mise à jour (et avec DB2 c'est la seule façon d'accomplir cela en pur SQL!) –

2

Je ne comprends pas pourquoi vous suggérez un lien entre la mise à jour d'un enregistrement dans la table parent et ses dépendances dans la table enfant. Le point d'avoir des tables séparées est précisément que nous pouvons modifier les colonnes non clés dans People sans toucher Likes.

En ce qui concerne la mise à jour Likes, il existe deux transactions commerciales différentes. La première est quand Dave dit: «Je ne voulais pas dire 'oranges' je voulais dire que j'aime l'arrangement floral. Correction d'une erreur utiliserait une mise à jour:

update likes 
set like = 'flower arranging' 
where userid = 1 
and like = 'oranges' 
/

La clause WHERE peut utiliser la colonne LIKES.ID à la place.

L'autre cas est celui où les préférences ont réellement changé. C'est-à-dire, quand Dave dit «Maintenant, j'ai 79 ans, je n'aime plus les femmes, j'ai de nouveaux goûts». Cela peut ressembler à ceci:

delete from likes 
where userid = 1 
and like = 'women' 
/
insert into likes (userid, like) 
values (1, 'dominoes') 
/
insert into likes (userid, like) 
values (1, 'Werthers Orignals') 
/

La différence entre ces deux instructions est principalement celle de la clarté. Nous aurions pu mettre en œuvre la deuxième série de déclarations sous forme de mise à jour et d'insertion unique, mais cela serait trompeur. Garder la distinction entre des changements significatifs dans les données et corriger les erreurs est une discipline utile. Il est particulièrement utile lorsque nous conservons des enregistrements historiques et/ou des modifications d'audit.

Ce qui est définitivement une mauvaise idée est de supprimer tous les enregistrements Likes de Dave, puis de les réinsérer. Votre application devrait être capable de suivre quels enregistrements ont changé.

Questions connexes