I have a SQL Server database set up as the publisher in a replication environment. It has a couple of subscriptions and several different people have been executing INSERT statements on these. Because of the different value ranges allocated for identity columns, we end up with very wide variations once all the data is pushed back up into the publication.
This is of course to be expected and even desirable in a production environment. However, we're still in development and therefore desire to reorganize all identity values so they are sequential. Instead of [1,2,3,1001,1001,1003] we'd like to have [1,2,3,4,5,6]. I realize this means changing the identity column values and to update them accordingly across the relationships they support. Is it possible to do something like this?
Seed an identity column when you create it in Management Studio.
If you create the table using code, you can easily seed the table’s identity column using the Transact-SQL (T-SQL) CREATE TABLE statement in the following form:
CREATE TABLE tablename
(
columnname datatype identity [(seed, increment)
[NOT FOR REPLICATION]],
[columnname ...]
)
In the code, datatype is a numeric column. Both seed and increment are optional and the default value for both is 1.
Figure B shows the result of using CREATE TABLE to create a table named Orders and setting the OrderID column’s identity seed and increment values to 100 and 10, respectively. As you can see, the first identity value is 100 and each subsequent value increases by 10. (You can decrease identity values by specify a negative value for increment.)
And Use CREATE TABLE to seed an identity column.
Checking and reseeding
For instance, if you copy all the table’s records to an archive table and then delete all the records in the source table, you might want to reseed the source table’s identity column, so you can control the sequence. Use T-SQL’s DBCC CHECKIDENT as follows to reseed an identity column:
DBCC CHECKIDENT
(
tablename
[, [NORESEED | RESEED [, newreseedvalue]]]
)
[WITH NO_INFOMSGS]
Table A defines this statement’s optional parameters.
Table A: DBCC CHECKIDENT
Parameter
Description
NORESEED
Returns the current identity value and the current maximum value of the identity column, without reseeding. These values are usually (and should be) the same.
RESEED
Changes the current identity value, using the maximum value in the identity column, if the current identity value is less than the maximum identity value stored in the identity column.
newreseedvalue
Specifies the new seed value when reseeding. If the table is empty, the first identity value (after executing DBCC CHECKIDENT) will equal newreseedvalue. If the table contains data, the next identity value will equal newreseedvalue + the current increment value (the default is 1). This behavior is new to SQL Server 2005 (and remains in 2008). SQL Server 2000 always increments the seed value.
WITH NO INFOMSGS
Suppresses all informational messages.
Technically, DBCC CHECKIDENT checks and corrects an identity value. Simply put, use it to learn the current identity value or to reseed an existing identity column.
Related
I have a table Line_Production_Plan in SQL Server; it has a UID column (int, auto-increment, identity).
It also has multiple other columns. One of them is execution_priority (int, not null).
When I insert a new row into the table (via a stored procedure (without passing execution_priority or UID as parameters)), I want execution_priority to take up the same value as the corresponding UID column in during insert. Is there a way to set the default value of a column, equal to another upon insert?
The execution, priority needs to be changed from time to time. Hence I can't use identity or auto increment.
You should use IDENT_CURRENT to get the last identity value generated for the table Line_Production_Plan.
Try this code:
INSERT INTO Line_Production_Plan (execution_priority)
VALUES ((SELECT IDENT_CURRENT('Line_Production_Plan')));
I have a problem with identity specification when I create a table in SQL Server 2016.
In column Id I set Identity Increment and Identity Seed equal 1.
Next I add new record to new table.
In column Id show up 2 value. Why? Why not 1 value?
Next drop the first record and add new. In column Id show up 3 value. Why? Why not 1 value.
Next I use command ' update nametable set id=1' and receive answer cannot update identity column Id. Why?
This is probably easier to explain with some code:
CREATE TABLE YourTable (ID int IDENTITY(1,1),
SomeCol varchar(5));
INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 1
INSERT INTO dbo.YourTable (SomeCol)
VALUES('def'),('ghi'); --Will get 2 and 3.
SELECT *
FROM dbo.YourTable;
DELETE FROM dbo.YourTable;
INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 4, because 1-3 have been used. Deleting doesn't let you reuse values.
SELECT *
FROM dbo.YourTable;
DELETE FROM dbo.YourTable;
DBCC CHECKIDENT ('dbo.YourTable', RESEED, 1);
INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 2, as you seeded back to 1; so the NEXT ID is used.
SELECT *
FROM dbo.YourTable;
TRUNCATE TABLE dbo.YourTable;
INSERT INTO dbo.YourTable (SomeCol)
VALUES('abc'); --Will get ID 4, because 1-3 have been used.
SELECT *
FROM dbo.YourTable; --Will get ID 1, as the column was reseed with the TRUNCATE
DROP TABLE dbo.YourTable;
For your specific question on reseeding, the next value after the seed your define is use. The seed you define is the one you are saying was last used. This is covered in the documentation Forcing the current identity value to a new value:
Because the table has existing rows, the next row inserted will use 11
as the value – the new current identity value defined for the column
plus 1 (which is the column's increment value).
The only way to define a table doesn't have existing rows is the TRUNCATE it, which is what I do later on in the above batch (and why 1 is reused).
At the end of the day, the value of your IDENTITY is meaningless other than to provide the row with a single use value (which is not guarenteed to be unique on it's own). Combined with the Primary key/Unique constraints, it makes a good Clustered index candidate, as the next value is always greater than the last used, and values aren't reused.
If having sequential values is important, then what you need to use is a SEQUENCE, not the IDENTITY property. The latter doesn't guarantee uniqueness, or sequential values on it's own (as they could be skipped due to deletes, failed inserts, an unexpected shutdown, etc), but it does guarantee it will not reuse values once they have been (without a RESEED): IDENTITY (Transact-SQL) - Remarks. A SEQUENCE can be used to ensure the values are indeed sequential (apart from due to a DELETE).
Welcome to the forum :)
If you created the table using
Id INT IDENTITY(1,1)
Then the first record inserted will have Id = 1, however, if the insert statement fails or the transaction is rolled back the consumed identity be marked as used (or lost) and the next insert statement will proceed from Id = 2.
Have a look at Microsoft documentation on this topic:
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property?view=sql-server-2017
When deleting inserted rows (which also happens when those inserts are rolled-back in a transaction, by the way), the identity value is not automatically reset. The identity functionality "remembers" its last value.
Gaps in the identity values will also NOT be filled when older records are deleted from the table and new records are inserted into the table.
That's just how identity works. It's a simple and safe mechanism.
If you (occasionally!) want to reset the identity value, you can take a look at DBCC CHECKIDENT. I personally tend to use it like this:
DBCC CHECKIDENT (MyTable, RESEED, 0) WITH NO_INFOMSGS;
DBCC CHECKIDENT (MyTable, RESEED) WITH NO_INFOMSGS;
(I execute both lines, in this order.)
I would advice against this practice in production environments, however.
I have column id which has identity column
CREATE TABLE EMP
(id int primary key identity(1,1),
name varchar(255));
Problem is that after 10 its gives value 111 then 112
why it is not giving 11
It depends how you are inserting the data into it. If it's simple INSERT INTO and nothing else around it, it's weird.
Maybe it's that issue with MSSQL 2012 server? There is a know bug about identity jump when server restarts.
More information http://www.codeproject.com/Tips/668042/SQL-Server-Auto-Identity-Column-Value-Jump-Is
Whatever the cause, you can reset your identity column using the DBCC CHECKIDENT command.
It accepts parameters to allow you to reset the value to whatever you desire. For example this:
DBCC CHECKIDENT ('[TableNameHere]', RESEED, 11)
Will reset the column to 11 - you can substitute whatever number is required as the final parameter.
Using TRUNCATE TABLE will also reset any identity columns - but it will also delete all your data, obviously. Using DELETE will remove data, but it does not change identity values.
After deleting the duplicate records from the table,
I want to update Identity column of a table with consecutive numbering starting with 1. Here is my table details
id(identity(1,1)),
EmployeeID(int),
Punch_Time(datetime),
Deviceid(int)
I need to perform this action through a stored procedure.
When i tried following statement in stored procedure
DECLARE #myVar int
SET #myVar = 0
set identity_insert TempTrans_Raw# ON
UPDATE TempTrans_Raw# SET #myvar = Id = #myVar + 1
set identity_insert TempTrans_Raw# off
gave error like...Cannot update identity column 'Id'
Anyone please suggest how to update Identity column of that table with consecutive numbering starting with 1.
--before running this make sure Foreign key constraints have been removed that reference the ID.
--insert everything into a temp table
SELECT (ColumnList) --except identity column
INTO #tmpYourTable
FROM yourTable
--clear your table
DELETE FROM yourTable
-- reseed identity
DBCC CHECKIDENT('table', RESEED, new reseed value)
--insert back all the values
INSERT INTO yourTable (ColumnList)
SELECT OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
GO
The IDENTITY keword is used to generate a key which can be used in combination with the PRIMARY KEY constraint to get a technical key. Such keys are technical, they are used to link table records. They should have no other meaning (such as a sort order). SQL Server does not guarantee the generated IDs to be consecutive. They do guarantee however that you get them in order. (So you might get 1, 2, 4, ..., but never 1, 4, 2, ...)
Here is the documentation for IDENTITY: https://msdn.microsoft.com/de-de/library/ms186775.aspx.
Personally I don't like it to be guaranteed that the generated IDs are in order. A technical ID is supposed to have no meaning other then offering a reference to a record. You can rely on the order, but if order is information you are interested in, you should store that information in my opinion (in form of a timestamp for example).
If you want to have a number telling you that a record is the fifth or sixteenth or whatever record in order, you can get always get that number on the fly using the ROW_NUMBER function. So there is no need to generate and store such consecutive value (which could also be quite troublesome when it comes to concurrent transactions on the table). Here is how to get that number:
select
row_number() over(order by id),
employeeid,
punch_time,
deviceid
from mytable;
Having said all this; it should never be necessary to change an ID. It is a sign for inappropriate table design, if you feel that need.
If you really need sequential numbers, may I suggest that you create a table ("OrderNumbers") with valid numbers, and then make you program pick one row from OrderNumbers when you add a row to yourTable.
If you everything in one transaction (i.e. with Begin Tran and Commit) then you can get one number for one row with no gabs.
You should have either Primary Keys or Unique Keys on both tables on this column to protect against duplicates.
HIH,
Henrik
Check this function: DBCC CHECKIDENT('table', RESEED, new reseed value)
I am using SQL Server Management Studio and I want to change an auto increment primary key value of a table row, with a different value. SQL Server Management Studio after opening the table for edit, shows this field grayed for all rows, of course.
Is it possible? I want to use the number of a row we deleted by mistake, therefore it's valid (there is no conflict with other primary key values) and - most important of all - the next row added in the DB should have an intact auto incremented value.
Thanks.
EDIT: losing the link with other table records on this PK is not an issue for this row. We can restore it manually.
Not necessarily recommended but, insert a copy of the row where you want to change the number, but with the ID you require:
SET IDENTITY_INSERT aTable ON
GO
-- Attempt to insert an explicit ID value of 3
INSERT INTO aTable (id, product) VALUES(3, 'blah')
GO
SET IDENTITY_INSERT aTable OFF
GO
Then delete the row with the number you don't want (after you update any FK references).
More details here: http://technet.microsoft.com/en-us/library/aa259221(v=sql.80).aspx
For posterity, to clarify the question in the comment below, the auto increment value will only be affected if you insert a value greater than the current maximum.
Quoting from linked article:
If the value inserted is larger than the current identity value for
the table, SQL Server automatically uses the new inserted value as the
current identity value.