I am hoping someone can help me with a set-based approach to this problem. We already have a WHILE loop solution. I'll provide it below to show what we have. NMCAccount TractorID LoadID StopNumber PlaceCode ----------- ---------- ------ ----------- ---------- 10000 Tractor1 Load1 1 2310000 Tractor1 Load1 2 1110000 Tractor1 Load1 3 4510000 Tractor1 Load1 4 1310000 Tractor1 Load1 99 52
The first four columns are the primary key. The application requirement is that if a user wants to insert a StopNumber with a value of 2, we have to bump up 2, 3, 4 so that they become 3, 4, 5 respectively. Expected result set using the above sample data:NMCAccount TractorID LoadID StopNumber PlaceCode ----------- ---------- ------ ----------- ---------- 10000 Tractor1 Load1 1 2310000 Tractor1 Load1 2 7610000 Tractor1 Load1 3 1110000 Tractor1 Load1 4 4510000 Tractor1 Load1 5 1310000 Tractor1 Load1 99 52
In the above result set, I added StopNumber 2 with PlaceCode of 76. Notice how the old 2 row became 3, the old 3 row became 4, the old 4 row became 5, and the 99 row wasn't touched since the other rows fit already.DDL and DML:CREATE TABLE [dbo].[Stop]( [NMCAccount] [int] NOT NULL, [TractorID] [varchar](10) NOT NULL, [LoadID] [varchar](5) NOT NULL, [StopNumber] [int] NOT NULL, [PlaceCode] [varchar](10)NOT NULL, CONSTRAINT [PK_Stop] PRIMARY KEY CLUSTERED ( [NMCAccount] ASC, [TractorID] ASC, [LoadID] ASC, [StopNumber] ASC)) ON [PRIMARY]GOINSERT INTO [dbo].[Stop]([NMCAccount], [TractorID], [LoadID], [StopNumber], [PlaceCode])SELECT 10000, 'Tractor1', 'Load1', 1, '23' UNION ALLSELECT 10000, 'Tractor1', 'Load1', 2, '11' UNION ALLSELECT 10000, 'Tractor1', 'Load1', 3, '45' UNION ALLSELECT 10000, 'Tractor1', 'Load1', 4, '13' UNION ALLSELECT 10000, 'Tractor1', 'Load1', 99, '52'GO
Here is the solution that the developer came up with. It is using SQL Server 2005 logic.CREATE PROCEDURE [dbo].[usp_StopRenumber](@NMCAccount int, @LoadID varchar(20), @StopNumber int)AS--declare variablesDECLARE @Stop int, @Count int, @StopNo int--initailize variablesSELECT @Stop = NULL, @Count = 0, @StopNo = 0--Create a temp tableCREATE TABLE #TempStops(StopNumber int)--Gather all the stop numbers that need to be renumberedBEGIN TRY WHILE (1=1) BEGIN SELECT @Stop = StopNumber FROM Stop WHERE NMCAccount = @NMCAccount AND LoadId = @LoadId AND StopNumber = @StopNumber --If no rows were selected then break out else try the next incremented stop number IF ISNULL(@Stop,0) = 0 BREAK ELSE BEGIN --Insert this stop number into the temp table INSERT INTO #TempStops(StopNumber) VALUES(@Stop) SELECT @StopNumber = @StopNumber + 1, @Stop = null END END --Obtain the number of records in the temp stop table. SELECT @Count = Count(*) FROM #TempStops --If the temp table does have records, then increment the stop numbers of the stops in the temp table WHILE @Count > 0 BEGIN --select the largest stop number SELECT TOP 1 @StopNo = StopNumber FROM #TempStops ORDER BY StopNumber DESC --Increment it by 1 UPDATE Stop SET StopNumber = StopNumber + 1 WHERE NmcAccount = @NMCAccount AND LoadId = @LoadId AND StopNumber = @StopNo --Delete it from the temp table DELETE #TempStops WHERE StopNumber = @StopNo --Decrement the count SET @Count = @Count - 1 ENDEND TRYBEGIN CATCH RETURN 0END CATCHGO
I can provide SQL Server 2000 for the above as well. I just didn't want to make the post too long.Here's how to see that the stored procedure works:DECLARE @NMCAccount int, @TractorID varchar(50), @LoadID varchar(20), @StopNumber int, @PlaceCode varchar(50), @err intSELECT @NMCAccount = 10000, @TractorID = 'Tractor1', @LoadID = 'Load1', @StopNumber = 2, @PlaceCode = '76'--insert the stopBEGIN TRY INSERT Stop (NMCAccount, TractorID, LoadID, StopNumber, PlaceCode) VALUES (@NMCAccount, @TractorID, @LoadID, @StopNumber, @PlaceCode)END TRYBEGIN CATCH --If the stop number already exists, then renumber the other stops and try the insert again SET @err = @@ERROR IF @err = 2627 --Primary Key Violation BEGIN EXEC usp_StopRenumber @NMCAccount, @LoadID, @StopNumber INSERT Stop (NMCAccount, TractorID, LoadID, StopNumber, PlaceCode) VALUES (@NMCAccount, @TractorID, @LoadID, @StopNumber, @PlaceCode) ENDEND CATCHGOSELECT * FROM Stop
Clean-up:DROP TABLE StopDROP PROC usp_StopRenumber
Note: I do have a Numbers table in this environment.Tara Kizer