sql >> Database >  >> RDS >> PostgreSQL

Dynamische ORDER BY en ASC / DESC in een plpgsql-functie

Ik zou het als volgt doen:

CREATE OR REPLACE FUNCTION list(
      _category varchar(100)
    , _limit int
    , _offset int
    , _order_by varchar(100)
    , _order_asc_desc text = 'ASC')  -- last param with default value
  RETURNS TABLE(id int, name varchar, clientname varchar, totalcount bigint)
  LANGUAGE plpgsql AS
$func$
DECLARE
   _empty text := '';
BEGIN
   -- Assert valid _order_asc_desc
   IF upper(_order_asc_desc) IN ('ASC', 'DESC', 'ASCENDING', 'DESCENDING') THEN
      -- proceed
   ELSE
      RAISE EXCEPTION 'Unexpected value for parameter _order_asc_desc.
                       Allowed: ASC, DESC, ASCENDING, DESCENDING. Default: ASC';
   END IF;
   
   RETURN QUERY EXECUTE format(
     'SELECT id, name, clientname, count(*) OVER() AS full_count
      FROM   design_list
      WHERE ($1 = $2 OR category ILIKE $1) 
      ORDER  BY %I %s
      LIMIT  %s
      OFFSET %s'
    , _order_by, _order_asc_desc, _limit, _offset)
   USING _category, _empty;
END
$func$;

Kernfunctie:gebruik de indeling format() om uw queryreeks veilig en elegant samen te voegen. Gerelateerd:

ASC / DESC (of ASCENDING / DESCENDING ) zijn vaste trefwoorden. Ik heb een handmatige controle toegevoegd (IF ... ) en later samenvoegen met een eenvoudige %s . Dat is één manier om juridische inbreng te doen gelden. Voor het gemak heb ik een foutmelding toegevoegd voor onverwachte invoer en een parameterstandaard, zodat de functie standaard is ingesteld op ASC als de laatste parameter wordt weggelaten in de aanroep. Gerelateerd:

Adressering van Pavel is geldig commentaar , ik voeg _limit samen en _offset direct, dus de query is al gepland met die parameters.

_limit en _offset zijn integer parameters, zodat we gewone %s . kunnen gebruiken zonder het gevaar van SQL-injectie. Misschien wilt u redelijke waarden claimen (exclusief negatieve waarden en waarden die te hoog zijn) voordat u samenvoegt ...

Andere opmerkingen:
  • Gebruik een consistente naamgevingsconventie. Ik heb alle parameters en variabelen voorafgegaan door een onderstrepingsteken _ , niet alleen sommige .

  • Tabelkwalificatie niet gebruiken binnen EXECUTE , aangezien er maar één tabel bij betrokken is en de EXECUTE heeft zijn eigen bereik.

  • Ik heb een aantal parameters hernoemd ter verduidelijking. _order_by in plaats van _sort_by; _order_asc_desc in plaats van _order .



  1. MySQL sorteren op aantal keren

  2. ORA-06550:Verkeerd nummer of type argumenten fout bij het aanroepen van een functie in een orakelpakket in ASP.NET

  3. Hoe in te voegen in MySQL met behulp van een voorbereide verklaring met PHP

  4. Alle gegevens in de SQL Server-database verwijderen