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 danEXECUTE
memiliki ruang lingkup tersendiri. -
Saya mengganti nama beberapa parameter untuk memperjelas.
_order_by
bukannya_sort_by
;_order_asc_desc
bukannya_order
.