sql >> Database >  >> RDS >> PostgreSQL

PL/pgSQL-kolomnaam hetzelfde als variabele

Ervan uitgaande dat id_pracownika is de PRIMARY KEY van de tafel. Of in ieder geval gedefinieerd UNIQUE . (Als het niet NOT NULL is , NULL is een hoekgeval.)

SELECT of INSERT

Jouw functie is een andere implementatie van "SELECT or INSERT" - een variant van de UPSERT probleem, dat complexer is in het licht van gelijktijdige schrijfbelasting dan het lijkt. Zie:

  • Is SELECT of INSERT in een functie die vatbaar is voor race-omstandigheden?

Met UPSERT in Postgres 9.5 of hoger

Gebruik in Postgres 9.5 of later UPSERT (INSERT ... ON CONFLICT ... ) Details in de Postgres Wiki. Deze nieuwe syntaxis doet schoon werk :

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

Kwalificeer kolomnamen voor tabellen om waar nodig ondubbelzinnig te maken. (Je kunt functieparameters ook vooraf laten gaan door de functienaam, maar dat wordt al snel lastig.)
Maar kolomnamen in de doellijst van een INSERT mogelijk niet tafelgekwalificeerd. (In ieder geval nooit dubbelzinnig.)

Vermijd dergelijke dubbelzinnigheden best a priori, dat is minder foutgevoelig. Sommigen (waaronder ikzelf) doen dat graag door alle functieparameters en variabelen vooraf te laten gaan met een onderstrepingsteken.

Als u zeker nodig een kolomnaam ook als functieparameternaam, een manier om naamgevingsbotsingen te voorkomen is het gebruik van een ALIAS binnen de functie. Een van de zeldzame gevallen waarin ALIAS is eigenlijk handig.

Of verwijs naar functieparameters op ordinale positie:$1 voor id_pracownika in dit geval.

Als al het andere faalt, kun je beslissen wat voorrang heeft door #variable_conflict in te stellen . Zie:

  • Naamconflict tussen functieparameter en resultaat van JOIN met de clausule USING

Er is meer:

  • Er zijn ingewikkeldheden aan de RETURNING clausule in een UPSERT. Zie:

    • Hoe RETURNING gebruiken met ON CONFLICT in PostgreSQL?
  • Letterlijke tekenreeksen (tekstconstanten) moeten tussen enkele aanhalingstekens staan:'OK', niet "OK" . Zie:

    • Tekst invoegen met enkele aanhalingstekens in PostgreSQL
  • Het toewijzen van variabelen is relatief duurder dan in andere programmeertalen. Beperk opdrachten tot een minimum voor de beste prestaties in plpgsql. Doe zoveel mogelijk rechtstreeks in SQL-instructies.

  • VOLATILE COST 100 zijn standaard decorateurs voor functies. Het is niet nodig om die te spellen.

Zonder UPSERT in Postgres 9.4 of ouder

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

In een EXISTS uitdrukking, de SELECT lijst maakt niet uit. SELECT id_pracownika , SELECT 1 , of zelfs SELECT 1/0 - allemaal hetzelfde. Gebruik gewoon een lege SELECT lijst. Alleen het bestaan ​​van een kwalificerende rij is van belang. Zie:

  • Wat is gemakkelijker te lezen in EXISTS-subquery's?


  1. MySQL Group By en Som totale waarde van andere kolom

  2. SQLite DATEADD() Equivalent

  3. Hoe alias een veld of kolom in MySQL?

  4. Moeten nieuwe indexkolommen in de sleutel of worden opgenomen?