Mempersiapkan
Rumus Anda terlihat seperti ini:
d*b+(l*4+r)+(i/d)+s
Saya akan mengganti variabel dengan $n
notasi sehingga mereka dapat diganti dengan nilai langsung di plpgsql EXECUTE
(lihat di bawah):
$1*$5+($3*4+$2)+($6/$1)+$4
Anda dapat menyimpan formula asli Anda tambahan (untuk mata manusia) atau menghasilkan formulir ini secara dinamis dengan ekspresi seperti:
SELECT regexp_replace(regexp_replace(regexp_replace(
regexp_replace(regexp_replace(regexp_replace(
'd*b+(l*4+r)+(i/d)+s'
, '\md\M', '$1', 'g')
, '\mr\M', '$2', 'g')
, '\ml\M', '$3', 'g')
, '\ms\M', '$4', 'g')
, '\mb\M', '$5', 'g')
, '\mi\M', '$6', 'g');
Pastikan saja, terjemahan Anda baik-baik saja. Beberapa penjelasan untuk ekspresi regexp :
\ m .. hanya cocok di awal kata
\ M .. hanya cocok di akhir kata
Parameter 4 'g'
.. ganti secara global
Fungsi inti
CREATE OR REPLACE FUNCTION f_calc(
d int -- days worked that month
,r int -- new nodes accuired
,l int -- loyalty score
,s numeric -- subagent commission
,b numeric -- base rate
,i numeric -- revenue gained
,formula text
,OUT result numeric
) RETURNS numeric AS
$func$
BEGIN
EXECUTE 'SELECT '|| formula
INTO result
USING $1, $2, $3, $4, $5, $6;
END
$func$ LANGUAGE plpgsql SECURITY DEFINER IMMUTABLE;
Panggilan:
SELECT f_calc(1, 2, 3, 4.1, 5.2, 6.3, '$1*$5+($3*4+$2)+($6/$1)+$4');
Pengembalian:
29.6000000000000000
Poin utama
Fungsi ini mengambil 6 parameter nilai dan formula text
sebagai 7. Saya menempatkan formula terakhir, jadi kita bisa menggunakan $1 .. $6
bukan $2 .. $7
. Hanya demi keterbacaan.
Saya menetapkan tipe data untuk nilai-nilai yang saya lihat cocok. Tetapkan jenis yang tepat (untuk menerapkan pemeriksaan kewarasan dasar) atau buat semuanya numeric
:
Masukkan nilai untuk eksekusi dinamis dengan USING
klausa. Ini menghindari bolak-balik dan membuat segalanya lebih sederhana, lebih aman dan lebih cepat.
Saya menggunakan OUT
parameter karena itu lebih elegan dan membuat sintaks yang lebih jelas lebih pendek. Final RETURN
tidak diperlukan, nilai parameter OUT dikembalikan secara otomatis.
Pertimbangkan kuliah tentang keamanan oleh @Chris dan bab "Menulis Fungsi Penjamin Keamanan dengan Aman" dalam manual. Dalam desain saya, satu-satunya titik injeksi adalah formula itu sendiri.
Anda dapat menggunakan default untuk beberapa parameter untuk lebih menyederhanakan panggilan.