Forudsat id_pracownika
er den PRIMARY KEY
af bordet. Eller i det mindste defineret UNIQUE
. (Hvis det ikke er NOT NULL
, NULL er en hjørnekasse.)
SELECT
eller INSERT
Din funktion er en anden implementering af "SELECT or INSERT" - en variant af UPSERT
problem, som er mere komplekst i lyset af samtidig skrivebelastning, end det ser ud til. Se:
- Er SELECT eller INSERT i en funktion, der er tilbøjelig til løbsforhold?
Med UPSERT i Postgres 9.5 eller nyere
I Postgres 9.5 eller nyere brug UPSERT (INSERT ... ON CONFLICT ...
) Detaljer i Postgres Wiki. Denne nye syntaks gør et rent stykke arbejde :
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$;
Tabelkvalificerer kolonnenavne for at tvetydige, hvor det er nødvendigt. (Du kan også præfikse funktionsparametre med funktionsnavnet, men det bliver nemt akavet.)
Men kolonnenavne i mållisten for en INSERT
er muligvis ikke bordkvalificeret. (Aldrig tvetydig alligevel.)
Det er bedst at undgå sådanne uklarheder på forhånd, det er mindre udsat for fejl. Nogle (inklusive mig) kan lide at gøre det ved at sætte en understregning foran alle funktionsparametre og variable.
Hvis du positivt bruger et kolonnenavn som funktionsparameternavn også, en måde at undgå navngivningskollisioner på er at bruge et ALIAS
inde i funktionen. Et af de sjældne tilfælde, hvor ALIAS
er faktisk nyttigt.
Eller reference funktionsparametre efter ordensposition:$1
for id_pracownika
i dette tilfælde.
Hvis alt andet fejler, kan du bestemme, hvad der skal have forrang ved at indstille #variable_conflict
. Se:
- Navngivningskonflikt mellem funktionsparameter og resultat af JOIN med USING-sætning
Der er mere:
-
Der er forviklinger ved
RETURNING
klausul i en UPSERT. Se:- Hvordan bruger man RETURNING med ON CONFLICT i PostgreSQL?
-
Strengliteraler (tekstkonstanter) skal være omgivet af enkelte anførselstegn:'OK', ikke
. Se:"OK"
- Indsæt tekst med enkelte anførselstegn i PostgreSQL
-
At tildele variabler er forholdsvis dyrere end i andre programmeringssprog. Hold opgaver på et minimum for den bedste ydeevne i plpgsql. Gør så meget som muligt i SQL-sætninger direkte.
-
VOLATILE COST 100
er standard dekoratører til funktioner. Det er ikke nødvendigt at stave dem ud.
Uden UPSERT i Postgres 9.4 eller ældre
...
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;
...
I en EXISTS
udtryk, SELECT
listen er ligegyldig. SELECT id_pracownika
, SELECT 1
, eller endda SELECT 1/0
- alt det samme. Bare brug en tom SELECT
liste. Kun eksistensen af en kvalificerende række har betydning. Se:
- Hvad er nemmere at læse i EXISTS underforespørgsler?