• This might help:

    IF object_id('TempDB..#Temp') IS NOT NULL

    DROP TABLE #Temp

    CREATE TABLE #Temp (DateTimeRow DATETIME)

    DECLARE @STARTDATE DATETIME, @StartTimeChar CHAR(5), @EndTimeChar CHAR(5);

    SELECT

    @STARTDATE = CAST(GETDATE() AS DATE),

    @StartTimeChar = '08:00', -- note left-padded digit

    @EndTimeChar = '10:00';

    -- inline tally table CTE

    WITH E1(N) AS (

    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL

    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL

    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1), -- 10 rows

    E2(N) AS (SELECT 1 FROM E1 a, E1 b),-- 10*10 = 100 rows

    iTally(N) AS (SELECT 1 FROM E2 a, E2 b)-- 100*100 = 10000 rows max

    INSERT INTO #Temp

    (DateTimeRow)

    SELECT TOP(1+DATEDIFF(minute,@StartTimeChar,@EndTimeChar)/15) -- number of rows to collect

    DateTimeRow = DATEADD(minute,((ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1)*15),StartDateTime)

    FROM iTally -- row source - inline tally table

    CROSS APPLY (

    SELECT StartDateTime =

    DATEADD(hour,CAST(LEFT(@StartTimeChar,2) AS INT),@STARTDATE)

    ) x;

    SELECT * FROM #Temp;

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden