You can also store history directly in your table. You add an activedate and an inactivedate column. If you don't care about the time of the insert or change, then use a date column instead of datetime.
If this is done on an existing sytem, tou change the name of the table. You write a view that shows only those records currently active and name it what the old table used to be called (so all the old code doesn't break).
If this is a new system, create the table with the columns mentioned above and still write a view that gets only the active records. This will enable your developers to consistently use the active view so they don't forget to filter the records when they want to show the data as it stands right now.
You will have to change how you would normally do your update record process (I'd do this in an instead of trigger) so that when a record is updated, it puts in the inactive date in the current record and adds a new one. Do the same with a delete using an instead of trigger to inactivate the record rather than deleting it. If this is anew process, you could skip teh triggers and simply write updates that do the same thing and updates to the inactive date filed when you want to delte. However, I find the triggers are morerelaible in terms of ensuring data integrity. I would personally do the instead of triggers and tehn let developers write normal updates and deletes in the user interface. This would ensure that all chagnes are properly handled whether they came from the GUI or from an adhoc update in SSMS.
Then you write a stored proc with a dateparameter to return the data active on the date input (you may need some special code to handle if a date input was earlier that the data you started doing this), then use this in the GUI form for the user to see the data as of a certain date.