简体   繁体   中英

Auto Increment SQL Value

In the infinte wisdom of the global DBA at a firm I am working at right now he has created a table that takes an int as an ID field, but does not auto increment the number.

I am passing up a table valued parameter from .Net because it has roughly 100 or more rows of data that are being passed up at any one time and I dont want to kill the application, hammer the network or the SQL Server.

So this is my stored procedure

CREATE PROCEDURE sp_Insert_Supporting_Error_Info

(@tvp [dbo].udt_CEQZW READONLY)

as
begin

INSERT INTO CEQZW 
ERROR_VAR_ID, 
ERROR_ID, 
ERROR_VAR_TYPE_CD, 
ERROR_VAR_VALUE) 
SELECT (SELECT coalesce(MAX(ERROR_VAR_ID), 0) + row_number() over (order by 
(select NULL)) FROM CEQZW) as ERROR_VAR_ID, 
ERROR_ID, 
ERROR_VAR_TYPE_CD, 
ERROR_VAR_VALUE FROM @TVP
end
go

I was hoping that this SELECT coalesce(MAX(ERROR_VAR_ID), 0) + row_number() over (order by (select NULL)) FROM CEQZW would some how do the trick for me as when I test with this

declare @p3 dbo.udt_CEQZW
insert into @p3 values(1,N'es',N'test')
insert into @p3 values(1,N'ec',N'test')
insert into @p3 values(1,N'ec',N'test')
insert into @p3 values(1,N'ses',N'test')
insert into @p3 values(1,N'es',N'test')

exec sp_Insert_Supporting_Error_Info @p3

this is what I get back

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected) Msg 2627, Level 14, State 1, Procedure sp_Insert_Supporting_Error_Info, Line 9 Violation of PRIMARY KEY constraint 'PK_CEQZW'. Cannot insert duplicate key in object 'dbo.CEQZW'. The duplicate key value is (1). The statement has been terminated.

So the question I have is how would I, other than hammering the network, app and SQL Server auto increment and add the ID into the table

Well, I would start by going to your DBA and ask why he decided to not make the ID column and identity. Perhaps he will change his mind.

If, however, he will keep this decision, do not attempt to create an auto-increment mechanism on your own.
99.9% of the cases it has a potential to fail, especially in a multi user environment.
Instead, use the already built in, thread safe method of an identity column.

Since we are talking about a situation where you can't use an identity column directly in your target table, I would suggest using a simple mimic of the sequence object introduced in 2012 version to get you your auto increment.

For this, you'll need a tally (numbers) table. If your DBA did not already create one, send him to to read Jeff Moden's The "Numbers" or "Tally" Table: What it is and how it replaces a loop and then send him to KM.'s answer on this SO post for the creation script. (Method 7 is my favorite.)

Now that you have a numbers table, you add a very simple table:

CREATE TABLE tblSequence
(
    Value int identity(1,1)
)

Then, you create a stored procedure that will insert any number of rows into this table and returns the newly created values (Thanks to Martin Smith for the merge trick on this post !):

CREATE PROCEDURE stp_GetNextValues
(
    @NumberOfValues as int
)
AS

    MERGE INTO Sequence
    USING (SELECT Number
           FROM   Tally
           WHERE  Number <= @NumberOfValues) T
    ON 1 = 0
    WHEN NOT MATCHED THEN
      INSERT
      DEFAULT VALUES
    OUTPUT INSERTED.Value; 

GO

Then whenever you execute this stored procedure you'll get safe auto incremented values.

EXEC stp_GetNextValues 125

You can see the full script in action on rextester.

I leave it up to you to incorporate this into your own procedure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM