sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL - Skriver dynamisk sql i lagrad procedur som returnerar en resultatuppsättning

Det finns utrymme för förbättringar:

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

Huvudpunkter

  • PostgreSQL 8.4 introducerade USING sats för EXECUTE , vilket är användbart av flera skäl. Sammanfattning i manualen:

    Kommandosträngen kan använda parametervärden, som refereras till i kommandot som $1, $2 , etc. Dessa symboler refererar till värden som finns i USING klausul. Denna metod är ofta att föredra framför att infoga datavärden i kommandosträngen som text:den undviker runtime overhead för att konvertera värdena till text och tillbaka, och den är mycket mindre benägen för SQL-injektionsattacker eftersom det inte finns något behov av att citera eller fly.

    IOW, det är säkrare och snabbare än att bygga en frågesträng med textrepresentation av parametrar, även när det saneras med quote_literal() .
    Observera att $1, $2 i frågesträngen hänvisar till de angivna värdena i USING klausul, inte till funktionsparametrarna.

  • Medan du returnerar SELECT * FROM lookups.countries , kan du förenkla RETURN deklaration som visas:

    RETURNS SETOF lookups.countries
    

    I PostgreSQL finns en sammansatt typ definierad för varje tabell automatiskt. Använd den. Effekten är att funktionen beror på typen och du får ett felmeddelande om du försöker ändra tabellen. Släpp och återskapa funktionen i ett sådant fall.

    Detta kan eller kanske inte är önskvärt - i allmänhet är det så! Du vill bli medveten om biverkningar om du ändrar tabeller. Som du har det kommer din funktion att gå sönder tyst och göra ett undantag vid nästa samtal.

  • Om du anger en uttrycklig standard för den andra parametern i deklarationen som visas, kan du (men behöver inte) förenkla anropet om du inte vill sätta en övre gräns med ends_with .

    SELECT * FROM report_get_countries_new('Zaire');
    

    istället för:

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

    Var medveten om funktionsöverbelastning i detta sammanhang.

  • Citera inte språknamnet 'plpgsql' även om det tolereras (för nu). Det är en identifierare.

  • Du kan tilldela en variabel vid deklarationstillfället. Sparar ett extra steg.

  • Parametrar namnges i rubriken. Släpp de meningslösa raderna:

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


  1. Hur man kontrollerar om en T-SQL UDF är schemabunden (även när den är krypterad)

  2. Hur kan jag återställa MySQL root-användarens fullständiga rättigheter?

  3. Fullständig återställning av ett MySQL- eller MariaDB Galera-kluster från säkerhetskopiering

  4. SQL AVG() för nybörjare