PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Динамичен ORDER BY и ASC / DESC във функция plpgsql

Бих го направил така:

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$;

Основна функция:използвайте format() за безопасно и елегантно свързване на вашия низ на заявка. Свързани:

ASC / DESC (или ASCENDING / DESCENDING ) са фиксирани ключови думи. Добавих ръчна проверка (IF ... ) и по-късно да се свържат с прост %s . Това е един начин за отстояване на правен принос. За удобство добавих съобщение за грешка за неочаквано въвеждане и параметър по подразбиране, така че функцията по подразбиране е ASC ако последният параметър е пропуснат в повикването. Свързани:

Адресиране на валиден на Павел коментар , свързвам _limit и _offset директно, така че заявката вече е планирана с тези параметри.

_limit и _offset са integer параметри, така че можем да използваме обикновен %s без опасност от SQL инжектиране. Може да искате да заявите разумни стойности (изключете отрицателните стойности и твърде високите стойности), преди да свържете...

Други бележки:
  • Използвайте последователна конвенция за именуване. Префиксирах всички параметри и променливи с долна черта _ , не само някои .

  • Не се използва квалификация на таблица в EXECUTE , тъй като има само една включена таблица и EXECUTE има отделен обхват.

  • Преименувах някои параметри за изясняване. _order_by вместо _sort_by; _order_asc_desc вместо _order .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Има ли начин за ограничаване на скоростта или ограничаване на потребител или връзка в PostgreSql?

  2. psql - запазване на резултатите от командата във файл

  3. PostgreSQL/JDBC и TIMESTAMP срещу TIMESTAMPTZ

  4. Как да интегрирам PostgreSql с EntityFramework 6.0.2?

  5. postgres array_agg ГРЕШКА:не може да натрупва масиви с различна размерност