Asumiendo id_pracownika
es la PRIMARY KEY
de la mesa. O al menos definido UNIQUE
. (Si no es NOT NULL
, NULL es un caso de esquina.)
SELECT
o INSERT
Su función es otra implementación de "SELECCIONAR o INSERTAR", una variante de UPSERT
problema, que es más complejo frente a la carga de escritura simultánea de lo que podría parecer. Ver:
- ¿Es SELECCIONAR o INSERTAR en una función propensa a condiciones de carrera?
Con UPSERT en Postgres 9.5 o posterior
En Postgres 9.5 o posterior, use UPSERT (INSERT ... ON CONFLICT ...
) Detalles en Postgres Wiki. Esta nueva sintaxis hace un trabajo limpio :
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$;
Nombres de columna de calificación de tabla para eliminar la ambigüedad cuando sea necesario. (También puede prefijar los parámetros de la función con el nombre de la función, pero eso se vuelve incómodo fácilmente).
Pero los nombres de las columnas en la lista de objetivos de un INSERT
puede no estar calificado para la mesa. (Nunca ambiguo de todos modos.)
Es mejor evitar tales ambigüedades a priori, eso es menos propenso a errores. A algunos (incluyéndome a mí) les gusta hacer eso prefijando todos los parámetros de funciones y variables con un guión bajo.
Si definitivamente necesita un nombre de columna como nombre de parámetro de función también, una forma de evitar colisiones de nombres es usar un ALIAS
dentro de la función. Uno de los casos raros donde ALIAS
es realmente útil.
O haga referencia a los parámetros de la función por posición ordinal:$1
para id_pracownika
en este caso.
Si todo lo demás falla, puede decidir qué tiene prioridad configurando #variable_conflict
. Ver:
- Conflicto de nombre entre el parámetro de la función y el resultado de JOIN con la cláusula USING
Hay más:
-
Hay complejidades en
RETURNING
cláusula en un UPSERT. Ver:- ¿Cómo usar RETURNING con ON CONFLICT en PostgreSQL?
-
Los literales de cadena (constantes de texto) deben estar entre comillas simples:'OK', no
. Ver:"OK"
- Insertar texto con comillas simples en PostgreSQL
-
Asignar variables es comparativamente más caro que en otros lenguajes de programación. Mantenga las asignaciones al mínimo para obtener el mejor rendimiento en plpgsql. Haz todo lo que puedas en sentencias SQL directamente.
-
VOLATILE COST 100
son decoradores predeterminados para funciones. No hay necesidad de deletrearlos.
Sin UPSERT en Postgres 9.4 o anterior
...
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;
...
En un EXISTS
expresión, el SELECT
la lista no importa. SELECT id_pracownika
, SELECT 1
, o incluso SELECT 1/0
- todos iguales. Simplemente use un SELECT
vacío lista. Solo importa la existencia de cualquier fila calificada. Ver:
- ¿Qué es más fácil de leer en las subconsultas EXISTS?