Use a CTE, do a UNION ALL on it, this will create a cursive loop that is MUCH better performing than your loop. Look here Using CTE as a block loop ?
What is the best way to store long term Data in MSSQL like stored procedure
-
19-09-2022 - |
题
i have a Problem with my performance on this procedure. I am useing MS SQL SERVER 2012 Standard and SSMS on i7 with 8 GB. The OS is Windows Server 2008. The procedure I wrote, are able to Insert or Update Values in the SQL Table between two Times and Dates. For Example
- The Procedure Inserts/Update Values between 00:45 AM and 02:45 AM between 01.01.2014 and 01.12.2014.
- The Procedure Inserts/Update Values between 00:00 AM and 23:45 PM between 01.01.2014 and 01.12.2014.
For this Procedure, the Important Parameters are
@startdate @Starttime
and @enddate @endtime
For Example 01.01.2014 00:00 - 01.12.2014 23:45 / 11
Month. Its quite necessary that the Inputs in the SQL Table are every 15 minutes.
4*24*30*11 = 31580 Values for 11 Month. This take some time.
More than 6 Minutes !
All Threads from the OS are used, if I execute the procedure.
How can I get my slow procedure smarter and faster?
USE [DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Insert_Into]
-- parameters for the stored procedure
@id int,
@StartDate date,
@EndDate date,
@Starttime time,
@Endtime time,
@value int
AS
DECLARE @TempTime time = @Starttime
BEGIN
SET NOCOUNT ON;
WHILE @Startdate <= @EndDate
BEGIN
WHILE @Starttime <= @Endtime
BEGIN
--If the entry exisits than update, if not, than insert
if exists (select date,ID from [dbo].[Insert_Table] where Datum = @StartDate + cast(@Starttime as datetime) AND ID = @id)
begin
PRINT @Starttime
UPDATE [dbo].[Insert_Table]
SET [ID] = @id, [datum] =( @StartDate + cast(@Starttime as datetime)), [value] = @value
WHERE ID = @id AND Datum =( @StartDate+ cast(@Starttime as datetime))
IF( @Starttime = @Endtime)
begin
print'EndDay'
SET @Starttime = DATEADD(Minute,1,@Endtime) -- Starttime One Minute over Endtime
end
else
select @Starttime = DATEADD(MINUTE,15,@Starttime)
end
else
begin
INSERT INTO [dbo].[Insert_Table]([ID],[date],[value])
VALUES
(@id, @StartDate + cast(@Starttime as datetime), @value )
IF( @Starttime = @Endtime)
begin
--print'EndDay'
SET @Starttime = DATEADD(Minute,1,@Endtime) -- Starttime one minute over Endtime
end
else
Select @Starttime = DATEADD(MINUTE,15,@Starttime)
end
END
--PRINT 'END'
SET @Starttime = @Temptime
Select @StartDate = DATEADD(DAY,1,@StartDate)
END
END
解决方案
其他提示
Thanks a lot ! Great, thats what i looking for !
There is my New Code with CTE
USE DB
declare @StDate datetime = '01/01/2013 00:00.000'
declare @Enddate datetime = '01/06/2014 23:45.000'
declare @value as int = 400
declare @id as int = 999
;with cte as
(
select DATEADD(MONTH,DATEDIFF(MONTH,0,@StDate),0) as Sdate
union all
select DATEADD(MINUTE,15,SDate) from cte where SDate < @Enddate
)
Insert into Insert_Table(Date,Value,id)(select SDate as Date, @value,@id from cte )
OPTION (maxrecursion 0)
Select * from Insert_Table order by Date ASC