Бих го направил така:
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()
за безопасно и елегантно свързване на вашия низ на заявка. Свързани:
- INSERT с име на динамична таблица във функция за задействане
- Спецификатор на формат за целочислени променливи във format() за EXECUTE?
ASC
/ DESC
(или ASCENDING
/ DESCENDING
) са фиксирани ключови думи. Добавих ръчна проверка (IF ...
) и по-късно да се свържат с прост %s
. Това е един начин за отстояване на правен принос. За удобство добавих съобщение за грешка за неочаквано въвеждане и параметър по подразбиране, така че функцията по подразбиране е ASC
ако последният параметър е пропуснат в повикването. Свързани:
- Незадължителен аргумент в PL /pgSQL функция
- ГРЕШКА:входните параметри след един със стойност по подразбиране също трябва да имат стойности по подразбиране в Postgres
Адресиране на валиден на Павел коментар
, свързвам _limit
и _offset
директно, така че заявката вече е планирана с тези параметри.
_limit
и _offset
са integer
параметри, така че можем да използваме обикновен %s
без опасност от SQL инжектиране. Може да искате да заявите разумни стойности (изключете отрицателните стойности и твърде високите стойности), преди да свържете...
-
Използвайте последователна конвенция за именуване. Префиксирах всички параметри и променливи с долна черта
_
, не само някои . -
Не се използва квалификация на таблица в
EXECUTE
, тъй като има само една включена таблица иEXECUTE
има отделен обхват. -
Преименувах някои параметри за изясняване.
_order_by
вместо_sort_by
;_order_asc_desc
вместо_order
.