CREATE FUNCTION (LANGUAGE sql) în PostgreSQL

Funcții, proceduri și triggere PostgreSQL 8.0+ (corp în stil standard SQL: RETURN / BEGIN ATOMIC: 14+)

Creează o funcție scrisă direct în SQL, pe care o poți folosi apoi în SELECT, WHERE sau în indecși.

Sintaxă SQL
CREATE [OR REPLACE] FUNCTION nume(param tip, ...)
    RETURNS tip | RETURNS TABLE (coloana tip, ...)
    LANGUAGE sql [IMMUTABLE | STABLE | VOLATILE]
    AS $$ interogare $$;

-- PostgreSQL 14+:
CREATE FUNCTION nume(param tip) RETURNS tip
    LANGUAGE sql RETURN expresie;

Ce face CREATE FUNCTION (LANGUAGE sql)

O funcție SQL salvează o expresie sau o interogare sub un nume. Corpul se scrie între $$ (dollar quoting), ca să nu fie nevoie să dublezi apostrofurile din interior. Rezultatul este valoarea ultimei interogări.

Cu RETURNS TABLE funcția returnează mai multe rânduri și se folosește în FROM, ca un tabel. Din PostgreSQL 14 corpul se poate scrie și în stil standard SQL (RETURN expresie sau BEGIN ATOMIC ... END), verificat la creare.

Marcajul de volatilitate ajută planificatorul: IMMUTABLE = același rezultat pentru aceleași argumente, mereu (poate fi folosită în indecși); STABLE = nu modifică date și dă același rezultat într-o interogare; VOLATILE (implicit) = orice altceva.

Parametri

Parametru Descriere
OR REPLACE Înlocuiește funcția existentă cu aceeași listă de parametri (tipul returnat nu se poate schimba).
RETURNS tip Tipul valorii returnate; SETOF tip sau RETURNS TABLE (...) pentru mai multe rânduri.
IMMUTABLE / STABLE / VOLATILE Cât de stabil este rezultatul.
STRICT Dacă un argument este NULL, rezultatul este NULL fără să ruleze funcția.

Ce returnează

Mesajul CREATE FUNCTION.

Exemple

Exemplul 1: Preț cu TVA

CREATE FUNCTION pret_cu_tva(pret numeric)
    RETURNS numeric
    LANGUAGE sql
    IMMUTABLE
    RETURN round(pret * 1.21, 2);

SELECT pret_cu_tva(100), pret_cu_tva(5.50);

Rezultat în psql

CREATE FUNCTION
 pret_cu_tva | pret_cu_tva 
-------------+-------------
      121.00 |        6.66
(1 row)

Exemplul 2: Funcție care returnează un tabel

CREATE FUNCTION clienti_din(p_oras text)
    RETURNS TABLE (id integer, nume text)
    LANGUAGE sql
    STABLE
AS $$
    SELECT c.id, c.nume FROM clienti c WHERE c.oras = p_oras ORDER BY c.nume;
$$;

SELECT * FROM clienti_din('Iași');

Rezultat în psql

CREATE FUNCTION
 id | nume  
----+-------
  1 | Ana
  4 | Ioana
  7 | Vlad
(3 rows)

Exemplul 3: Schimbarea tipului returnat

CREATE OR REPLACE FUNCTION pret_cu_tva(pret numeric)
    RETURNS text
    LANGUAGE sql
    RETURN round(pret * 1.21, 2)::text || ' lei';

Rezultat în psql

ERROR:  cannot change return type of existing function
HINT:  Use DROP FUNCTION pret_cu_tva(numeric) first.

Greșeli frecvente

  • Marchezi IMMUTABLE o funcție care citește din tabele sau folosește now(). Rezultatele pot fi greșite, mai ales în indecși.
  • Dai parametrilor același nume ca și coloanelor (oras) și interogarea devine ambiguă. Folosește un prefix (p_oras) sau alias de tabel.

Comenzi înrudite

  • CREATE FUNCTION (LANGUAGE plpgsql): Creează o funcție în PL/pgSQL, limbajul procedural al PostgreSQL: variabile, IF, bucle, tratarea erorilor.
  • CREATE PROCEDURE și CALL: O procedură este ca o funcție, dar se apelează cu CALL și poate face COMMIT sau ROLLBACK în interior, de exemplu pentru prelucrări pe loturi.
  • CREATE TRIGGER: Rulează automat o funcție la INSERT, UPDATE sau DELETE pe un tabel, de exemplu pentru a completa coloana actualizat_la sau pentru jurnal de audit.