• Here's something I came up with. Not sure it's bullet-proof, but maybe it will give you

    some ideas. Sorry that it's a bit of a kludge and not very elegant... :crazy:

    First some sample data:

    IF OBJECT_ID('dbo.eventLog') IS NOT NULL

    DROP TABLE dbo.eventLog

    CREATE TABLE dbo.eventLog

    (

    sessionID INT NOT NULL

    ,logID TIMESTAMP NOT NULL

    ,logText VARCHAR(1000) NULL

    ,created DATETIME NULL

    ,PRIMARY KEY CLUSTERED (sessionID, logID)

    ,UNIQUE (sessionID)

    )

    ;WITH cteSampleData (sessionID,logText,created)

    AS

    (

    SELECT 1001,'George Washington','2013-03-31' UNION ALL

    SELECT 1002,'John Adams','2013-02-28' UNION ALL

    SELECT 1003,'Thomas Jefferson','2013-02-15' UNION ALL

    SELECT 1004,'James Madison','2013-02-01' UNION ALL

    SELECT 1005,'James Monroe','2013-01-31' UNION ALL

    SELECT 1006,'John Q Adams','2013-01-22' UNION ALL

    SELECT 1007,'Andrew Jackson','2013-01-13'

    )

    INSERT INTO dbo.eventLog

    (sessionID,logText,created)

    SELECT

    sessionID

    ,logText

    ,created

    FROM

    cteSampleData

    SELECT

    *

    FROM

    dbo.eventLog

    Now of course the following insert will fail (just to set up a base case)

    ;WITH cteNewData (sessionID,logText,created)

    AS

    (

    SELECT 1001,'Ronald Reagan','2013-05-31'

    )

    INSERT INTO dbo.eventLog

    (sessionID,logText,created)

    SELECT

    sessionID

    ,logText

    ,created

    FROM

    cteNewData

    Msg 2627, Level 14, State 1, Line 1

    Violation of UNIQUE KEY constraint 'UQ__eventLog__23DB12CA731B1205'. Cannot insert duplicate key in object 'dbo.eventLog'. The duplicate key value is (1001).

    The statement has been terminated.

    Now the rest of the code below takes some explaining.

    The first block of code will do an insert. But FOR TESTING I've put in a

    wait state so that you can flip over to another window and insert a

    DIFFERENT row while the first is waiting. This is to simulate what might

    happen if the next ID has been assigned but before the insert completes

    a second insert attempt trying to use the same value.

    So this code will INSERT a new row and "hold" that value even if another

    insert takes place in the interim. It does this by inserting only the sessioID

    and then coming back and doing an update even if another row has been

    inserted behind it. To see how this works, before running the code, create another

    window with the second insert command. Then run the first script and while it's waiting

    flip over and insert a record (or two or more) from the second page. After the wait state

    expires (I made it 15 secs for testing) you can go back to the first page and

    see that the first row has been updated properly. The only minor anomaly I

    see is that the timestamp column value may not be in order.

    WINDOW 1:

    DECLARE

    @NextID INT

    BEGIN

    -- get the next id

    ;WITH NextID(sessionID)

    AS

    (

    SELECT

    MAX(sessionID)+1

    FROM dbo.eventLog

    )

    INSERT INTO dbo.EventLog(sessionID)

    SELECT

    sessionID

    FROM

    NextID AS n

    SELECT TOP(1)

    @NextID = SessionID

    FROM

    dbo.EventLog

    WHERE

    logText IS NULL

    ORDER BY

    logText

    --for testing

    SELECT @NextID AS NextID

    /* Put in a wait state for testing only */

    WAITFOR DELAY '000:00:15' -- 15 sec delay for TESTING ONLY!

    --WHILE WAITING, GO TO SEPARATE WINDOW AND RUN AN INSERT--

    UPDATE dbo.eventLog

    SET

    logText = 'Ronald Reagan'

    ,created = GETDATE()

    WHERE

    sessionID = @NextID

    END

    SELECT

    *

    FROM

    dbo.eventLog

    WINDOW 2:

    /* Simulate a second simultaneous insert */

    /* while waiting for the first insert */

    DECLARE @NewID INT

    SELECT

    @NewID = MAX(sessionID)+1

    FROM

    dbo.eventLog

    ;WITH cteNewData (sessionID,logText,created)

    AS

    (

    SELECT @NewID,'Bill Clinton','2013-01-31'

    )

    INSERT INTO dbo.eventLog

    (sessionID,logText,created)

    SELECT

    nd.sessionID

    ,nd.logText

    ,nd.created

    FROM

    cteNewData AS nd

    SELECT

    *

    FROM

    dbo.eventLog