views:

754

answers:

5

I am designing this database that must maintain a history of employee salary and the movements within the organization. Basically, my design has 3 tables (I mean, there more tables but for this question I'll mention 3, so bear with me). Employee table (containing the most current salary, position data, etc), SalaryHistory table (salary, date, reason, etc.) and MovementHistory(Title, Dept., comments). I'll be using Linq to Sql, so what I was thinking is that every time employee data is updated, the old values will be copied to their respective history tables. Is this a good approach? Should I just do it using Linq to SQL or triggers? Thanks for any help, suggestion or idea.

+5  A: 

It is a good idea to keep that logic internal to the database: that's basically why triggers exist. I say this carefully, however, as there are plenty of reasons to keep it external. Often times - especially with a technology as easy as LINQ-to-SQL - it is easier to write the code externally. In my experience, more people could write that logic in C#/LINQ than could do it correctly using a trigger.

Triggers are fast - they're compiled! However, they're very easy to misuse and make your logic overcomplex to a degree that performance can degrade rapidly. Considering how simple your use case is, I would opt to use triggers, but that's me personally.

Tony k
Thanks for your insights :)
jasonco
I think this is the approach I am going to use. I don't have a lot of experience with triggers. I mean, I am still learning linq to sql but I feel much more comfortable.
jasonco
I disagree with the "good idea" comment but not in the way you think. These rules should *always* be in the database to ensure that database clients follow them. The DB should be an entity unto itself, protecting its own data integrity, not relying on external parties. +1 anyway.
paxdiablo
Pax, I would definitely agree with you. However, it can never be a hard and fast rule. While there is a strong preference towards that sort of encapsulation, there are definitely times that the productivity can be more valuable. But again, I definitely agree with you that it's the correct option.
Tony k
Certainly if those rules will be in the database they should be documented so people don't end up enforcing the sames rules in the "external" code also. Thanks both of you for your replies.
jasonco
+2  A: 

Triggers will likely be faster, and don't require a "middle man" to get the job done, eliminating at least one chance for errors.

Depending on your database of choice, you can just use one table and enable OID's on it, and add two more columns, "flag" and "previous". Never update this table, only insert. Add a trigger so that when a row is added for employee #id, set all records with employee #id to have a flag of "old" and set the new rows "previous" value to the previous row.

Thanks for your comment!
jasonco
+6  A: 

Have a look at http://www.simple-talk.com/sql/database-administration/database-design-a-point-in-time-architecture .

Basically, the article suggests that you have the following columns in the tables you need to track history for -

* DateCreated – the actual date on which the given row was inserted.
* DateEffective – the date on which the given row became effective.
* DateEnd – the date on which the given row ceased to be effective.
* DateReplaced – the date on which the given row was replaced by another row.
* OperatorCode – the unique identifier of the person (or system) that created the row.

DateEffective and DateEnd together tell you the time for which the row was valid (or the time for which an employee was in a department, or the time for which he earned a particular salary).

sandesh247
Interesting link - good read, thanks!
ChristopheD
Cool, I already had a similar patter regarding the dates. Thanks for your post, very useful!
jasonco
+1  A: 

Triggers make your front-end easier to migrate to something else and they will keep the database consistent no matter how data is inserted/updated/removed.

Besides in your case I would write the salaries straight to the salary history - from your description I wouldn't see a reason why you should go the way via an update-trigger on the employee table.

PepperBob
That's the way I had it first but decided to use the history table just for history, nothing current. I mean, I am sure there quite a lot of ways to do it I am just kind of stuck looking for the right solution and there is no right solution! hehe thanks for your comment.
jasonco
+1  A: 

I think this belongs in the database for two reasons.

First, middle tiers come and go, but databases are forever. This year Java EJBs, next year .NET, the year after that something else. The data remains, in my experience.

Second, if the database is shared at all it should not have to rely on every application that uses it to know how to maintain its data integrity. I would consider this an example of encapsulation of the database. Why force knowledge and maintenance of the history on every client?

duffymo
Thanks, I'll consider this too.
jasonco