Ervan uitgaande dat id_pracownika
is de PRIMARY KEY
van de tafel. Of in ieder geval gedefinieerd UNIQUE
. (Als het niet NOT NULL
is , NULL is een hoekgeval.)
SELECT
of INSERT
Jouw functie is een andere implementatie van "SELECT or INSERT" - een variant van de UPSERT
probleem, dat complexer is in het licht van gelijktijdige schrijfbelasting dan het lijkt. Zie:
- Is SELECT of INSERT in een functie die vatbaar is voor race-omstandigheden?
Met UPSERT in Postgres 9.5 of hoger
Gebruik in Postgres 9.5 of later UPSERT (INSERT ... ON CONFLICT ...
) Details in de Postgres Wiki. Deze nieuwe syntaxis doet schoon werk :
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$;
Kwalificeer kolomnamen voor tabellen om waar nodig ondubbelzinnig te maken. (Je kunt functieparameters ook vooraf laten gaan door de functienaam, maar dat wordt al snel lastig.)
Maar kolomnamen in de doellijst van een INSERT
mogelijk niet tafelgekwalificeerd. (In ieder geval nooit dubbelzinnig.)
Vermijd dergelijke dubbelzinnigheden best a priori, dat is minder foutgevoelig. Sommigen (waaronder ikzelf) doen dat graag door alle functieparameters en variabelen vooraf te laten gaan met een onderstrepingsteken.
Als u zeker nodig een kolomnaam ook als functieparameternaam, een manier om naamgevingsbotsingen te voorkomen is het gebruik van een ALIAS
binnen de functie. Een van de zeldzame gevallen waarin ALIAS
is eigenlijk handig.
Of verwijs naar functieparameters op ordinale positie:$1
voor id_pracownika
in dit geval.
Als al het andere faalt, kun je beslissen wat voorrang heeft door #variable_conflict
in te stellen . Zie:
- Naamconflict tussen functieparameter en resultaat van JOIN met de clausule USING
Er is meer:
-
Er zijn ingewikkeldheden aan de
RETURNING
clausule in een UPSERT. Zie:- Hoe RETURNING gebruiken met ON CONFLICT in PostgreSQL?
-
Letterlijke tekenreeksen (tekstconstanten) moeten tussen enkele aanhalingstekens staan:'OK', niet
. Zie:"OK"
- Tekst invoegen met enkele aanhalingstekens in PostgreSQL
-
Het toewijzen van variabelen is relatief duurder dan in andere programmeertalen. Beperk opdrachten tot een minimum voor de beste prestaties in plpgsql. Doe zoveel mogelijk rechtstreeks in SQL-instructies.
-
VOLATILE COST 100
zijn standaard decorateurs voor functies. Het is niet nodig om die te spellen.
Zonder UPSERT in Postgres 9.4 of ouder
...
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;
...
In een EXISTS
uitdrukking, de SELECT
lijst maakt niet uit. SELECT id_pracownika
, SELECT 1
, of zelfs SELECT 1/0
- allemaal hetzelfde. Gebruik gewoon een lege SELECT
lijst. Alleen het bestaan van een kwalificerende rij is van belang. Zie:
- Wat is gemakkelijker te lezen in EXISTS-subquery's?