sql >> Databasteknik >  >> RDS >> PostgreSQL

PL/pgSQL kolumnnamn samma som variabel

Förutsatt id_pracownika är PRIMARY KEY av bordet. Eller åtminstone definierad UNIQUE . (Om det inte är NOT NULL , NULL är ett hörnfall.)

SELECT eller INSERT

Din funktion är en annan implementering av "SELECT or INSERT" - en variant av UPSERT problem, vilket är mer komplext inför samtidig skrivbelastning än det kan verka. Se:

  • Är SELECT eller INSERT i en funktion utsatt för tävlingsförhållanden?

Med UPSERT i Postgres 9.5 eller senare

I Postgres 9.5 eller senare använd UPSERT (INSERT ... ON CONFLICT ... ) Detaljer i Postgres Wiki. Den här nya syntaxen gör ett rent jobb :

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

Tabellkvalificerar kolumnnamn för att disambiguera där det behövs. (Du kan också prefixa funktionsparametrar med funktionsnamnet, men det blir lätt besvärligt.)
Men kolumnnamn i mållistan för en INSERT kanske inte är tabellkvalificerad. (Aldrig tvetydig i alla fall.)

Bäst att undvika sådana oklarheter a priori, det är mindre felbenäget. Vissa (inklusive jag) gillar att göra det genom att prefixa alla funktionsparametrar och variabler med ett understreck.

Om du verkligen behöver ett kolumnnamn som funktionsparameternamn också, ett sätt att undvika namnkollisioner är att använda en ALIAS inne i funktionen. Ett av de sällsynta fallen där ALIAS är faktiskt användbart.

Eller referera funktionsparametrar efter ordningsposition:$1 för id_pracownika i det här fallet.

Om allt annat misslyckas kan du bestämma vad som ska ha företräde genom att ställa in #variable_conflict . Se:

  • Namnkonflikt mellan funktionsparameter och resultat av JOIN med USING-sats

Det finns mer:

  • Det finns krångligheter med RETURNING klausul i en UPSERT. Se:

    • Hur använder man RETURNING med ON CONFLICT i PostgreSQL?
  • Strängliteraler (textkonstanter) måste omges av enkla citattecken:'OK', inte "OK" . Se:

    • Infoga text med enkla citattecken i PostgreSQL
  • Att tilldela variabler är jämförelsevis dyrare än i andra programmeringsspråk. Håll uppdragen till ett minimum för bästa prestanda i plpgsql. Gör så mycket som möjligt i SQL-satser direkt.

  • VOLATILE COST 100 är standardinredare för funktioner. Du behöver inte skriva ut dem.

Utan UPSERT i Postgres 9.4 eller äldre

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

I en EXISTS uttryck, SELECT listan spelar ingen roll. SELECT id_pracownika , SELECT 1 , eller till och med SELECT 1/0 - alla likadana. Använd bara en tom SELECT lista. Endast förekomsten av någon kvalificerande rad spelar roll. Se:

  • Vad är lättare att läsa i EXISTS-underfrågor?


  1. hur kopierar man data från fil till PostgreSQL med JDBC?

  2. Välj från tabell om posten finns i en annan tabell

  3. SQL Server bcp Utility och den numeriska datatypen

  4. SQL-frågeoptimering — Hur man avgör när och om det behövs