Fungsi sanitasi
Apa yang Anda miliki saat ini dapat disederhanakan / dibersihkan menjadi:
CREATE OR REPLACE FUNCTION func_a (username text = '', databaseobject text = '')
RETURNS ????
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE
format ('SELECT * FROM %s v1 LEFT JOIN %I v2 USING (id)'
, CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
, databaseobject);
END
$func$;
Anda hanya memerlukan contoh tambahan dari BEGIN ... END
di badan fungsi untuk memulai blok kode terpisah dengan cakupannya sendiri, yang jarang diperlukan.
Operator gabungan SQL standar adalah ||
. +
adalah tambahan "kreatif" dari vendor Anda sebelumnya.
Jangan gunakan pengidentifikasi kasus CaMeL kecuali Anda mengutipnya dua kali. Sebaiknya jangan gunakan sama sekali Lihat:
- Apakah nama kolom PostgreSQL peka huruf besar/kecil?
varchar(4000)
juga disesuaikan dengan batasan tertentu dari SQL Server. Itu tidak memiliki signifikansi khusus di Postgres. Hanya gunakan varchar(4000)
jika Anda benar-benar membutuhkan batas 4000 karakter. Saya hanya akan menggunakan text
- kecuali bahwa kita tidak memerlukan variabel sama sekali di sini, setelah menyederhanakan fungsinya.
Jika Anda belum menggunakan format()
, namun, lihat manualnya di sini.
Jenis pengembalian
Sekarang, untuk pertanyaan Anda yang sebenarnya:Jenis pengembalian untuk kueri dinamis bisa jadi rumit karena SQL mengharuskannya untuk dideklarasikan paling lambat pada waktu panggilan. Jika Anda memiliki tabel atau tampilan atau tipe komposit di database Anda yang sudah cocok dengan daftar definisi kolom, Anda bisa menggunakannya:
CREATE FUNCTION foo()
RETURNS SETOF my_view AS
...
Jika tidak, eja daftar definisi kolom dengan (paling sederhana) RETURNS TABLE
:
CREATE FUNCTION foo()
RETURNS TABLE (col1 int, col2 text, ...) AS
...
Jika Anda membuat baris mengetik saat Anda pergi, Anda dapat mengembalikan catatan anonim:
CREATE FUNCTION foo()
RETURNS SETOF record AS
...
Tapi kemudian Anda harus memberikan daftar definisi kolom dengan setiap panggilan, jadi saya hampir tidak pernah menggunakannya.
Saya tidak akan menggunakan SELECT *
memulai dengan. Gunakan daftar kolom definitif untuk kembali dan nyatakan jenis pengembalian Anda sesuai dengan itu:
CREATE OR REPLACE FUNCTION func_a(username text = '', databaseobject text = '')
RETURNS TABLE(col1 int, col2 text, col3 date)
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE
format ($f$SELECT v1.col1, v1.col2, v2.col3
FROM %s v1 LEFT JOIN %I v2 USING (id)$f$
, CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
, databaseobject);
END
$func$;
Untuk kueri yang sepenuhnya dinamis, pertimbangkan untuk membuat kueri di klien Anda sebagai permulaan, daripada menggunakan fungsi.
Anda perlu memahami dasar-dasarnya terlebih dahulu:
- Memfaktorkan ulang fungsi PL/pgSQL untuk mengembalikan output dari berbagai kueri SELECT
- PL/pgSQL di manual Postgres
Lalu ada opsi yang lebih maju dengan tipe polimorfik, yang memungkinkan Anda meneruskan tipe pengembalian pada waktu panggilan. Selengkapnya di bab terakhir:
- Memfaktorkan ulang fungsi PL/pgSQL untuk mengembalikan output dari berbagai kueri SELECT