PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Der PL/pgSQL-Spaltenname ist derselbe wie die Variable

Angenommen id_pracownika ist der PRIMARY KEY des Tisches. Oder zumindest UNIQUE definiert . (Wenn es nicht NOT NULL ist , NULL ist ein Eckfall.)

SELECT oder INSERT

Ihre Funktion ist eine weitere Implementierung von "SELECT or INSERT" - eine Variante von UPSERT Problem, das angesichts der gleichzeitigen Schreiblast komplexer ist, als es scheinen mag. Siehe:

  • Ist SELECT oder INSERT in einer Funktion anfällig für Race-Conditions?

Mit UPSERT in Postgres 9.5 oder höher

Verwenden Sie in Postgres 9.5 oder höher UPSERT (INSERT ... ON CONFLICT ... ) Details im Postgres-Wiki. Diese neue Syntax macht einen sauberen Job :

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

Tabellenqualifizieren Sie Spaltennamen, um sie bei Bedarf zu disambiguieren. (Sie können Funktionsparametern auch den Funktionsnamen voranstellen, aber das wird leicht umständlich.)
Aber Spaltennamen in der Zielliste eines INSERT möglicherweise nicht tabellenqualifiziert. (Jedenfalls nie mehrdeutig.)

Vermeiden Sie solche Mehrdeutigkeiten am besten a priori, das ist weniger fehleranfällig. Einige (mich eingeschlossen) machen das gerne, indem sie allen Funktionsparametern und Variablen einen Unterstrich voranstellen.

Wenn Sie unbedingt brauchen auch ein Spaltenname als Funktionsparametername, eine Möglichkeit, Namenskollisionen zu vermeiden, ist die Verwendung eines ALIAS innerhalb der Funktion. Einer der seltenen Fälle, in denen ALIAS ist tatsächlich nützlich.

Oder referenzieren Sie Funktionsparameter nach Ordnungsposition:$1 für id_pracownika in diesem Fall.

Wenn alles andere fehlschlägt, können Sie entscheiden, was Vorrang hat, indem Sie #variable_conflict setzen . Siehe:

  • Namenskonflikt zwischen Funktionsparameter und Ergebnis von JOIN mit USING-Klausel

Es gibt noch mehr:

  • Es gibt Feinheiten beim RETURNING Klausel in einem UPSERT. Siehe:

    • Wie verwendet man RETURNING mit ON CONFLICT in PostgreSQL?
  • Zeichenfolgenliterale (Textkonstanten) müssen in einfache Anführungszeichen gesetzt werden:'OK', nicht "OK" . Siehe:

    • Text mit einfachen Anführungszeichen in PostgreSQL einfügen
  • Die Zuweisung von Variablen ist vergleichsweise aufwendiger als in anderen Programmiersprachen. Beschränken Sie die Zuweisungen auf ein Minimum, um die beste Leistung in plpgsql zu erzielen. Machen Sie so viel wie möglich direkt in SQL-Anweisungen.

  • VOLATILE COST 100 sind Standarddekorateure für Funktionen. Sie müssen diese nicht buchstabieren.

Ohne UPSERT in Postgres 9.4 oder älter

...
   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 einem EXISTS Ausdruck, der SELECT Liste spielt keine Rolle. SELECT id_pracownika , SELECT 1 , oder sogar SELECT 1/0 - alles das selbe. Verwenden Sie einfach ein leeres SELECT aufführen. Nur das Vorhandensein einer qualifizierenden Zeile ist von Bedeutung. Siehe:

  • Was ist in EXISTS-Unterabfragen einfacher zu lesen?