sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL - Dynamische sql schrijven in opgeslagen procedure die een resultatenset retourneert

Er is ruimte voor verbeteringen:

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

Belangrijkste punten

  • PostgreSQL 8.4 introduceerde de USING clausule voor EXECUTE , wat om verschillende redenen nuttig is. Samenvatting in de handleiding:

    De opdrachtreeks kan parameterwaarden gebruiken, waarnaar in de opdracht wordt verwezen als $1, $2 , enz. Deze symbolen verwijzen naar waarden die zijn opgegeven in de USING clausule. Deze methode heeft vaak de voorkeur boven het invoegen van gegevenswaarden in de opdrachtreeks als tekst:het vermijdt runtime-overhead van het converteren van de waarden naar tekst en terug, en het is veel minder vatbaar voor aanvallen met SQL-injectie, omdat citeren of ontsnappen niet nodig is.

    IOW, het is veiliger en sneller dan het bouwen van een queryreeks met tekstweergave van parameters, zelfs wanneer deze is opgeschoond met quote_literal() .
    Merk op dat $1, $2 in de queryreeks verwijzen naar de opgegeven waarden in de USING clausule, niet naar de functieparameters.

  • Terwijl u SELECT * FROM lookups.countries return retourneert , kunt u de RETURN . vereenvoudigen verklaring zoals aangetoond:

    RETURNS SETOF lookups.countries
    

    In PostgreSQL is er automatisch een samengesteld type gedefinieerd voor elke tabel. Gebruik het. Het effect is dat de functie afhankelijk is van het type en je een foutmelding krijgt als je de tabel probeert te wijzigen. Laat de functie vallen en maak deze opnieuw aan in een dergelijk geval.

    Dit kan al dan niet wenselijk zijn - over het algemeen is het dat wel! U wilt op de hoogte worden gesteld van bijwerkingen als u tabellen wijzigt. Zoals je het hebt, zou je functie stil breken en een uitzondering veroorzaken bij de volgende aanroep.

  • Als u een expliciete standaard . opgeeft voor de tweede parameter in de declaratie, zoals aangetoond, kun je (maar hoeft niet) de aanroep te vereenvoudigen voor het geval je geen bovengrens wilt instellen met ends_with .

    SELECT * FROM report_get_countries_new('Zaire');
    

    in plaats van:

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

    Houd in deze context rekening met functieoverbelasting.

  • Citeer niet de taalnaam 'plpgsql' zelfs als dat wordt getolereerd (voorlopig). Het is een identificatie.

  • U kunt een variabele toewijzen op het moment van declaratie. Bespaart een extra stap.

  • Parameters worden genoemd in de kop. Laat de onzinnige regels vallen:

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


  1. Python-woordenboek invoegen met Psycopg2

  2. Tabel is 'alleen lezen'

  3. Gegevens selecteren van twee verschillende servers in SQL Server

  4. Aanhoudende UUID in PostgreSQL met behulp van JPA