PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Nazwa kolumny PL/pgSQL taka sama jak zmienna

Zakładając id_pracownika to PRIMARY KEY tabeli. Lub przynajmniej zdefiniowany UNIQUE . (Jeśli nie jest NOT NULL , NULL to przypadek narożny.)

SELECT lub INSERT

Twoja funkcja to kolejna implementacja "SELECT lub INSERT" - wariant UPSERT problem, który jest bardziej złożony w obliczu współbieżnego obciążenia zapisu, niż mogłoby się wydawać. Zobacz:

  • Czy SELECT lub INSERT w funkcji podatnej na wyścigi?

Z UPSERT w Postgresie 9.5 lub nowszym

W Postgresie 9.5 lub nowszym użyj UPSERT (INSERT ... ON CONFLICT ... ) Szczegóły w Postgres Wiki. Ta nowa składnia wykonuje czystą pracę :

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$;

W razie potrzeby kwalifikuj nazwy kolumn do ujednoznacznienia. (Możesz także poprzedzić parametry funkcji nazwą funkcji, ale to staje się niezręczne, łatwo.)
Ale nazwy kolumn na liście docelowej INSERT może nie być zakwalifikowany do tabeli. (I tak nigdy nie jest dwuznaczny).

Najlepiej unikać takich niejasności a priori, to jest mniej podatne na błędy. Niektórzy (w tym ja) lubią to robić, poprzedzając wszystkie parametry funkcji i zmienne podkreśleniem.

Jeśli zdecydowanie potrzebujesz nazwa kolumny jako nazwa parametru funkcji, jednym ze sposobów uniknięcia kolizji nazw jest użycie ALIAS wewnątrz funkcji. Jeden z rzadkich przypadków, w których ALIAS jest rzeczywiście przydatne.

Lub odwołaj się do parametrów funkcji według pozycji porządkowej:$1 dla id_pracownika w tym przypadku.

Jeśli wszystko inne zawiedzie, możesz zdecydować, co ma pierwszeństwo, ustawiając #variable_conflict . Zobacz:

  • Konflikt nazw między parametrem funkcji a wynikiem JOIN z klauzulą ​​USING

Jest więcej:

  • Istnieją zawiłości RETURNING klauzula w UPSERT. Zobacz:

    • Jak używać RETURNING z ON CONFLICT w PostgreSQL?
  • Literały tekstowe (stałe tekstowe) muszą być ujęte w pojedyncze cudzysłowy:„OK”, a nie "OK" . Zobacz:

    • Wstaw tekst z pojedynczymi cudzysłowami w PostgreSQL
  • Przypisywanie zmiennych jest porównywalnie droższe niż w innych językach programowania. Ogranicz przypisania do minimum, aby uzyskać najlepszą wydajność w plpgsql. Zrób jak najwięcej bezpośrednio w instrukcjach SQL.

  • VOLATILE COST 100 są domyślnymi dekoratorami funkcji. Nie trzeba ich wyjaśniać.

Bez UPSERT w Postgresie 9.4 lub starszym

...
   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;
...

W EXISTS wyrażenie, SELECT lista nie ma znaczenia. SELECT id_pracownika , SELECT 1 , a nawet SELECT 1/0 - wszystkie takie same. Po prostu użyj pustego SELECT lista. Liczy się tylko istnienie jakiegokolwiek kwalifikującego się wiersza. Zobacz:

  • Co jest łatwiejsze do odczytania w podzapytaniach EXISTS?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Liczba warunkowych zapytań SQL

  2. Ustawianie limitu czasu połączenia z PDO

  3. Wydajność OLTP od PostgreSQL 8.3

  4. Jak przekonwertować ciąg na znacznik czasu w PostgreSQL

  5. 4 sposoby na wybranie zduplikowanych wierszy w PostgreSQL