The immediate cause of the error message is the missing END
at the end.
DO
$do$
DECLARE
i int := 0;
_date date := '2009-01-01';
BEGIN
WHILE i <= 10 LOOP
BEGIN -- expensive noise
INSERT INTO test_calendar (test_date)
VALUES (_date + i);
i := i + 1;
END;
END LOOP;
END -- !
$do$;
A semicolon after the final END
is optional.
But there is more:
There is no dateadd()
function in Postgres (like in SQL Server). You can simply add integer
to a date
for your purpose.
The expensive nested block serves no purpose. Remove it.
Such a loop is simpler and cheaper with FOR
. See:
DO
$do$
DECLARE
_date date := '2009-01-01';
BEGIN
FOR i IN 1..10 -- i defined implicitely
LOOP
INSERT INTO test_calendar (test_date)
VALUES (_date + i);
END LOOP;
END
$do$;
Proper way
All of the above is just proof of concept. What I really would do:
INSERT INTO test_calendar (test_date)
SELECT generate_series(timestamp '2009-01-01'
, timestamp '2009-01-11'
, interval '1 day');
db<>fiddle here
A set-based solution is generally better for this. Use generate_series()
in Postgres. Detailed explanation:
A single multi-row INSERT
is much cheaper than many single-row INSERT
commands.
The generated timestamp
values are cast to date
in the assignment. In other contexts you may need to cast explicitly.
Typically, you don't even need a persisted calendar table at all in Postgres. Just use generate_series()
directly. Might be even faster.