I'm new to plpgsql and I'm trying to create function that will check if a certain value exists in table and if not will add a row.
CREATE OR REPLACE FUNCTION hire(
id_pracownika integer,
imie character varying,
nazwisko character varying,
miasto character varying,
pensja real)
RETURNS TEXT AS
$BODY$
DECLARE
wynik TEXT;
sprawdzenie INT;
BEGIN
sprawdzenie = id_pracownika;
IF EXISTS (SELECT id_pracownika FROM pracownicy WHERE id_pracownika=sprawdzenie) THEN
wynik = "JUZ ISTNIEJE";
RETURN wynik;
ELSE
INSERT INTO pracownicy(id_pracownika,imie,nazwisko,miasto,pensja)
VALUES (id_pracownika,imie,nazwisko,miasto,pensja);
wynik = "OK";
RETURN wynik;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
The issue is that I'm getting errors saying that id_pracownika
is a column name and a variable.
How to specify that "id_pracownika" in such context refers to column name?
It is a example tested by me where I use EXECUTE to run a select and put its result in a cursor, using dynamic column names.
1. Create the table:
2. Create the function:
3. Run the function
select fun_find_people('name', 'Cristian'); select fun_find_people('country', 'Chile');
Like @pozs commented, schema-qualify column names and prefix function parameters with the function name to disambiguate where necessary. Be aware, however, that column names in the target list of an
INSERT
may not be prefixed. Those are never ambiguous anyway.Like @Frank commented, it's best to avoid such ambiguities to begin with, that's less error prone. If you need a column name as function parameter name, too, one way to avoid naming collisions would be to use an
ALIAS
inside the function. That's one of the rare cases whereALIAS
is actually useful. Or you can reference input parameter by ordinal position:$1
forid_pracownika
in this case.But there is more:
String literals (text constants) must be enclosed in single quotes: 'OK', not
."OK"
The assignment operator in plpgsql is
:=
.In an
EXISTS
expression, it does not matter what you select.SELECT id_pracownika
is the same asSELECT 1
or evenSELECT 123/0
. Only the existence of a rows matters.Assigning variables is comparatively more expensive than in other programming languages. If there is an elegant way to save some of those operations, that's the preferable way in plpgsql. Do as much as possible in SQL statements directly.
VOLATILE COST 100
are default decorators for functions. You don't have to spell those out.SELECT
orINSERT
Your function is another implementation of "SELECT or INSERT" - a variant of the
UPSERT
problem, which is more complex in the face of concurrent write load than you might imagine. (Potential problems your simple solution ignores, btw, and can make it fail!) Details:UPSERT in Postgres 9.5
The Postgres team (most prominently Peter Geoghegan) has implemented UPSERT in Postgres 9.5. Details in the Postgres Wiki. This new syntax will do a clean job: