问题
CREATE OR REPLACE FUNCTION drop_now()
RETURNS void AS
$BODY$
DECLARE
row record;
BEGIN
RAISE INFO 'in';
FOR row IN
select relname from pg_stat_user_tables
WHERE schemaname='public' AND relname LIKE '%test%'
LOOP
IF EXISTS(SELECT row.relname.tm FROM row.relname
WHERE row.relname.tm < current_timestamp - INTERVAL '90 minutes'
LIMIT 1)
THEN
-- EXECUTE 'DROP TABLE ' || quote_ident(row.relname);
RAISE INFO 'Dropped table: %', quote_ident(row.relname);
END IF;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
Could you tell me how to use variables in SELECT
which is inside IF EXISTS
? At the present moment, row.relname.tm
and row.relname
are treated literally which is not I want.
回答1:
CREATE OR REPLACE FUNCTION drop_now()
RETURNS void AS
$func$
DECLARE
_tbl regclass;
_found int;
BEGIN
FOR _tbl IN
SELECT relid
FROM pg_stat_user_tables
WHERE schemaname = 'public'
AND relname LIKE '%test%'
LOOP
EXECUTE format($f$SELECT 1 FROM %s
WHERE tm < now() - interval '90 min'$f$, _tbl);
GET DIAGNOSTICS _found = ROW_COUNT;
IF _found > 0 THEN
-- EXECUTE 'DROP TABLE ' || _tbl;
RAISE NOTICE 'Dropped table: %', _tbl;
END IF;
END LOOP;
END
$func$ LANGUAGE plpgsql;
Major points
row
is a reserved word in the SQL standard. It's use is allowed in Postgres, but it's still unwise. I make it a habbit to prepend psql variable with an underscore_
to avoid any naming conflicts.You don't don't select the whole row anyway, just the table name in this example. Best use a variable of type
regclass
, thereby avoiding SQL injection by way of illegal table names automatically. Details in this related answer:
Table name as a PostgreSQL function parameterYou don't need
LIMIT
in anEXISTS
expression, which only checks for the existence of any rows. And you don't need meaningful target columns for the same reason. Just write SELECT 1 or SELECT * or something.You need dynamic SQL for queries with variable identifiers. Plain SQL does not allow for that. I.e.: build a query string and
EXECUTE
it. Details in this closely related answer:
Dynamic SQL (EXECUTE) as condition for IF statementThe same is true for a
DROP
statement, should you want to run it. I added a comment.
回答2:
You'll need to build your query as a string then execute that - see the section on executing dynamic commands in the plpgsql section of the manual.
来源:https://stackoverflow.com/questions/20193432/variables-for-identifiers-inside-if-exists-in-a-plpgsql-function