PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

ORDER BY dinamis dan ASC / DESC dalam fungsi plpgsql

Saya akan melakukannya seperti ini:

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

Fitur inti:gunakan format format() untuk menggabungkan string kueri Anda dengan aman dan elegan. Terkait:

ASC / DESC (atau ASCENDING / DESCENDING ) adalah kata kunci tetap. Saya menambahkan pemeriksaan manual (IF ... ) dan kemudian digabungkan dengan %s sederhana . Itu satu cara untuk menegaskan masukan hukum. Untuk kenyamanan, saya menambahkan pesan kesalahan untuk input tak terduga dan default parameter, sehingga fungsi default ke ASC jika parameter terakhir dihilangkan dalam panggilan. Terkait:

Mengatasi Pavel valid komentar , saya menggabungkan _limit dan _offset langsung, jadi kueri sudah direncanakan dengan parameter tersebut.

_limit dan _offset adalah integer parameter, jadi kita bisa menggunakan %s plain biasa tanpa bahaya injeksi SQL. Anda mungkin ingin menegaskan nilai wajar (mengecualikan nilai negatif dan nilai terlalu tinggi) sebelum menggabungkan ...

Catatan lain:
  • Gunakan konvensi penamaan yang konsisten. Saya mengawali semua parameter dan variabel dengan garis bawah _ , bukan hanya beberapa .

  • Tidak menggunakan kualifikasi tabel di dalam EXECUTE , karena hanya ada satu tabel yang terlibat dan EXECUTE memiliki ruang lingkup tersendiri.

  • Saya mengganti nama beberapa parameter untuk memperjelas. _order_by bukannya _sort_by; _order_asc_desc bukannya _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. Hitung total kumulatif di Postgresql

  2. Hibernate 'Inverse' dalam file pemetaan

  3. Perbarui tabel dan tampilkan baris yang diperbarui dengan satu perintah SQL

  4. Fungsi agregat di beberapa kolom di postgres

  5. Tidak dapat menentukan tipe polimorfik karena input memiliki tipe yang tidak diketahui