views:

44

answers:

3

Lets say I have a database similar to the following:

Table: People

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

Table: Likes

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

What would be the best way to handle updating daves data? Currently, I do the following:

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');

I delete all the users data from the table and then readd their new stuff. This seems inefficient. Is there a better way?

A: 

You could add a new column to Likes storing the actual age. By doing this you get a history funtionality and you can determine his likes by requesting those with the highest age like:

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

When you want be able to override some Likes you also could add another column "overriden_by" containing the id of the new Like. This would result in a simpler query:

SELECT * FROM Likes WHERE userid = 1 and overriden_by is null;
coding.mof
So you recommend not to delete old values but to create a way to recognise the newest data in the table? Could that not lead to a, potentially, huge database?
chuck
Yes, your are right. It will lead to filling up the database. If you don't need any history and want to keep the database small I wouldn't recommend this solution. How do you determine what the new likes are? Does the user enter it into a GUI or will he fill up something like a form which is processed later?
coding.mof
Adding `AGE` to the `LIKES` table is a pointless denormalisation. Furthermore,@Chuck has not expressed a desire to maintain a history of Likes, but even if they had this is not the way to do it.
APC
+1  A: 

Depending on the DBMS you could use "MERGE" "REPLACE" "INSERT OR REPLACE", most DBMSes support this functionality but the syntax varies wildly so you will need to RTFM to find out how do do this with the databse you are using.

James Anderson
This is a kluj. MERGE is intended for importing data from one table into another table, for instance in an ETL or data migration scenario. Given that the data already exists in our table, our application can - or at least ought to be able to - track which records have changed.
APC
Merge is also good for this type of insert or update ( and with DB2 its the only way to accomplish this in pure SQL!)
James Anderson
+2  A: 

It's not clear to me why you are suggesting a link between updating a record in the parent table and its dependents in the child table. The point of having separate tables is precisely that we can modify the non-key columns in People without touching Likes.

When it comes to updating Likes there are two different business transactions. The first is when Dave says, "I didn't mean 'oranges' I meant to say I like flower arranging". Correcting a mistake would use an update:

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

The WHERE clause could use the LIKES.ID column instead.

The other case is where the preferences have actually changed. That is, when Dave says "Now I'm 79 I don't like women any more. I have new tastes.". This might look like this:

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')
/

The difference between these two statements is primarily one of clarity. We could have implemented the second set of statements as an update and a single insert but that would be misleading. Keeping the distinction between meaningful changes to the data and correcting mistakes is a useful discipline. It is especially helpful when we are keeping historical records and/or auditing changes.

What is definitely a bad idea is deleting all Dave's Likes records and then re-inserting them. Your application should be able to track which records have changed.

APC