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
RETURNING
klausa 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 100
adalah 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?