PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Името на колоната PL/pgSQL е същото като променливата

Ако приемем id_pracownika е PRIMARY KEY на масата. Или поне дефиниран UNIQUE . (Ако не е NOT NULL , NULL е ъглов случай.)

SELECT или INSERT

Вашата функция е друга реализация на "SELECT или INSERT" - вариант на UPSERT проблем, който е по-сложен при едновременно натоварване при запис, отколкото може да изглежда. Вижте:

  • Изберете или INSERT във функция предразположени ли са условия на състезание?

С UPSERT в Postgres 9.5 или по-нова версия

В Postgres 9.5 или по-нова версия използвайте UPSERT (INSERT ... ON CONFLICT ... ) Подробности в Postgres Wiki. Този нов синтаксис върши чиста работа :

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

Квалифицирайте имената на колоните в таблицата, за да ги дезидентирате, когато е необходимо. (Можете също да поставите префикс на параметрите на функцията с името на функцията, но това става неудобно, лесно.)
Но имената на колони в целевия списък на INSERT може да не е квалифициран за маса. (Все пак никога не е двусмислено.)

Най-добре избягвайте подобни неясноти априори, това е по-малко податливо на грешки. Някои (включително мен) обичат да правят това, като поставят префикс на всички функционални параметри и променлива с долно черта.

Ако положително нуждате име на колона също като име на параметър на функцията, един от начините да избегнете сблъсъци с имена е да използвате ALIAS вътре във функцията. Един от редките случаи, когато ALIAS всъщност е полезно.

Или препоръчайте параметрите на функцията по редна позиция:$1 за id_pracownika в този случай.

Ако всичко друго не успее, можете да решите кое има предимство, като зададете #variable_conflict . Вижте:

  • Конфликт на именуване между параметър на функцията и резултат от JOIN с клауза USING

Има още:

  • Има тънкости в RETURNING клауза в UPSERT. Вижте:

    • Как да използвам RETURNING с ON CONFLICT в PostgreSQL?
  • Низовите литерали (текстови константи) трябва да бъдат затворени в единични кавички:'OK', а не "OK" . Вижте:

    • Вмъкнете текст с единични кавички в PostgreSQL
  • Присвояването на променливи е сравнително по-скъпо, отколкото в други езици за програмиране. Сведете заданията до минимум за най-добра производителност в plpgsql. Правете колкото е възможно повече в SQL изрази директно.

  • VOLATILE COST 100 са декоратори по подразбиране за функции. Няма нужда да ги изричате.

Без UPSERT в Postgres 9.4 или по-стара версия

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

В EXISTS израз, SELECT списъкът няма значение. SELECT id_pracownika , SELECT 1 , или дори SELECT 1/0 - все същото. Просто използвайте празен SELECT списък. От значение е само наличието на който и да е квалификационен ред. Вижте:

  • Какво е по-лесно за четене в 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. [Видео] Интегриране на данни с PostgreSQL

  2. Формулата на коефициента на корелация на Пиърсън в SQL

  3. Postgres връзката е затворена грешка в Spring Boot

  4. Името на колоната PL/pgSQL е същото като променливата

  5. PostgreSQL последователности без празнини