sql >> Base de Datos >  >> RDS >> PostgreSQL

Nombre de columna PL/pgSQL igual que variable

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 "OK" . Ver:

    • 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?