You cannot DECLARE
(global) variables (there are workarounds) nor loop with plain SQL - with the exception of recursive CTEs as provided by @bma (which is actually iterating over rows, not looping, strictly speaking).
However, there is the DO
statement for such ad-hoc procedural code. Introduced with Postgres 9.0. It works like a one-time function, but does not take any parameters and does not return anything. You can RAISE
notices et al, so your example would just work fine:
DO
$do$
DECLARE
_counter int := 0;
BEGIN
WHILE _counter < 10
LOOP
_counter := _counter + 1;
RAISE NOTICE 'The counter is %', _counter; -- coerced to text automatically
END LOOP;
END
$do$
If not specified otherwise, the language in the body defaults to plpgsql
. You can use any registered procedural language though, if you declare it (like: LANGUAGE plpython
).
Postgres also offers generate_series()
to generate sets ad-hoc, which may obviate the need for looping in many cases. Try a search here on SO for examples.
Also, you can use the WHERE
clause in a data-modifying CTE in plain SQL to fork cases and emulate IF .. THEN .. ELSE .. END
...