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;
Wichtige Punkte
-
row
ist ein reserviertes Wort im SQL-Standard. Seine Verwendung ist in Postgres erlaubt, aber es ist immer noch unklug. Ich mache es mir zur Gewohnheit, der psql-Variablen einen Unterstrich_
voranzustellen um Namenskonflikte zu vermeiden. -
Sie wählen nicht die ganze Zeile aus Wie auch immer, nur der Tabellenname in diesem Beispiel. Verwenden Sie am besten eine Variable vom Typ
regclass
, wodurch eine SQL-Injection durch illegale Tabellennamen automatisch vermieden wird. Details in dieser zugehörigen Antwort:
Tabellenname als PostgreSQL-Funktionsparameter -
Sie brauchen
LIMIT
nicht in einemEXISTS
-Ausdruck, der nur die Existenz von any prüft Reihen. Und aus dem gleichen Grund brauchen Sie keine aussagekräftigen Zielspalten. Schreiben Sie einfachSELECT 1
oderSELECT *
oder so . -
Sie benötigen dynamisches SQL für Abfragen mit variablen Bezeichnern. Plain SQL lässt das nicht zu. D.h.:Erstellen Sie eine Abfragezeichenfolge und
EXECUTE
es. Details in dieser eng verwandten Antwort:
Dynamisches SQL (EXECUTE) als Bedingung für IF-Anweisung -
Dasselbe gilt für ein
DROP
Anweisung, wenn Sie es ausführen möchten. Ich habe einen Kommentar hinzugefügt.