I am making an SQL database that stores contacts. I want to be able to delete contacts, and the correct id for each contact is crucial for my software connecting to it. Lets
This is such a bad idea in so many ways. I am debating if I should show you how to do this. There should never be a reason to change a row's identity once it's set.
If there is you are probably using the wrong field as your PK identifier. I am making an assumption here that you're talking about your PK field which is also an identity column.
Keep in mind if you create any tables which link to your contact table and you start changing your Id you need to update all those tables as well. Which will get expensive...
It makes no sense to do this on an auto-incrementing primary key column, as even if it was trivial to do, without mass updates in related tables you affect your data integrity. To do so you would likely need to drop the index and primary key constraint from the column (at which point your application may flake out), renumber all later records, renumber all related tables, then re-apply the primary key constraint and index.
If you really must have some form of linear identifier which always starts at 0 (this may then indicate a problem with the software design) then you can have a secondary ID column in addition to the primary key, which you then update to shuffle higher values down a rung with a statement such as:
UPDATE table
SET secondaryID = secondaryID - 1
WHERE secondaryID > (SELECT secondaryID FROM table WHERE primaryID = [id to delete]);
DELETE FROM table
WHERE primaryID = [id to delete];
I strongly discourage such a practice - if your IDs are 'missing' values because of deleted records, the software should test for existence of these values rather than just wigging out.
I wrote an application to handle a multi-level sales program. Of course, people drop out. In ours, people had to be inserted as well.
You're on the right track with one modification.
The identity number (ID) and the sequence number (seq) are two different things. They have no relationship with each other at all.
Never change an ID. Once assigned, always assigned.
Create a column (cNEXT) in your table for the sequence and populate it with IDs. "What ID is to be the next one in this sequence?"
Shuffle the IDs in cNEXT around, reassigning cNEXT, any time you want. Any stored proc can do that.
Then you also have the flexibility to create non-sequential chains of IDs. This is useful when people move to different regions or get promotions to different groups.
Hope this helps! :)
A 1 minute google search gave me a page that I can't display. Google this and it'll be your first link as of 6/1/2009: tsql fix "identity column"
Essentially, I would suggest adding a foreign key constraint between all of your relational fields to the ID field in question prior to doing any renumbering (which is also a horrible idea if there are any relationships whatsoever, strictly because if you are asking this question, you will have a heck of a time).
If your contacts table is your ONLY table or has ZERO relationships based on this ID field, you could set the Identity property to NO, renumber the values from 1 to COUNT(ID), then set the Identity property to YES, and reseed the identity for completion using:
DECLARE @MaxID INT
SELECT @MaxID = COUNT(ID) FROM TableID
DBCC CHECKIDENT('TableID', RESEED, @MaxID)
In this scenario, you could use the above reseed script after each set of deletions (but change COUNT(ID) to MAX(ID) once everything is initially and correctly set up, this adds a little speed as the table gets larger), prior to any additional inserts or foreign key constraint updates. Ensure you use TRANSACTIONS wrapped around the deletes and reseeding blocks, and ensure the table only allows synchronous transactions, this will prevent any data hosing in the middle of the reseeds.
Complex eh? That's why it's best to start out on the right foot. ;) (I learned this from experience) E-mail me at mraarone et yahoo d0t com if you have any more questions.
All the answers are assuming this is a production environment. If your testing a database design, then want to quickly truncate all the tables there should be an easy way to accomplish this:
DBCC CHECKIDENT({table name}, reseed, 0)
*Delete all rows from all tables using the id first
Thats is going to get real slow once you have more than a trivial amount of records in the database. The identity column will not work for you, you need to do some custom tsql to keep changing all the numbers - but a very bad idea, imo.
Why not use a date/time stamp if you need to keep track of the ordered they were added.
You need to re-think your design.