Dengan asumsi id_pracownika adalah PRIMARY KEY dari meja. Atau setidaknya didefinisikan UNIQUE . (Jika bukan NOT NULL , NULL adalah kasus sudut.)
SELECT atau INSERT
Fungsi Anda adalah implementasi lain dari "SELECT or INSERT" - varian dari UPSERT masalah, yang lebih kompleks dalam menghadapi beban tulis bersamaan daripada yang terlihat. Lihat:
- Apakah SELECT atau INSERT dalam fungsi rentan terhadap kondisi balapan?
Dengan UPSERT di Postgres 9.5 atau lebih baru
Di Postgres 9.5 atau yang lebih baru gunakan UPSERT (INSERT ... ON CONFLICT ... ) Detail di Wiki Postgres. Sintaks baru ini melakukan pekerjaan bersih :
CREATE OR REPLACE FUNCTION hire(
_id_pracownika integer
, _imie varchar
, _nazwisko varchar
, _miasto varchar
, _pensja real)
RETURNS text
LANGUAGE plpgsql AS
$func$
BEGIN
INSERT INTO pracownicy
( id_pracownika, imie, nazwisko, miasto, pensja)
VALUES (_id_pracownika,_imie,_nazwisko,_miasto,_pensja);
ON CONFLICT DO NOTHING
RETURNING 'OK';
IF NOT FOUND THEN
RETURN 'JUZ ISTNIEJE';
END IF;
END
$func$;
Nama kolom yang memenuhi syarat tabel untuk disambiguasi jika perlu. (Anda juga dapat memberi awalan parameter fungsi dengan nama fungsi, tetapi itu menjadi canggung, dengan mudah.)
Tetapi nama kolom dalam daftar target INSERT mungkin tidak memenuhi syarat meja. (Lagi pula, tidak pernah ambigu.)
Sebaiknya hindari ambiguitas seperti itu secara apriori, itu kurang rawan kesalahan. Beberapa (termasuk saya) suka melakukannya dengan mengawali semua parameter fungsi dan variabel dengan garis bawah.
Jika Anda benar-benar membutuhkan nama kolom sebagai nama parameter fungsi juga, salah satu cara untuk menghindari tabrakan penamaan adalah dengan menggunakan ALIAS di dalam fungsi. Salah satu kasus langka dimana ALIAS sebenarnya berguna.
Atau parameter fungsi referensi menurut posisi ordinal:$1 untuk id_pracownika dalam hal ini.
Jika semuanya gagal, Anda dapat memutuskan apa yang didahulukan dengan menyetel #variable_conflict . Lihat:
- Konflik penamaan antara parameter fungsi dan hasil JOIN dengan klausa USING
Masih ada lagi:
-
Ada seluk-beluk
RETURNINGklausa dalam UPSERT. Lihat:- Bagaimana cara menggunakan RETURNING dengan ON CONFLICT di PostgreSQL?
-
Literal string (konstanta teks) harus diapit oleh tanda kutip tunggal:'OK', bukan
. Lihat:"OK"- Menyisipkan teks dengan tanda kutip tunggal di PostgreSQL
-
Menetapkan variabel relatif lebih mahal daripada dalam bahasa pemrograman lain. Pertahankan tugas seminimal mungkin untuk kinerja terbaik di plpgsql. Lakukan sebanyak mungkin dalam pernyataan SQL secara langsung.
-
VOLATILE COST 100adalah dekorator default untuk fungsi. Tidak perlu mengejanya.
Tanpa UPSERT di Postgres 9.4 atau lebih lama
...
IF EXISTS (SELECT FROM pracownicy p
WHERE p.id_pracownika = hire.id_pracownika) THEN
RETURN 'JUZ ISTNIEJE';
ELSE
INSERT INTO pracownicy(id_pracownika,imie,nazwisko,miasto,pensja)
VALUES (hire.id_pracownika,hire.imie,hire.nazwisko,hire.miasto,hire.pensja);
RETURN 'OK';
END IF;
...
Dalam EXISTS ekspresi, SELECT daftar tidak masalah. SELECT id_pracownika , SELECT 1 , atau bahkan SELECT 1/0 - semua sama. Cukup gunakan SELECT empty yang kosong daftar. Hanya keberadaan baris kualifikasi yang penting. Lihat:
- Apa yang lebih mudah dibaca di subkueri EXISTS?