DO command vs. PL/pgSQL function
A DO command does not return rows. You can send NOTICES or RAISE other messages (using default LANGUAGE plpgsql), or you can write to a (temporary) table and later SELECT from it to get around this.
But really, create a function instead, where you can define a return type with the RETURNS clause and/or OUT and INOUT parameters and return from the function in various ways. Related:
- Returning from a function with OUT parameter
If you don’t want a function saved and visible for other connections, consider a “temporary” function, which is an undocumented but well established feature:
- How to create a temporary function in PostgreSQL?
generate_series() for problem at hand
For the problem at hand you don’t seem to need any of this. Use this simple query instead:
SELECT row_number() OVER () AS running_month
, extract('year' FROM m) AS year
, extract('month' FROM m) AS month
FROM generate_series(timestamp '2012-04-01'
, timestamp '2016-01-01'
, interval '1 month') m;
db<>fiddle here
Why?
- Generating time series between two dates in PostgreSQL