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:
- MASUKKAN dengan nama tabel dinamis dalam fungsi pemicu
- Penentu format untuk variabel integer dalam format() untuk EXECUTE?
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:
- Argumen opsional di PL /pgSQL fungsi
- ERROR:parameter input setelah satu dengan nilai default juga harus memiliki default di Postgres
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 ...
-
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 danEXECUTEmemiliki ruang lingkup tersendiri. -
Saya mengganti nama beberapa parameter untuk memperjelas.
_order_bybukannya_sort_by;_order_asc_descbukannya_order.