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.
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.
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.
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) .
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.
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With