

 Amazon Redshift non supporterà più la creazione di nuovi Python UDFs a partire dalla Patch 198. Python esistente UDFs continuerà a funzionare fino al 30 giugno 2026. Per ulteriori informazioni, consulta il [post del blog](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Struttura di PL/pgSQL
<a name="c_PLpgSQL-structure"></a>

PL/pgSQL è un linguaggio procedurale con molte delle stesse costruzioni di altri linguaggi procedurali. 

**Topics**
+ [Blocco](#r_PLpgSQL-block)
+ [Dichiarazione di variabile](#r_PLpgSQL-variable-declaration)
+ [Dichiarazione alias](#r_PLpgSQL-alias-declaration)
+ [Variabili integrate](#r_PLpgSQL-builtin-variables)
+ [Tipi di record](#r_PLpgSQL-record-type)

## Blocco
<a name="r_PLpgSQL-block"></a>

PL/pgSQL è un linguaggio strutturato a blocchi. Il corpo completo di una procedura è definito in un blocco, che contiene dichiarazioni variabili e istruzioni PL/pgSQL. Un'istruzione può anche essere un blocco nidificato o un sottoblocco. 

Finire le dichiarazioni e le istruzioni con un punto e virgola. Segui la parola chiave END in un blocco o un sottoblocco con un punto e virgola. Non utilizzare il punto e virgola dopo le parole chiave DECLARE e BEGIN. 

Puoi scrivere tutte le parole chiave e tutti gli identificatori in un mix di maiuscolo e minuscolo. Gli identificatori vengono convertiti implicitamente in minuscolo a meno che siano racchiusi in virgolette doppie.

Un trattino doppio (--) inizia un commento che si estende alla fine della riga. Un /\$1 inizia un commento blocco che si estende alla prossima occorrenza di \$1/. Non è possibile nidificare commenti blocco. Tuttavia, è possibile racchiudere i commenti a doppio trattino in un commento blocco e un trattino doppio può nascondere i delimitatori del commento blocco /\$1 e \$1/.

Qualsiasi istruzione in una sezione istruzioni di un blocco può essere un sottoblocco. Puoi utilizzare sottoblocchi per un raggruppamento logico o per localizzare variabili di un gruppo piccolo di istruzioni.

```
[ <<label>> ]
[ DECLARE
  declarations ]
BEGIN
  statements
END [ label ];
```

Le variabili dichiarate nella sezione dichiarazioni prima di un blocco vengono inizializzate ai loro valori predefiniti ogni volta che viene inserito il blocco. In altre parole, non vengono inizializzati solo una volta per chiamata di funzione.

Di seguito viene riportato un esempio.

```
CREATE PROCEDURE update_value() AS $$
DECLARE
  value integer := 20;
BEGIN
  RAISE NOTICE 'Value here is %', value;  -- Value here is 20
  value := 50;
  --
  -- Create a subblock
  --
  DECLARE
    value integer := 80;
  BEGIN
    RAISE NOTICE 'Value here is %', value;  -- Value here is 80
  END;

  RAISE NOTICE 'Value here is %', value;  -- Value here is 50
END;
$$ LANGUAGE plpgsql;
```

Utilizza un'etichetta per identificare il blocco da utilizzare in un'istruzione EXIT o per qualificare i nome delle variabili dichiarate nel blocco.

Non confondere l'utilizzo di BEGIN/END per le istruzioni di raggruppamento in PL/pgSQL con i comandi del database per il controllo della transazione. BEGIN e END in PL/pgSQL sono solo per il raggruppamento. Non iniziano o terminano la transazione.

## Dichiarazione di variabile
<a name="r_PLpgSQL-variable-declaration"></a>

Dichiarare tutte le variabili in un blocco, ad eccezione delle variabili di loop, nella sezione DECLARE del blocco. Le variabili possono utilizzare qualsiasi tipo di dati Amazon Redshift valido. Per tipi di dati supportati, consultare [Tipi di dati](c_Supported_data_types.md). 

Le variabili PL/pgSQL possono essere qualsiasi tipo di dati supportati da Amazon Redshift, più `RECORD` e `refcursor`. Per ulteriori informazioni su `RECORD`, consulta [Tipi di record](#r_PLpgSQL-record-type). Per ulteriori informazioni su `refcursor`, consulta [Cursori](c_PLpgSQL-statements.md#r_PLpgSQL-cursors). 

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

Seguono delle dichiarazioni delle variabili di esempio.

```
customerID integer;
numberofitems numeric(6);
link varchar;
onerow RECORD;
```

La variabile per un loop FOR che effettua l'iterazione in una gamma di numeri interi viene dichiarata automaticamente come variabile di numero intero. 

La clausola DEFAULT, se fornita, specifica il valore iniziale assegnato alla variabile quando viene inserito il blocco. Se la clausola DEFAULT non viene fornita, la variabile viene inizializzata con il valore SQL NULL. L'opzione CONSTANT previene che la variabile venga assegnata, in modo che il suo valore rimanga constante per la durata del blocco. Se NOT NULL è specificato, un'assegnazione di un valore null risulta in errore di runtime. Tutte le variabili dichiarate come NOT NULL devono avere un valore predefinito non-null specificato.

Il valore predefinito viene valutato ogni volta che il blocco viene inserito. Ad esempio, l'assegnazione di `now()` a una variabile del tipo `timestamp` determina che la variabile abbia l'ora della chiamata di funzione corrente, non l'ora di quando la funzione è stata precompilata.

```
quantity INTEGER DEFAULT 32;
url VARCHAR := 'http://mysite.com';
user_id CONSTANT INTEGER := 10;
```

Il tipo di dati `refcursor` è il tipo di dati delle variabili di cursore nelle procedure archiviate. Un valore `refcursor` può essere restituito da una procedura archiviata. Per ulteriori informazioni, consultare [Restituzione di un set di risultati di una stored procedure](stored-procedure-result-set.md).

## Dichiarazione alias
<a name="r_PLpgSQL-alias-declaration"></a>

Se la firma della procedura archiviata omette il nome dell'argomento, è possibile dichiarare un alias per l'argomento.

```
name ALIAS FOR $n;
```

## Variabili integrate
<a name="r_PLpgSQL-builtin-variables"></a>

Le seguenti variabili integrate sono supportate:
+ FOUND
+ SQLSTATE
+ SQLERRM
+ GET DIAGNOSTICS integer\$1var := ROW\$1COUNT;

FOUND è una variabile speciale di tipo booleano. FOUND inizia come falsa in ogni chiamata di procedura. FOUND viene impostato dai seguenti tipi di istruzioni:
+ SELECT INTO

  Imposta FOUND su true se restituisce una riga, false se non viene restituita alcuna riga.
+ UPDATE, INSERT e DELETE

  Imposta FOUND su true se almeno una riga è coinvolta, false se nessuna riga è coinvolta.
+ FETCH

  Imposta FOUND su true se restituisce una riga, false se non viene restituita alcuna riga.
+ Istruzione FOR

  Imposta FOUND su true se l'istruzione FOR effettua l'iterazione una o più volte, altrimenti la imposta su false. Questo si applica a tutte e tre le varianti dell'istruzione FOR: loop FOR interi, loop FOR record-set e loop FOR record-set dinamici. 

  FOUND viene impostato quando il loop FOR esce. Nel runtime del loop, FOUND non viene modificato dall'istruzione FOR. Tuttavia, può essere modificato dall'esecuzione di altre istruzioni nel corpo del loop.

Di seguito viene riportato un esempio.

```
CREATE TABLE employee(empname varchar);
CREATE OR REPLACE PROCEDURE show_found()
AS  $$
DECLARE
  myrec record;
BEGIN
  SELECT INTO myrec * FROM employee WHERE empname = 'John';
  IF NOT FOUND THEN
    RAISE EXCEPTION 'employee John not found';
  END IF;
END;
$$ LANGUAGE plpgsql;
```

Nel gestore delle eccezioni, la variabile speciale SQLSTATE contiene il codice di errore che corrisponde all'eccezione che è stata generata. La variabile speciale SQLERRM contiene il messaggio di errore associato all'eccezione. Queste variabili non sono definite al di fuori dei gestori delle eccezioni e, se utilizzate, generano un errore.

Di seguito viene riportato un esempio.

```
CREATE OR REPLACE PROCEDURE sqlstate_sqlerrm() AS
$$
BEGIN
  UPDATE employee SET firstname = 'Adam' WHERE lastname = 'Smith';
  EXECUTE 'select invalid';
  EXCEPTION WHEN OTHERS THEN
  RAISE INFO 'error message SQLERRM %', SQLERRM;
  RAISE INFO 'error message SQLSTATE %', SQLSTATE;
END;
$$ LANGUAGE plpgsql;
```

ROW\$1COUNT viene utilizzato con il comando GET DIAGNOSTICS. Mostra il numero di righe elaborate dall'ultimo comando SQL inviato al motore SQL.

Di seguito viene riportato un esempio.

```
CREATE OR REPLACE PROCEDURE sp_row_count() AS
$$
DECLARE
  integer_var int;
BEGIN
  INSERT INTO tbl_row_count VALUES(1);
  GET DIAGNOSTICS integer_var := ROW_COUNT;
  RAISE INFO 'rows inserted = %', integer_var;
END;
$$ LANGUAGE plpgsql;
```

## Tipi di record
<a name="r_PLpgSQL-record-type"></a>

Un tipo RECORD non è un tipo di dati true, solo un segnaposto. Le variabili tipo di record assumono la struttura della riga attuale della riga alla quale sono assegnate durante un comando SELECT o FOR. La sottostruttura di una variabile di record può cambiare ogni volta che le viene assegnato un valore. Fino a quando una variabile di record non viene assegnata, non ha sottostruttura. Ogni tentativo di accedere un campo in essa genera un errore di runtime.

```
name RECORD;
```

Di seguito viene riportato un esempio.

```
CREATE TABLE tbl_record(a int, b int);
INSERT INTO tbl_record VALUES(1, 2);
CREATE OR REPLACE PROCEDURE record_example()
LANGUAGE plpgsql
AS $$
DECLARE
  rec RECORD;
BEGIN
  FOR rec IN SELECT a FROM tbl_record
  LOOP
    RAISE INFO 'a = %', rec.a;
  END LOOP;
END;
$$;
```