There have been various similar questions, but they either referred to a too specific DB or assumed unsorted data.
In my case, the SQL should be portable if possible. The index column in question is a clustered PK containing a timestamp.
The timestamp is 99% of the time larger than previously inserted value. On rare occasions however, it can be smaller, or collide with an existing value.
I'm currently using this code to insert new values:
IF NOT EXISTS (select * from Foo where Timestamp = @ts) BEGIN
INSERT INTO Foo ([Timestamp]) VALUES (@ts);
END
ELSE BEGIN
INSERT INTO Foo ([Timestamp]) VALUES (
(SELECT Max (t1.Timestamp) - 1
FROM Foo t1
WHERE Timestamp < @ts
AND NOT EXISTS (select * from Foo t2 where t2.Timestamp = t1.Timestamp - 1))
);
END;
If the row is unused yet, just insert. Else, find the closest free row with a smaller value using an EXISTS
check.
I am a novice when it comes to databases, so I'm not sure if there is a better way. I'm open for any ideas to make the code simpler and/or faster (around 100-1000 insertions per second), or to use a different approach altogether.
Edit Thank you for your comments ans answers so far.
To explain about the nature of my case: The timestamp is the only value ever used to sort the data, minor inconsistencies can be neglected. There are no FK relationships.
However, I agree that my approach is flawed, outweighing the reasons to use the presented idea in the first place. If I understand correctly, a simple way to fix the design is to have a regular, autoincremented PK column in combination with the known (and renamed) timestamp column, which will be clustered.
From a performance POV, I don't see how this could be worse than the initial approach. It also simplifies the code a lot.