Only values can be parameterized in SQL commands, not identifiers or key words. And it currently works only for SELECT
, INSERT
, UPDATE
, and DELETE
commands. Details:
You need dynamic SQL with EXECUTE
in plpgsql.
Combine that with the implicit cursor of a FOR
loop, which is typically simpler and faster than an explicit cursor. Instructions in the manual.
I also suggest to use a regclass
parameter to pass valid table names safely.
CREATE OR REPLACE FUNCTION myfunction(_tbl regclass)
RETURNS int AS
$func$
DECLARE
bid integer; -- appropriate data type!
BEGIN
FOR bid IN EXECUTE
'SELECT id FROM ' || _tbl
LOOP
-- statements can use bid
RAISE NOTICE '%', bid;
END LOOP;
RETURN 1;
END
$func$ LANGUAGE plpgsql;
Call:
SELECT myfunction('tableA'); -- careful: case sensitive!
More explanation:
And typically, there is a faster set-based solution that does not need to loop at all.
If you positively need a cursor, declare an unbound cursor and open it with OPEN FOR EXECUTE
:
CREATE OR REPLACE FUNCTION myfunction(_tbl text) -- could be regclass again
RETURNS int AS
$func$
DECLARE
_bids refcursor;
_rec record;
BEGIN
OPEN _bids FOR EXECUTE 'SELECT id FROM ' || quote_ident(_tbl); -- text must be escaped
LOOP
FETCH NEXT FROM _bids INTO _rec;
EXIT WHEN _rec IS NULL;
-- some logic
RAISE NOTICE '%', _rec.id;
END LOOP;
RETURN 1;
END
$func$ LANGUAGE plpgsql;
Same call. More details in this closely related answer: