Documentazione di PostgreSQL 9.0 > Programmazione del server > PL/pgSQL - Linguaggio procedurale SQL > Dichiarazioni
PrecedenteStruttura di PL/pgSQLEspressioniSuccessivo

39.3. Dichiarazioni

Tutte le variabili usate in un blocco devono essere dichiarate nella sezione delle dichiarazioni del blocco. (Le uniche eccezioni sono che la variabile loop di un ciclo FOR che itera su un intervallo di valori interi è automaticamente dichiarata come una variabile intera, come anche la variabile loop di un ciclo FOR che itera sul risultato di un cursore viene automaticamente dichiarata come una variabile record).

Le variabili PL/pgSQL possono avere qualsiasi tipo di dato SQL, tipo integer, varchar e char.

Ecco alcuni esempi di dichiarazione di variabili:

user_id integer;
quantity numeric(5);
url varchar;
myrow tablename%ROWTYPE;
myfield tablename.columnname%TYPE;
arow RECORD;

La sintassi generale di una dichiarazione di variabile è:

name [ CONSTANT ] type [ NOT NULL ] [ { DEFAULT | := } expression ];

La clausola DEFAULT, se fornita, specifica il valore iniziale assegnato alla variabile quando viene specificato il blocco. Se la clausola DEFAULT non è fornita allora la variabile è inizializzata al valore SQL null. L'opzione CONSTANT evita che la variabile possa essere assegnata, così quel valore rimarrà costante per tutta la durata del blocco. Se è specificato NOT NULL, un'assegnazione di un valore null risulterà in un errore durante l'esecuzione. Tutte le variabili dichiarate come NOT NULL devono avere un valore non null di default specificato.

Il valore di default di una variabile è valutato e assegnato alla variabile ogni volta che il blocco è iniziato (non solo una volta per chiamata di funzione). Quindi, per esempio, assegnare now() a una variabile di tipo timestamp fa sì che la variabile avrà l'orario della chiamata di fuzione corrente, non l'orario in cui la funzione è stata precompilata.

Examples:

quantity integer DEFAULT 32;
url varchar := 'http://mysite.com';
user_id CONSTANT integer := 10;

39.3.1. Dichiarazione di parametri di funzione

I parametri passati alle funzioni sono chiamati con gli identificatori $1, $2, ecc. Opzionalmente, possono essere dichiarati degli alias per $n nomi di parametri per aumentare la leggibilità. Sia l'alias che l'identificatore numerico possono quindi essere usati per riferirsi al valore del parametro.

Ci sono due modi di creare un alias. Il modo preferito è di dare un nome al parametro nel comando CREATE FUNCTION, per esempio:

CREATE FUNCTION sales_tax(subtotal real) RETURNS real AS $$
BEGIN
    RETURN subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;

L'altro modo, che era l'unico disponibile prima di PostgreSQL™ 8.0, è di dichiarare esplicitamente un alias, usando la sintassi di dichiarazione

name ALIAS FOR $n;

Lo stesso esempio in questo stile somiglia a:

CREATE FUNCTION sales_tax(real) RETURNS real AS $$
DECLARE
    subtotal ALIAS FOR $1;
BEgin
    RETURN subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;

[Nota]

Nota

Questi due esempi non sono perfettamente equivalenti. Nel primo caso, subtotal potrebbe essere riferito come sales_tax.subtotal, ma nel secondo caso non potrebbe. (Dato che abbiamo attaccato un'etichetta al blocco interno, subtotal potrebbe essere qualificato con quell'etichetta, invece).

Altri esempi:

CREATE FUNCTION instr(varchar, integer) RETURNS integer AS $$
DECLARE
    v_string ALIAS FOR $1;
    index ALIAS FOR $2;
BEgin
    -- alcuni calcoli usando v_string e index
END;
$$ LANGUAGE plpgsql;


CREATE FUNCTION concat_selected_fields(in_t sometablename) RETURNS text AS $$
BEgin
    RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7;
END;
$$ LANGUAGE plpgsql;

Quando una funzione PL/pgSQL è dichiarata con parametri di output, ai parametri di output sono dati $n nomi e opzionalmente alias nello stesso modo dei normali parametri di input. Un parametro di output è effettivamente una variabile che parte NULL; dovrebbe essere assegnata durante l'esecuzione della funzione. Il valore finale del parametro è cosa viene restituito. Per esempio, l'esempio delle sales_tax potrebbe anche essere fatto in questo modo:

CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$
BEgin
    tax := subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;

Notare che si è omesso RETURNS real - potevamo includerlo, ma sarebbe stato ridondante.

I parametri di output sono utili quando si restituiscono molteplivi valori. Un esempio banale è:

CREATE FUNCTION sum_n_product(x int, y int, OUT sum int, OUT prod int) AS $$
BEgin
    sum := x + y;
    prod := x * y;
END;
$$ LANGUAGE plpgsql;

Come discusso in Sezione 35.4.4, «SQL Functions with Output Parameters», questo crea effettivamente un tipo record anonimo per i risultati della funzione. Se viene specificata una clausola RETURNS, deve essere specificato RETURNS record.

Un altro modo di dichiarare una funzione PL/pgSQL è con RETURNS TABLE, per esempio:

CREATE FUNCTION extended_sales(p_itemno int)
RETURNS TABLE(quantity int, total numeric) AS $$
BEgin
    RETURN QUERY SELECT quantity, quantity * price FROM sales
                 WHERE itemno = p_itemno;
END;
$$ LANGUAGE plpgsql;

Questo è esattamente equivalente a dichiarare uno o più parametri OUT e specificare RETURNS SETOF sometype.

Quando il tipo di ritorno di una funzione PL/pgSQL viene dichiarata come un tipo polimorfico (anyelement, anyarray, anynonarray, or anyenum), viene creato un parametro speciale $0 Il suo tipo di dato è effettivamente il tipo di ritorno della funzione, come dedotto fagli effettivi tipi di input (si veda Sezione 35.2.5, «Tipi polimorfici»). Questo permette alla funzione di accedere il suo effettivo tipo di ritorno come mostrato in Sezione 39.3.3, «Copiare tipi». $0 viene inizializzato a null e può essere modificato dalla funzione, così può essere usato per tenere il valore di ritorno se lo si desidera, anche se non è richiesto. È possibile dare un alias a $0. Per esempio, questa funzione funziona su qualsiasi tipo di dato che ha un operatore +:

CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement)
RETURNS anyelement AS $$
DECLARE
    result ALIAS FOR $0;
BEgin
    result := v1 + v2 + v3;
    RETURN result;
END;
$$ LANGUAGE plpgsql;

Lo stesso effetto può essere ottenuto dichiarando uno o più parametri come tipi polimorfici. In questo caso il parametro speciale $0 non viene usato; i parametri di output stessi servono allo stesso scopo. PEr esempio:

CREATE FUNCTION add_three_values(v1 anyelement, v2 anyelement, v3 anyelement,
                                 OUT sum anyelement)
AS $$
BEgin
    sum := v1 + v2 + v3;
END;
$$ LANGUAGE plpgsql;

39.3.2. ALIAS

newname ALIAS FOR oldname;

La sintassi di ALIAS è più generale rispetto a come suggerito nella sezione precedente: è possibile dichiarare un alias per qualsiasi variabile, non solo parametri di funzione. L'uso pratico principale per questo è di assegnare un nome diverso per variabili con nomi predeterminati, tipo NEW o OLD all'interno di una procedura trigger.

Esempi:

DECLARE
  prior ALIAS FOR old;
  updated ALIAS FOR new;

Dato che ALIAS crea due modi differenti per nominare lo stesso oggetto, l'uso incontrollato può confondere. È meglio usarlo solo per lo scopo di sovrascrivere nomi predeterminati.

39.3.3. Copiare tipi

variable%TYPE

%TYPE fornisce il tipo di dato di una variabile o una colonna di tabella. È possibile usarlo per dichiarare variabili che conterranno valori di database. Per esempio, diciamo che si ha una colonna chiamata user_id nella tabella users. Per dichiarare una variabile con lo stesso tipo di dato di users.user_id scrivere:

