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;
Vigtige punkter
-
række
er et reserveret ord i SQL-standarden. Dets brug er tilladt i Postgres, men det er stadig uklogt. Jeg gør det til en vane at sætte psql-variabelen foran med en understregning_
for at undgå navnekonflikter. -
Du skal ikke vælge hele rækken i hvert fald kun tabelnavnet i dette eksempel. Brug bedst en variabel af typen
regclass
, hvorved SQL-injektion undgås automatisk ved hjælp af ulovlige tabelnavne. Detaljer i dette relaterede svar:
Tabelnavn som en PostgreSQL-funktionsparameter -
Du behøver ikke
LIMIT
i enFINDER
udtryk, som kun kontrollerer eksistensen af enhver rækker. Og du har ikke brug for meningsfulde målkolonner af samme grund. Bare skrivVÆLG 1 eller
.SELECT *
eller noget -
Du skal bruge dynamisk SQL for forespørgsler med variable identifikatorer. Det tillader almindelig SQL ikke. Dvs.:Byg en forespørgselsstreng og
EXECUTE
det. Detaljer i dette nært beslægtede svar:
Dynamisk SQL (EXECUTE) som betingelse for IF-sætning -
Det samme gælder for en
DROP
statement, hvis du ønsker at køre det. Jeg tilføjede en kommentar.