7

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 say I have contact James and he is the first one. His id is 0. I add Mary and her id is 1. If I delete James, how can Mary's id be set to 0 instead of staying 1? It has to reset since she is the first one now. In other words, how can I reset all of the IDs in the database when someone gets deleted? Thanks

4

10 回答 10

17

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...

于 2009-03-19T17:56:05.903 回答
6

That's 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 T-SQL 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 order they were added?

You need to re-think your design.

于 2009-03-19T17:52:08.723 回答
5

That's not how IDs work, and not how they should work. The ID should never change, or all the linked information would point to the wrong row.

Instead, why not add a "External_ID" column that you control? Or number them dynamically in your query (with a computed column?)

于 2009-03-19T17:53:04.587 回答
4

The ID is the unique identifier of the row.

It can be used to link a row to another row in another table. The absence of ID holds information in itself as well, as it would clearly say that it was deleted. Starting to recycle ID numbers defeats completely the purpose of having a unique identifier, and doesn't make any sense really. Once an ID is assigned to a row, you must not arbitrarily change it.

Imagine for a second that when someone dies, they hand over his social insurance number (ID) to someone else. That will result in transferring all the old information that was linked to the dead person's social insurance number to that new person, which doesn't make any sense. Same happens with IDs, if an ID is reassigned, it'll be inheriting any old data that was previously linked to it.

于 2009-03-19T18:01:49.883 回答
4

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.

于 2009-03-20T14:24:10.180 回答
3

This would be much better solved using another method than renumbering the identity column each time a row is deleted.

Hard to say exactly what else you would do without knowing why your application has this need, but the fact that your application needs this functionality is probably indicative of a design problem somewhere.

于 2009-03-19T17:57:15.713 回答
2

You're using id's as more than just an identifier. If that's the case, you won't be able to use an auto increment field. You'll need to handle this in your code.

于 2009-03-19T17:52:23.370 回答
1

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.

于 2009-06-01T21:23:11.070 回答
0

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! :)

于 2009-05-22T17:34:54.827 回答
0

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

于 2009-06-26T20:26:46.213 回答