Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server: insert next available int

I'm dealing with a table in SQL Server that has a serial_no column, which is defined as a non null int. It doesn't appear to be an auto incrementing field, as if I leave that column out of my insert statement I get an error saying that the serial_no field cannot be null.

So how do I insert the next available number?

I tried this:

INSERT INTO mytable (serial_no) VALUES ( (SELECT MAX(serial_no)+1 FROM mytable))

but I get an error saying that subqueries cannot be used in this context.

EDIT: This table is used in an off the shelf product so I cannot change the design and make the serial_no column an auto increment.

like image 943
Paul Wieland Avatar asked Jan 31 '11 16:01

Paul Wieland


People also ask

How can insert next value in sequence in SQL Server?

SEQUENCE statement is used to generate UNIQUE values on particular column in existing table with starting value and increment by value. NEXTVAL statement is used to insert values on existing table by increasing old sequence value with increment by value and returns generated new value.

How do I find the next identity value in SQL Server?

You cannot reliably find out the next identity value - until you've actually inserted a new row into the table. Stop trying - you won't succeed - just accept the fact you cannot know the identity value before the row is actually inserted into the table and SQL Server has assigned the value.

How do you increment in SQL?

The MS SQL Server uses the IDENTITY keyword to perform an auto-increment feature. In the example above, the starting value for IDENTITY is 1, and it will increment by 1 for each new record. Tip: To specify that the "Personid" column should start at value 10 and increment by 5, change it to IDENTITY(10,5) .

Does insert () replace?

You can use the INSERT OR REPLACE statement to write new rows or replace existing rows in the table. The syntax and behavior of the INSERT OR REPLACE statement is similar to the INSERT statement. Unlike the INSERT statement, the INSERT OR REPLACE statement does not generate an error if a row already exists.


1 Answers

You can improve write concurrency with locking hints

INSERT INTO mytable (serial_no, value)
SELECT MAX (serial_no)+1, @value 
FROM mytable WITH (ROWLOCK, XLOCK, HOLDLOCK)

If performance is't important, try TABLOCKX in place of ROWLOCK, XLOCK

However, given this isn't safe either you need to retry

DECLARE @retry bit
SET @retry = 1

WHILE @Retry = 1
BEGIN
    BEGIN TRY
        INSERT INTO mytable (serial_no, value)
        SELECT MAX (serial_no)+1, @value 
        FROM mytable WITH (ROWLOCK, XLOCK, HOLDLOCK)

        SET @Retry = 0
    END TRY
    BEGIN CATCH
        IF ERROR_NUMBER() <> 2627  --PK violation
            RAISERROR ('blah', 16, 1)
    END CATCH
END

Or change to an IDENTITY column and do it properly...

like image 50
gbn Avatar answered Sep 20 '22 12:09

gbn