Ada ruang untuk perbaikan:
CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
, ends_with text = NULL)
RETURNS SETOF lookups.countries AS
$func$
DECLARE
sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
IF ends_with IS NOT NULL THEN
sql := sql || ' AND country_name <= $2';
END IF;
RETURN QUERY EXECUTE sql
USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;
-- the rest is default settings
Poin utama
-
PostgreSQL 8.4 memperkenalkan
USING
klausa untukEXECUTE
, yang berguna karena beberapa alasan. Rekap dalam manual:String perintah dapat menggunakan nilai parameter, yang dirujuk dalam perintah sebagai
$1, $2
, dll. Simbol-simbol ini mengacu pada nilai yang diberikan dalamUSING
ayat. Metode ini sering lebih disukai daripada memasukkan nilai data ke dalam string perintah sebagai teks:metode ini menghindari overhead run-time dari mengubah nilai menjadi teks dan sebaliknya, dan jauh lebih rentan terhadap serangan injeksi SQL karena tidak perlu mengutip atau melarikan diri.IOW, ini lebih aman dan lebih cepat daripada membangun string kueri dengan representasi teks dari parameter, bahkan ketika dibersihkan dengan
quote_literal()
.
Perhatikan bahwa$1, $2
dalam string kueri mengacu pada nilai yang disediakan diUSING
klausa, tidak ke parameter fungsi. -
Saat Anda mengembalikan
SELECT * FROM lookups.countries
, Anda dapat menyederhanakanRETURN
deklarasi seperti yang ditunjukkan:RETURNS SETOF lookups.countries
Di PostgreSQL ada tipe komposit yang ditentukan untuk setiap tabel secara otomatis. Gunakan. Efeknya adalah bahwa fungsinya tergantung pada jenisnya dan Anda mendapatkan pesan kesalahan jika Anda mencoba mengubah tabel. Jatuhkan &buat ulang fungsi dalam kasus seperti itu.
Ini mungkin atau mungkin tidak diinginkan - umumnya memang begitu! Anda ingin mengetahui efek samping jika Anda mengubah tabel. Cara Anda memilikinya, fungsi Anda akan terputus secara diam-diam dan memunculkan pengecualian pada panggilan berikutnya.
-
Jika Anda memberikan default eksplisit untuk parameter kedua dalam deklarasi seperti yang ditunjukkan, Anda dapat (tetapi tidak harus) menyederhanakan panggilan jika Anda tidak ingin menetapkan batas atas dengan
ends_with
.SELECT * FROM report_get_countries_new('Zaire');
bukannya:
SELECT * FROM report_get_countries_new('Zaire', NULL);
Waspadai fungsi yang berlebihan dalam konteks ini.
-
Jangan mengutip nama bahasa
bahkan jika itu ditoleransi (untuk saat ini). Ini adalah pengenal.'plpgsql' -
Anda dapat menetapkan variabel pada waktu deklarasi. Menghemat satu langkah ekstra.
-
Parameter diberi nama di header. Lepaskan kalimat yang tidak masuk akal:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;