Our application needs a simple scheduling mechanism – we can schedule only one visit per room for the same time interval (but one visit can be using one or more rooms). Using SQL Server 2005, sample procedure could look like this:
CREATE PROCEDURE CreateVisit
@start datetime, @end datetime, @roomID int
AS
BEGIN
DECLARE @isFreeRoom INT
BEGIN TRANSACTION
SELECT @isFreeRoom = COUNT(*)
FROM visits V
INNER JOIN visits_rooms VR on VR.VisitID = V.ID
WHERE @start = start AND @end = [end] AND VR.RoomID = @roomID
IF (@isFreeRoom = 0)
BEGIN
INSERT INTO visits (start, [end]) VALUES (@start, @end)
INSERT INTO visits_rooms (visitID, roomID) VALUES (SCOPE_IDENTITY(), @roomID)
END
COMMIT TRANSACTION
END
In order to not have the same room scheduled for two visits at the same time, how should we handle this problem in procedure? Should we use SERIALIZABLE transaction isolation level or maybe use table hints (locks)? Which one is better?
I would have the calling application pass in a comma separated list of room IDs and split them in the SQL, inserting all rows with one INSERT. Doing that, with the proper locking hints (on a single SELECT), should allow your scheduling procedure to work.
I prefer the number table approach to split a string in TSQL, but you can use your own split method if you have one. Here is how to make the number table split approach work:
For this method to work, you need to do this one time table setup:
Once the Numbers table is set up, create this split function:
You can now easily split a CSV string into a table and join on it:
OUTPUT:
This is what I would then make your procedure:
GO
if you have many RoomIDs one one schedule attempt, you could split them into a @TempTable variable or an actual table #TempTable first and then reuse it in the
IF EXISTSandINSERT SELECT.