Переменные для идентификаторов внутри IF EXISTS в функции plpgsql
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;
Не могли бы вы сказать мне, как использовать переменные в SELECT
который внутри IF EXISTS
? В настоящий момент row.relname.tm
а также row.relname
трактуются буквально что не хочу.
2 ответа
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;
Основные моменты
row
является зарезервированным словом в стандарте SQL. Его использование разрешено в Postgres, но все равно неразумно. Я делаю это хаббитом, чтобы добавить psql переменную с подчеркиванием_
чтобы избежать любых конфликтов имен.Вы не выбираете всю строку в любом случае, просто имя таблицы в этом примере. Лучше всего использовать переменную типа
regclass
, таким образом, избегая внедрения SQL путем недопустимых имен таблиц автоматически. Подробности в этом ответе:
Имя таблицы как параметр функции PostgreSQLВам не нужно
LIMIT
вEXISTS
выражение, которое проверяет только наличие каких-либо строк. И вам не нужны значимые целевые столбцы по той же причине. Просто пишиSELECT 1
или жеSELECT *
или что-тоВам нужен динамический SQL для запросов с идентификаторами переменных. Простой SQL не позволяет этого. Т.е.: построить строку запроса и
EXECUTE
Это. Подробности в этом тесно связанном ответе:
Динамический SQL (EXECUTE) как условие для оператора IFТо же самое верно для
DROP
заявление, если вы хотите запустить его. Я добавил комментарий.
Вам нужно будет построить свой запрос как строку, а затем выполнить ее - см. Раздел о выполнении динамических команд в разделе руководства plpgsql.