sql >> Database teknologi >  >> RDS >> PostgreSQL

PostgreSQL - Skrivning af dynamisk sql i lagret procedure, der returnerer et resultatsæt

Der er plads til forbedringer:

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
 

Vigtige punkter

  • PostgreSQL 8.4 introducerede USING klausul for EXECUTE , hvilket er nyttigt af flere grunde. Opsummering i manualen:

    Kommandostrengen kan bruge parameterværdier, der refereres til i kommandoen som $1, $2 osv. Disse symboler henviser til værdier, der er angivet i USING klausul. Denne metode er ofte at foretrække frem for at indsætte dataværdier i kommandostrengen som tekst:den undgår driftsomkostninger ved at konvertere værdierne til tekst og tilbage, og den er meget mindre tilbøjelig til SQL-injektionsangreb, da der ikke er behov for at citere eller undslippe.

    IOW, det er sikrere og hurtigere end at bygge en forespørgselsstreng med tekstrepræsentation af parametre, selv når det renses med quote_literal() .
    Bemærk at $1, $2 i forespørgselsstrengen henvises til de angivne værdier i USING klausul, ikke til funktionsparametrene.

  • Mens du returnerer SELECT * FROM lookups.countries , kan du forenkle RETURN erklæring som vist:

    RETURNS SETOF lookups.countries
     

    I PostgreSQL er der en sammensat type defineret for hver tabel automatisk. Brug det. Effekten er, at funktionen afhænger af typen, og du får en fejlmeddelelse, hvis du forsøger at ændre tabellen. Drop og genskab funktionen i et sådant tilfælde.

    Dette er måske eller måske ikke ønskeligt - generelt er det det! Du ønsker at blive gjort opmærksom på bivirkninger, hvis du ændrer tabeller. Som du har det, vil din funktion gå i stykker lydløst og rejse en undtagelse ved det næste opkald.

  • Hvis du angiver en eksplicit standard for den anden parameter i erklæringen som vist, kan du (men behøver ikke) forenkle opkaldet, hvis du ikke ønsker at sætte en øvre grænse med ends_with .

    SELECT * FROM report_get_countries_new('Zaire');
     

    i stedet for:

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

    Vær opmærksom på funktionsoverbelastning i denne sammenhæng.

  • Angiv ikke sprognavnet 'plpgsql' selvom det er tolereret (indtil videre). Det er en identifikator.

  • Du kan tildele en variabel på deklarationstidspunktet. Gemmer et ekstra trin.

  • Parametre er navngivet i overskriften. Drop de useriøse linjer:

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


  1. Oracle erklæring

  2. Hvordan kører man en lagret procedure i oracle sql developer?

  3. ALTER TABLE for at tilføje en sammensat primærnøgle

  4. #1273 - Ukendt sortering:'utf8mb4_unicode_ci' cPanel