PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

ĐẶT HÀNG động BẰNG và ASC / DESC trong một hàm plpgsql

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:

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:

Giải quyết Pavel hợp lệ bình luận , Tôi nối _limit_offset trực tiếp, vì vậy truy vấn đã được lập kế hoạch với các tham số đó.

_limit_offsetinteger 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 ...

Các lưu ý khác:
  • 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 .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sao chép môi trường Python trên một máy tính khác

  2. Chèn một mảng bằng cách sử dụng Sequel gem trong PostgreSQL

  3. Trừ các tuần cho một ngày trong PostgreSQL

  4. Castle Activerecord lỗi là "quan hệ không tồn tại" trên Postgresql?

  5. Mẫu &Công cụ sửa đổi mẫu cho Định dạng số trong PostgreSQL