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

PostgreSQL - Schreiben von dynamischem SQL in eine gespeicherte Prozedur, die eine Ergebnismenge zurückgibt

Es gibt Raum für Verbesserungen:

CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
                                                   , ends_with   text = NULL)
  RETURNS SETOF lookups.countries AS
$func$
DECLARE
   sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
   IF ends_with IS NOT NULL THEN
      sql := sql || ' AND country_name <= $2';
   END IF;

   RETURN QUERY EXECUTE sql
   USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;
-- the rest is default settings

Wichtige Punkte

  • PostgreSQL 8.4 hat den USING eingeführt Klausel für EXECUTE , was aus mehreren Gründen nützlich ist. Zusammenfassung im Handbuch:

    Die Befehlszeichenfolge kann Parameterwerte verwenden, die im Befehl als $1, $2 referenziert werden usw. Diese Symbole beziehen sich auf Werte, die in USING angegeben werden Klausel. Diese Methode ist oft dem Einfügen von Datenwerten in die Befehlszeichenfolge als Text vorzuziehen:Sie vermeidet Laufzeit-Overhead durch das Konvertieren der Werte in Text und zurück und ist viel weniger anfällig für SQL-Injection-Angriffe, da keine Anführungszeichen oder Escapezeichen erforderlich sind /P>

    IOW, es ist sicherer und schneller als das Erstellen einer Abfragezeichenfolge mit Textdarstellung von Parametern, selbst wenn es mit quote_literal() bereinigt wird .
    Beachten Sie, dass $1, $2 im Query-String beziehen sich auf die gelieferten Werte im USING Klausel, nicht zu den Funktionsparametern.

  • Während Sie SELECT * FROM lookups.countries zurückgeben , können Sie den RETURN vereinfachen Deklaration wie demonstriert:

    RETURNS SETOF lookups.countries
    

    In PostgreSQL wird für jede Tabelle automatisch ein zusammengesetzter Typ definiert. Benutze es. Der Effekt ist, dass die Funktion vom Typ abhängt und Sie eine Fehlermeldung erhalten, wenn Sie versuchen, die Tabelle zu ändern. In einem solchen Fall die Funktion löschen und neu erstellen.

    Dies kann wünschenswert sein oder nicht – im Allgemeinen ist es das! Sie möchten auf Nebenwirkungen aufmerksam gemacht werden, wenn Sie Tabellen ändern. So wie Sie es haben, würde Ihre Funktion stillschweigend abbrechen und beim nächsten Aufruf eine Ausnahme auslösen.

  • Wenn Sie eine explizite Standardeinstellung angeben für den zweiten Parameter in der Deklaration kann man (muss aber nicht) den Aufruf vereinfachen, falls man mit ends_with keine Obergrenze setzen will .

    SELECT * FROM report_get_countries_new('Zaire');
    

    statt:

    SELECT * FROM report_get_countries_new('Zaire', NULL);
    

    Beachten Sie in diesem Zusammenhang das Überladen von Funktionen.

  • Geben Sie den Sprachnamen 'plpgsql' auch wenn das (vorerst) geduldet wird. Es ist eine Kennung.

  • Sie können eine Variable zum Zeitpunkt der Deklaration zuweisen. Spart einen zusätzlichen Schritt.

  • Parameter werden in der Kopfzeile benannt. Lassen Sie die unsinnigen Zeilen weg:

     starts_with ALIAS FOR $1;
     ends_with ALIAS FOR $2;