Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server: arbitrary auto-increment of primary key [duplicate]

We're running SQL server 2012 SP1 x64 (11.0.3000.0)

I have the following table with the InvoiceId field as the auto-incrementing, primary key:

CREATE TABLE Orders(
    InvoiceId           bigint           IDENTITY(1001,1) NOT FOR REPLICATION,
    OrderId             varchar(8)       NOT NULL,
    ...  -- other fields removed for brevity
    CONSTRAINT [PK_ORDERS] PRIMARY KEY CLUSTERED (InvoiceId)
    ON [PRIMARY], 
)

New rows are inserted though a simple stored procedure like the following:

SET  XACT_ABORT ON
SET  NOCOUNT ON

BEGIN TRANSACTION
    INSERT INTO Orders(
          OrderId,
          ... -- other fields removed for brevity
        )
    VALUES  (
          @orderId,
          ...
        )              

    SELECT @newRowId = SCOPE_IDENTITY()
COMMIT TRANSACTION

The above sproc returns the newly created row-id (Orders.InvoiceId) to the caller.

The code was working perfectly, with [InvoiceId] starting from 1001 and incrementing by 1 for each successive inserts.

Our users inserted about 130 rows. [InvoiceId] was at 1130, then on the next insert its value jumped to 11091!

Here's the data screenshot:

data

I'm baffled as to what just happened here. Why did the auto-inc counter suddenly skip nearly 10,000 points?

We're using the value of [InvoiceId] to generate barcodes, so we'd prefer the value to remain in a specific range, preferably in a contiguous series.

I've perused the T-SQL documentation but failed to find anything related to my issue. Is this the normal behavior (arbitrary population) of an identity field?

like image 494
masroore Avatar asked Aug 26 '13 12:08

masroore


1 Answers

UPDATE Thanks to Marting & Aron, I've found a work-around. Here's the official response from Microsoft:

In SQL Server 2012 the implementation of the identity property has been changed to accommodate investments into other features. In previous versions of SQL Server the tracking of identity generation relied on transaction log records for each identity value generated. In SQL Server 2012 we generate identity values in batches and log only the max value of the batch. This reduces the amount and frequency of information written to the transaction log improving insert scalability.

If you require the same identity generation semantics as previous versions of SQL Server there are two options available:

• Use trace flag 272 o This will cause a log record to be generated for each generated identity value. The performance of identity generation may be impacted by turning on this trace flag.

• Use a sequence generator with the NO CACHE setting(http://msdn.microsoft.com/en-us/library/ff878091.aspx) o This will cause a log record to be generated for each generated sequence value. Note that the performance of sequence value generation may be impacted by using NO CACHE.

Example:

CREATE SEQUENCE s1 AS INT START WITH 1 NO CACHE; 
CREATE TABLE t1 (Id INT PRIMARY KEY DEFAULT NEXT VALUE FOR s1, col INT NOT NULL);
like image 146
masroore Avatar answered Oct 14 '22 06:10

masroore