Entering data at a specific ID where as Auto Increment is ON (i.e Identity =TRUE) - sql

how to insert value at a specific index in id Column where as Id Field is auto increment
for Example in may case say columns are ID and Name
ID Name
========================================
2 Austin
3 Peter
4 Albness
22 Sidhu
23 deepika
24 Shahrukh
Where Id is Auto incremented here in my case I have deleted the Id 1,4,5,6 to onward 21 and now I want to add the new name at Id=1 remember again Id is auto_increment (i.e Identity=TRUE in the property )
How do I Accomplish it

For all use cases I can think of, just leaving the gaps seems to be the simpler and safer solution. End users should not see these IDs, and DBAs should be OK with it.
If it's such a big deal, I'd still rather have a DBA manually run a "cleanup" script in a maintenance window than add complexity to production code.

To insert ID value on a table just do that
SET IDENTITY_INSERT [ database. [ owner. ] ] { table } { ON | OFF }
Example your table name is People it should be
INSERT INTO People(ID,NAME) VALUES(3,'Felicio')
PS: to insert indentity value you also need to explicity the columns names and order as in previous example.

Id is either surrogate or natural key.
If it's surrogate, it doesn't have a meaning, and therefore gaps don't matter.
If it's natural, it shouldn't have been auto-increment in the first place.

Related

Continue with Id order values after delete some rows

I accidentally deleted some rows from a table, it's just 4 rows, but now when I try to insert the same values again the Id values are different, it's like it's remembering the Id values that had the rows I deleted before and now every time I insert a row the value generated for Id is not the next to the existent sequence... For example:
Id Name
1 Peter
2 Luis
3 Charles
4 John
Let's say I deleted rows with Name value Peter, Luis, Charles and John. When I try to insert the same names again it inserts them but with a different Id..
Id Name
1 Peter
5 Luis
6 Charles
7 John
I can not change the Identity value manually to the old values.. Which is the best solution in this case?
The reason is that auto-incrementing Id's don't automatically reset. This is by design, as you may have the same values references in other tables, which you may not want to delete (although it creates orphaned rows).
The method of resetting the auto-incrementing value differs between databases. For instance, in MySQL, you can run:
ALTER TABLE myTable SET AUTO_INCREMENT=1;
If you AUTOINCREMENT the Primary Key then you can't change the sequence with which you have started.Even if you insert the same name again it does not matter.It will continue from the next number with which it previously ended.
But if you want to give it a number then don't AUTOINCREMENT it,INSERT primary key value like other values you have inserted in the table.
I ended up setting identity_insert to on and entering the Ids manually with the names and then changed the table back to how it was with identity_insert off

Postgres SQL, how to automatically increment ID when duplicate / insert between two sequential ID's?

