Tôi sẽ làm như thế này:
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$;
Tính năng chính:sử dụng định dạng format()
để nối chuỗi truy vấn của bạn một cách an toàn và trang nhã. Có liên quan:
- CHÈN với tên bảng động trong chức năng kích hoạt
- Định dạng chỉ định cho các biến số nguyên ở định dạng () cho EXECUTE?
ASC
/ DESC
(hoặc ASCENDING
/ DESCENDING
) là những từ khóa cố định. Tôi đã thêm kiểm tra thủ công (IF ...
) và sau đó nối với một %s
đơn giản . Đó là một cách để khẳng định đầu vào hợp pháp. Để thuận tiện, tôi đã thêm một thông báo lỗi cho đầu vào không mong muốn và một tham số mặc định, do đó, hàm mặc định thành ASC
nếu tham số cuối cùng bị bỏ qua trong cuộc gọi. Có liên quan:
- Đối số tùy chọn trong PL / pgSQL hàm
- LỖI:các tham số đầu vào sau một tham số có giá trị mặc định cũng phải có giá trị mặc định trong Postgres
Giải quyết Pavel hợp lệ bình luận
, Tôi nối _limit
và _offset
trực tiếp, vì vậy truy vấn đã được lập kế hoạch với các tham số đó.
_limit
và _offset
là integer
các tham số, vì vậy chúng tôi có thể sử dụng %s
đơn giản mà không có sự nguy hiểm của SQL injection. Bạn có thể muốn xác nhận các giá trị hợp lý (loại trừ các giá trị âm và giá trị quá cao) trước khi nối ...
-
Sử dụng quy ước đặt tên nhất quán. Tôi đã đặt trước tất cả các tham số và biến bằng dấu gạch dưới
_
, không chỉ một số . -
Không sử dụng tiêu chuẩn bảng bên trong
EXECUTE
, vì chỉ có một bảng duy nhất tham gia vàEXECUTE
có phạm vi riêng biệt. -
Tôi đã đổi tên một số thông số để làm rõ.
_order_by
thay vì_sort_by
;_order_asc_desc
thay vì_order
.