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

一世执手 提交于 2020-01-14 07:19:08

问题


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:

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?


回答1:


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);



回答2:


Alternatively, you can have a dedicated table with the counters. It is not a good design pattern but it put you in full control of the how the identity work.



来源:https://stackoverflow.com/questions/18444407/sql-server-arbitrary-auto-increment-of-primary-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!