I have a table with a SERIAL ID as primary key.
As you know the serial id increments itself automatically, and I need this feature in my table.
ID | info
---------
1 | xxx
2 | xxx
3 | xxx
For ordering matters, I want to insert a row between 1 and 2. Thus give to the new row an ID equal to 2, and want the other ID's to automatically increment to 3,4. If I execute such a query I get a duplicate key error.
Is there a way to make it possible, maybe changing the SERIAL ID to some other type?
What you are describing is not what most people would consider an ID, which should be a permanent and arbitrary identifier, for which an auto-increment column is just a convenient way of creating unique values. You couldn't use a value that kept changing as a foreign key, for example, so might well want both columns.
However, the task you've described is easily achieved with just an ordinary Integer column, let's call it "position", since that seems a more logical label for this behaviour.
The algorithm is simple:
Make a space for the new value by shifting all existing elements up one place.
Insert your new element.
In SQL, that would look something like this, to insert at position 42:
UPDATE items SET position=position + 1 WHERE position >= 42;
INSERT INTO items ( position, name ) VALUES ( 42, 'Answer' );
You could wrap this up in an SQL function on the server, and wrap it in a transaction to prevent concurrent inserts messing each other up.
Note that by default, a PRIMARY KEY or UNIQUE constraint on the position column may be invalidated during the update, as changes to each row are validated separately. To get around this, you can use a "deferrable constraint"; even in "immediate" mode, this will only be checked at the end of the statement, so the update will not violate it.
CONSTRAINT uq_position UNIQUE (position) DEFERRABLE INITIALLY IMMEDIATE
Note also that a Serial column doesn't have to be unique, so you could still have the default value be an auto-increment. However, it won't notice you inserting extra values, so you need to reset the sequence after a manual insert:
SELECT setval(
pg_get_serial_sequence('items', 'position'),
( SELECT max(position) FROM items )
);
Here is a live demo putting it all together. (SQLFiddle seems to have a bug which isn't dropping/resetting the sequence, making the id values look rather odd.)

T-SQL(MSSQL 2005)Reorder Scope_identity

Have a small table of 2 columns on MSSQL Server 2005 which contains a lot of information let's say about 1 billion records and it is constantly being written into.
Definition of the table is :
Create table Test(
id int identity(1,1) primary key ,
name varchar(30) )
Te PK is int which I choose it over uniqueidentifier for a number of reasons. The problem comes with the auto increment I want to reorganize the 'id' every time a row is deleted. The objective to this is leaving no gaps. The table is active and a lot of rows are written into it, so dropping a column is not an option also locking the table for a long time.
Quick example of what I want to accomplish:
I have this :
id | name
----+-------
1 | Roy
2 | Boss
5 | Jane
7 | Janet
I want to reorganize it so it will look like this :
id | name
----+-------
1 | Roy
2 | Boss
3 | Jane
4 | Janet
I am aware of DBCC CHECKIDENT (TableName, RESEED, position) but I am not sure it will benefit my case, because my table is big and it will take a lot of time to reposition also if I am not mistaken it will lock the table for a very long time. This table is not used by any other table. But if you like you can submit a suggestion to the same problem having in mind that the table is used by other tables.
EDIT 1 :
The objective is to prove that the rows follow each other in case a row is deleted so I can see it is deleted and reinstate it.I was thinking of adding a third column that will contain a hash value from the row above , and if the row above is deleted I would know that I have a gap and need to restore it ,in that case the order will not matter because I can compare the has codes and see if they match , so I can see which row follows which.But still I wonder is there a more clever and safer way of doing this ?Maybe involve something else rather then hash codes , some other way of proving that the rows follow each other , or that the new row contains parts of the previous row?
EDIT 2 :
I'll try to explain it one more time if I can't well then I don't want to waste anyone's time.
In the perfect case scenario there will be nothing missing from this table , but due to
server errors some data maybe deleted or some of my associates might be wasteful and delete it by fault.
I have logs and can recover that data, but I want to prove that the records are sequenced , that they follow
each other even if there is a server error and some of them are deleted but later on reinstated.
Is there a way to do this ?
Example:
well let's say that 7 is deleted and after that reinstated as 23 , how would you prove that 23 is 7, meaning that 23 came after 6 and before 8 ?
I would suggest not worrying about trying to reseed your Identity column -- let SQL Server maintain it's uniqueness for each row.
Generally this is wanted for presentation logic instead, in which case, you could use the ROW_NUMBER() analytic function:
SELECT Row_Number() Over (Order By Id) NewId,
Id, Name
FROM YourTable
I agree with others that this shouldn't typically be done, but if you absolutely want to do it you can utilize the quirky update to get it done quickly, should be something like this:
DECLARE #prev_id INT = 0
UPDATE Test
SELECT id = CASE WHEN id - #prev_id = 1 THEN id
ELSE #prev_id + 1
END
,#prev_id = id
FROM test
You should read about the limitations of quirky update, primarily the conditions that must be met to ensure consistent output. This is a good article but they annoyingly have you sign in, but you can find other resources: http://www.sqlservercentral.com/articles/T-SQL/68467/
Edit: Actually, in this case I think you could just use:
DECLARE #prev_id INT = 0
UPDATE Test
SELECT id = #prev_id + 1
,#prev_id = id
FROM Test
The way to do it is to not implement your proposed fix.
Leave the identity alone.
If identity 7 is deleted you know it is just after 6 and and just before 8.
If you need them to stay in the same order then simple.
Place unique constraint on name.
Don't delete the record.
Just add a bool column for active.

Filling the gaps in values of IDENTITY column

I have a table with an IDENTITY column
[Id] int IDENTITY(1, 1) NOT NULL
After some rows beeing added/removed I end with gaps in Id values:
Id Name
---------
1 Tom
2 Bill
4 Kate
Is there an easy way to compress the values to
Id Name
---------
1 Tom
2 Bill
3 Kate
?
I would strongly recommend that you leave the identity values as they are.
if this ID column is used as a foreign key on another table, changing them will get complicated very quickly.
if there is some business logic where they must be sequential then add a new column ID_Display where you can update them using ROW_NUMBER() and keep them pretty for the end user. I never let end users see and/or dictate how I create/populate/store the data, and if they are bothering you about the IDs then show them some other data that looks like an ID but is not a FK or PK.
I think it's pretty easy to create a 2nd table with the same schema, import all the data (except for the identity column of course; let the 2nd table start renumbering) from the first table, drop the first table and rename the 2nd to the original name.
Easiness may be in question if you'd have a ton of FK relationships to rebuild with other tables etc.
Well as far as I know the only way you can is manually update the values by turning Identity insert on..but you should really avoid doning such a thing in first place..also if you truncate the table it will not have those gaps.
I cannot control the part which requires ID columns to be in sequence.
This sounds like there is program logic which assumes there are no gaps--correct?
I need this to keep two different databases in sync.
It's still not clear what you mean. If the actual values in the IDENTITY column are not meaningful (not used as foreign keys by other tables), you can just do this:
DELETE FROM db1.table
SELECT col1, col2, col3 /* leave out the IDENTITY column */
INTO db1.table FROM db2.table

SQL Table Design - Identity Columns

SQL Server 2008 Database Question.
I have 2 tables, for arguments sake called Customers and Users where a single Customer can have 1 to n Users. The Customers table generates a CustomerId which is a seeded identity with a +1 increment on it. What I'm after in the Users table is a compound key comprising the CustomerId and a sequence number such that in all cases, the first user has a sequence of 1 and subsequent users are added at x+1.
So the table looks like this...
CustomerId (PK, FK)
UserId (PK)
Name
...and if for example, Customer 485 had three customers the data would look like...
CustomerId | UserId | Name
----------
485 | 1 | John
485 | 2 | Mark
485 | 3 | Luke
I appreciate that I can manually add the 1,2,3,...,n entry for UserId however I would like to get this to happen automatically on row insert in SQL, so that in the example shown I could effectively insert rows with the CustomerId and the Name with SQL Server protecting the Identity etc. Is there a way to do this through the database design itself - when I set UserId as an identity it runs 1 to infinity across all customers which isn't what I am looking for - have I got a setting wrong somewhere, or is this not an option?
Hope that makes sense - thanks for your help
I can think of no automatic way to do this without implementing a custom Stored Procedure that inserted the rows and checked to increment the Id appropriately, althouh others with more knowledge may have a better idea.
However, this smells to me of naturalising a surrogate key - which is not always a good idea.
More info here:
http://www.agiledata.org/essays/keys.html
That's not really an option with a regular identity column, but you could set up an insert trigger to auto populate the user id though.
The naive way to do this would be to have the trigger select the max user id from the users table for the customer id on the inserted record, then add one to that. However, you'll run into concurrency problems there if more than one person is creating a user record at the same time.
A better solution would be to have a NextUserID column on the customers table. In your trigger you would:
Start a transaction.
Increment the NextUserID for the customer (locking the row).
Select the updated next user id.
use that for the new User record.
commit the transaction.
This should ensure that simultaneous additions of users don't result in the same user id being used more than once.
All that said, I would recommend that you just don't do it. It's more trouble than it's worth and just smells like a bad idea to begin with.
So you want a generated user_id field that increments within the confines of a customer_id.
I can't think of one database where that concept exists.
You could implement it with a trigger. But my question is: WHY?
Surrogate keys are supposed to not have any kind of meaning. Why would you try to make a key that, simultaneously, is the surrogate and implies order?
My suggestions:
Create a date_created field, defaulting to getDate(). That will allow you to know the order (time based) in which each user_id was created.
Create an ordinal field - which can be updated by a trigger, to support that order.
Hope that helps.