SQL Loop – Do you Know How to Use WHILE or Recursive CTE?

Last modified date:

Loop is a repeated call of a part of a code with different parameters. Usually the code is bound to certain DML operation such as INSERT or UPDATE. We call out this cycle for predetermined number of repetitions and it can be built in SQL in different ways. We will take a look at all ways using a calendar as an example.

How to Generate Calendar in SQL Using Loop?

Let’s say we want to create a table with calendar in our database with calendar starting on 1/1/1980 and ending on 31/12/2050. We can obviously use more elegant ways to establish calendar in the database but we will take this as an exercise.

Establishing empty table with calendar as a preparation:

CREATE TABLE #Calendar(
   [Date] [Date] PRIMARY KEY,
   [DayOfYear]     AS (DATEPART(DAYOFYEAR,[Date])),
   [DayOfWeek]     AS (DATEPART(WEEKDAY,[Date])),
   [Month]         AS (DATENAME(MONTH,DATEADD(MONTH,DATEPART(MONTH,[Date]),(0))-(1))),
   [Quarter]       AS (CONCAT(DATEPART(QUARTER,[Date]),'Q')),
   [Year]          AS (DATEPART(YEAR,[Date]))
);

We establish pace table with calculated fields for exercise purposes. This way we do not need to insert whole list of fields but only [Datum]. After we establish the table, we only need to insert particular dates and the rest of the fields will be calculated automatically.

1. GOTO method

This method is not recommended much since it is slower than the other methods. It consists of label definition (e.g. “SQL_LOOP_START:”) to which we return by command GOTO in particular iterations.

DECLARE @date AS SMALLDATETIME = '1980-01-01';
DECLARE
@date_end AS SMALLDATETIME = '2050-12-31';

SQL_CYCLE_START:

   INSERT INTO #Calendar ([date])
   VALUES(@date)
   SET @date = @date+1

IF @date < @date_end
GOTO SQL_CYCLE;

SELECT * FROM #Calendar;

2. WHILE/BEGIN/END Cycle

Command WHILE is used to execute repeated call of code following after WHILE (usually separated BEGIN/END) until the requirement following after WHILE is in effect.

/*delete the dates in our table and enter the dates in a different way*/

TRUNCATE TABLE #Calendar;

DECLARE @date AS SMALLDATETIME = '1980-01-01'
DECLARE @date_end AS SMALLDATETIME = '2050-12-31'

WHILE @date< @date_end
BEGIN
INSERT INTO
#Calendar ([date])
  VALUES(@date)
SET @date = @date+1
END;

3. Recursive CTE (Common table expression)

Recursive CTE is by far the fastest way to achieve the needed result:

/*delete the dates in our table and enter the dates in a different way*/
TRUNCATE TABLE #Calendar;

DECLARE @date AS SMALLDATETIME = '1980-01-01';
DECLARE @date_end AS SMALLDATETIME = '2050-12-31'

;WITH [CTE_Date] ([Date]) AS (
   SELECT @date AS DATUM
     UNION ALL
   SELECT [DATE]+1 AS DATE
   FROM [CTE_Date]
   WHERE [DATE] + 1<@date_end
)
INSERT INTO #Calendar
SELECT * FROM [CTE_Date] OPTION (MAXRECURSION 32767);

More about recursive queries on Microsoft website

My name is Jan Zedníček and I work as a BI Developer at Kentico Software in Brno. Mostly you can see me there working in the office, but I also work partly as a freelancer. I have been working as a freelancer for many companies for more than 5 years, but Kentico is the matter of my heart. I used to work as a financial controller at companies like Aero Vodochody or Sberbank and I also used to be a bond program manager in Unicapital Investment group. When I am not at work, I like playing volleyball, chess, doing a workout in the gym and I enjoy tasting of best quality rums. I am trying to summarize all my knowledge on this website not to forget them (because of the rum effect, you know =) and to put them forward to anyone. Don´t worry about asking for help or writing some comments.

Category: SQL Commands Tags:

About Ing. Jan Zedníček - BI Developer, Finance controller

My name is Jan Zedníček and I work as a BI Developer at Kentico Software in Brno. Mostly you can see me there working in the office, but I also work partly as a freelancer. I have been working as a freelancer for many companies for more than 5 years, but Kentico is the matter of my heart. I used to work as a financial controller at companies like Aero Vodochody or Sberbank and I also used to be a bond program manager in Unicapital Investment group. When I am not at work, I like playing volleyball, chess, doing a workout in the gym and I enjoy tasting of best quality rums. I am trying to summarize all my knowledge on this website not to forget them (because of the rum effect, you know =) and to put them forward to anyone. Don´t worry about asking for help or writing some comments.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.