PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Variablen für Bezeichner innerhalb von IF EXISTS in einer plpgsql-Funktion

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 einem EXISTS -Ausdruck, der nur die Existenz von any prüft Reihen. Und aus dem gleichen Grund brauchen Sie keine aussagekräftigen Zielspalten. Schreiben Sie einfach SELECT 1 oder SELECT * 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.