user_id users.user_id%TYPE;

Usando %TYPE non si ha bisogno di conoscere il tipo di dato della struttura a cui ci si riferisce, e più importante, se il tipo di dato dell'elemento riferito in futuro cambia (per esempio: si cambia il tipo di user_id da integer a real), non ci sarà bisogno di cambiare la definizione di funzione.

%TYPE è particolarmente utile in funzioni polimorfiche, dato che i tipi di dato necessari per le variabili interne possono cambiare da una chiamata alla successiva. Variabili appropriate possono essere create applicando %TYPE agli argomenti della funzione o agli argomenti del risultato.

39.3.4. Tipi riga

name table_name%ROWTYPE;
name composite_type_name;

Una variabile di un tipo composto viene chiamata variabile row (o variabile tipo riga). Tale variabile può contenere una riga intera del risultato di una query SELECT o FOR, a patto che l'insieme delle colonne della query corrisponda al tipo dichiarato della variabile. Si accede ai campi individuali del valore della riga usando la solita notazione con il punto, per esempio rowvar.field.

Una variabile riga può essere dichiarata per avere lo stesso tipo delle righe di una tabella o vista esistente, usando la notazione table_name%ROWTYPE; o può essere dichiarata fornendo un nome di tipo composto. (Dato che ogni tabella ha un tipo composto associato dello stesso nome, attualmente in PostgreSQL™ non importa se si scrive %ROWTYPE o no. Ma la forma con %ROWTYPE è più portabile).

I parametri di una funzione possono essere tipi composti (righe di tabella complete). In tal caso, l'identificatore corrispondente $n sarà una variabile riga, e i campi possono essere selezionati da essa, per esempio $1.user_id.

Solo le colonne definite dall'utente di una riga di tabella sono accessibili in una variabile di tipo riga, non l'OID o altre colonne di sistema (dato che la riga poteva provenire da una vista). I campi del tipo riga ereditano la dimensione e la precisione dei campi della tabella per i tipi di dato come char(n).

Ecco un esempio dell'utilizzo di tipi composti. table1 e table2 sono tabelle esistenti aventi almeno i campi menzionati:

CREATE FUNCTION merge_fields(t_row table1) RETURNS text AS $$
DECLARE
    t2_row table2%ROWTYPE;
BEgin
    SELECT * INTO t2_row FROM table2 WHERE ... ;
    RETURN t_row.f1 || t2_row.f3 || t_row.f5 || t2_row.f7;
END;
$$ LANGUAGE plpgsql;

SELECT merge_fields(t.*) FROM table1 t WHERE ... ;

39.3.5. Tipi record

name RECORD;

Le variabili record sono simili alle variabili di tipo riga, ma non hanno strutture predefinite. Esse si preoccupano dell'effettiva struttura della riga a cui sono assegnate durante un comando SELECT o FOR. La sottostruttura di una variabile record può cambiare ogni volta che viene assegnata. Una conseguenza di questo è che finchè una variabile record non è assegnata, non ha sottostrutture, e qualsiasi tentativo di accedere ad un campo in essa genera un errore in fase di esecuzione.

Notare che RECORD non è un vero tipo di dato, solo un segnaposto. Ci si dovrebbe rendere conto che quando una funzione PL/pgSQL viene dichiarata per ritornare un tipo record, non è esattamente lo stesso concetto di una variabile record, anche se tale funzuione potrebbe usare una variabile recordo per contenere il suo risultato. In emtrambi i casi la struttura effettiva della riga è sconosciuta quando viene scritta la funzione, ma per una funzione che ritorna record l'effettiva struttura viene determinata quando viene fatto il parsing della query chiamante, mentre una variabile record può cambiare la sua struttura di riga al volo.

Documentazione di PostgreSQL 9.0 > Programmazione del server > PL/pgSQL - Linguaggio procedurale SQL > Dichiarazioni
PrecedenteStruttura di PL/pgSQLEspressioniSuccessivo