1

I was trying to create a calendar table. The query below. I get the error in the title. Can someone explain why?

create table if not exists test_calendar (test_date date primary key);

do $$
declare
    i intEGER := 0 ;--, date datetime := '20090101';
Begin
    while i <= 10 loop
        begin
            insert into test_calendar (test_date) values (dateadd(dd,i,'20090101'));
            i := i + 1;
        end;
    end Loop;
$$ ;

SELECT * FROM test_calendar
4
  • 1
    What error you are getting, also explain what you want to do in (dateadd(dd,i,'20090101')) . also add end after end loop. Commented Jun 22, 2022 at 2:15
  • ERROR: syntax error at end of input. Commented Jun 22, 2022 at 3:46
  • trying to create a calendar table with 10 dates starting from 2009-01-01/ Commented Jun 22, 2022 at 3:46
  • So do you have your answer? Commented Jul 9, 2022 at 22:48

1 Answer 1

0

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.