Generate sequential Ids without losing the sequence

Asked

Viewed 2,718 times

6

For Identity do not want, because it breaks the sequence if something happens. Max() + 1, I find it very vulnerable and slow when you have a lot of records. So I ask you, is there a way that someone knows, that I can generate sequential numbers and if there’s a problem in generation, it doesn’t fire the number, like Identity does? They say that there are algorithms that do this in Sql Server, but would not like to use triggers. Usage Sql Server 2008, Entity 6 and C#. Will be generated by C# with Entity.

  • use sequences + transactions with Isolation level up there (which generates performance impact due to "queuing") would not solve for you?

  • The most common and indicated is the use of Sequence in SQL Server, more if you call Next and do not use you lose the number, for this I think you would have to deal with in C#, maybe.

  • Sequence only exists from SQL Server 2012, the question is in 2008.

  • Why you need sequential numbers that identities would not be able to provide?

  • Are you uniquely in need of a sequel? If not, the @Ciganomorrisonmendex response is quite helpful.

  • @pnet you are stuck to SQL Server 2008 or an upgrade is possible?

Show 1 more comment

4 answers

3

The best way to solve this is:

Not using Identities.

For this you will have to abandon sequential keys and go to random keys. No Entity Framework, the type of field is the Guid.

The chance of collision Guids (that is, you generate two Guids equal) is one in 2.600.000.000.000.000.000.

To use, declare your key Model as follows:

public Guid MeuModeloId { get; set; }

Before applying SaveChanges(), it is necessary to generate a Guid to your property Id:

meuObjeto.MeuModeloId = Guid.NewGuid();

SQL Server works perfectly with Guids, but there the type of data is called UNIQUEIDENTIFIER (read more on http://msdn.microsoft.com/pt-br/library/ms190348.aspx).

  • I don’t think that would meet the requirement of sequential numbers.

  • The answer serves if he doesn’t necessarily need to use a sequence. Or I can put an algorithm that respects a sequence, but much more complex.

3

The resource you are looking for exists from the SQL Server 2012 and is called SEQUENCES.

As SEQUENCES are objects used to generate auto numbering values, where we can define the initial values and their increments. They are independent objects of tables and triggers and were created exactly to circumvent limitations of Identity, as the cited Max() + 1 for example.

It is possible to create a SEQUENCE with the following T-SQL

CREATE SEQUENCE dbo.NomeSeq AS INT MINVALUE 1 CYCLE;

A sequence of the type will be created INT starting from number 1, and reaching the type limit (2147483648 in the case of INT) field, the countdown will be restarted from the CYCLE.

Determine the next sequence value can be done with the command NEXT VALUE FOR

SELECT NEXT VALUE FOR dbo.NomeSeq;

More information regarding syntax and use of SEQUENCE can be found here.

  • 1

    As far as you know to avoid "toothless" only with TRANSACTION and ( Max()+1 or +1 control table) and registry lock.

  • @Motta, control table, seems to me to be the most obvious. It will always store the last value of the key and only write a new value after the key is generated and commited, because if there is a rollback, it will continue with the previous value (does not break the sequence). It’s a great one and I hadn’t even thought about it.

  • @pnet Just take care with Déad-Locks and Locked System , the lock and Unlock part has to be as fast as possible

  • @Motta, thanks for the tip, but I have to schedule an answer so I don’t leave the post open. If you suggest as a response to the control table, mark yours. All others are valid, but I have to choose one. As I opted for the control table, I can mark yours if there is an answer.

  • Mark the one you think best, no problem.

3

Simply create a parallel table of a row and a field just to save your increment.

So, you update this table with contador = contador + 1 every time you need a new ID, and use it in the next transaction.

The price is the extra query to get the ID, but it might be more interesting than the MAX()+1, with the advantage of not returning the counter if you delete the higher number record. (would be the only case of "Banguela record", but it is easy to control whether the auxiliary table will increase or not).

This solution lies between the threshold of a real solution and a technical repair 1, but it works well if applied correctly.

1. gambiarra

Addendum: if you have index in column, do not change anything a MAX() with 1 or with 10000000 records. I can’t imagine that any reasonable DB would check line by line an indexed field to get a simple MAX().

  • In addition to TRANSACTION and LOCK of records.

  • @Motta yes, mainly to ensure that the ID is incremented only if successfully used.

  • So there is no answer to pnet’s question, objects like Sequences ensure uniqueness but not integrity, to ensure uniqueness and integrity just by ensuring that we record the last available record, so LOCK and TRANSACTION should be used.

  • @Motta did not put in the answer not to complicate, but without transaction and lock you can still control this process in the main application. Transaction and lock would be facilitators, but there are outlines. Talk to those who have already had to work with DBF files in shared folder, who will find each solution great (and other scary - maybe the vast majority) for these things :D

  • what I saw controlling in the Application has control of the traffic light type , in short without control of the type "guarantee writing" does not guarantee the integrity.

2

Creating a sequence using a precedent

USE [DBBANCO]
GO

/****** Object:  StoredProcedure [dbo].[Gerador_Seq]  15:35:53 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

Create procedure [dbo].[Gerador_Seq]  @Total int as

DECLARE @intFlag INT

SET @intFlag = 1

WHILE (@intFlag <= @Total )

Begin

    SET @intFlag = @intFlag + 1
    INSERT INTO dbo.TEMP_SEQ (my_name) values ('na') ;

    IF @intFlag = @Total
       begin 
         BREAK;
       end
end
  return ''



GO

/** O campo my_id int IDENTITY =>> Completa o Serviço **/
  • user37310, I will test this at home and put the result. I need something that generates me sequential number, but without breaking the sequence in case of rollback.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.