Za předpokladu id_pracownika
je PRIMARY KEY
tabulky. Nebo alespoň definované UNIQUE
. (Pokud to není NOT NULL
, NULL je rohový případ.)
SELECT
nebo INSERT
Vaše funkce je další implementací "SELECT or INSERT" - varianta UPSERT
problém, který je při současném zatížení zápisu složitější, než by se mohlo zdát. Viz:
- Je SELECT nebo INSERT ve funkci náchylný k závodům?
S UPSERT v Postgres 9.5 nebo novější
V Postgres 9.5 nebo novějším použijte UPSERT (INSERT ... ON CONFLICT ...
) Podrobnosti na Postgres Wiki. Tato nová syntaxe dělá čistou práci :
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$;
Názvy sloupců kvalifikujte podle tabulky tak, aby byly v případě potřeby jednoznačné. (Parametry funkce můžete také předřadit názvem funkce, ale to se snadno stane nešikovným.)
Ale názvy sloupců v cílovém seznamu INSERT
nemusí být kvalifikované pro stůl. (Stejně nikdy ne dvojznačné.)
Takovým nejednoznačnostem se nejlépe vyhněte a priori, je to méně náchylné k chybám. Někteří (včetně mě) to rádi dělají tak, že všechny parametry funkcí a proměnnou označují podtržítkem.
Pokud nutně potřebujete název sloupce také jako název parametru funkce, jeden způsob, jak se vyhnout kolizím pojmenování, je použít ALIAS
uvnitř funkce. Jeden ze vzácných případů, kdy ALIAS
je skutečně užitečné.
Nebo odkazujte na parametry funkce podle pořadové pozice:$1
pro id_pracownika
v tomto případě.
Pokud vše ostatní selže, můžete se rozhodnout, co má přednost, nastavením #variable_conflict
. Viz:
- Konflikt pojmenování mezi parametrem funkce a výsledkem JOIN s klauzulí USING
Je toho víc:
-
RETURNING
má složitost doložka v UPSERT. Viz:- Jak používat RETURNING s ON CONFLICT v PostgreSQL?
-
Řetězcové literály (textové konstanty) musí být uzavřeny v jednoduchých uvozovkách:'OK', nikoli
. Viz:"OK"
- Vložit text s jednoduchými uvozovkami v PostgreSQL
-
Přiřazení proměnných je poměrně dražší než v jiných programovacích jazycích. Pro dosažení nejlepšího výkonu v plpgsql udržujte úkoly na minimu. Udělejte co nejvíce přímo v příkazech SQL.
-
VOLATILE COST 100
jsou výchozí dekorátory funkcí. Není třeba je hláskovat.
Bez UPSERT v Postgres 9.4 nebo starší
...
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;
...
V EXISTS
výraz, SELECT
na seznamu nezáleží. SELECT id_pracownika
, SELECT 1
, nebo dokonce SELECT 1/0
- pořád to samé. Stačí použít prázdný SELECT
seznam. Důležitá je pouze existence jakékoli kvalifikační řady. Viz:
- Co je snazší číst v EXISTS dílčích dotazech?