

 Amazon Redshift unterstützt UDFs ab Patch 198 nicht mehr die Erstellung von neuem Python. Das bestehende Python UDFs wird bis zum 30. Juni 2026 weiterhin funktionieren. Weitere Informationen finden Sie im [Blog-Posting](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Unterstützte PL/pgSQL-Anweisungen
<a name="c_PLpgSQL-statements"></a>

 PL/pgSQL-Anweisungen erweitern SQL-Befehle mit prozeduralen Konstrukten, einschließlich Schleifen- und bedingten Ausdrücken, um den logischen Fluss zu steuern. Die meisten SQL-Befehle können verwendet werden, einschließlich der Data Manipulation Language (DML) wie COPY, UNLOAD und INSERT, und der Data Definition Language (DDL) wie CREATE TABLE. Eine Liste umfassender SQL-Befehle finden Sie unter [SQL-Befehle](c_SQL_commands.md). Darüber hinaus werden die folgenden PL/pgSQL-Anweisungen von Amazon Redshift unterstützt. 

**Topics**
+ [Zuweisung](#r_PLpgSQL-assignment)
+ [SELECT INTO](#r_PLpgSQL-select-into)
+ [No-op](#r_PLpgSQL-no-op)
+ [Dynamisches SQL](#r_PLpgSQL-dynamic-sql)
+ [Ergebnis](#r_PLpgSQL-return)
+ [Bedingungen: IF](#r_PLpgSQL-conditionals-if)
+ [Bedingungen: CASE](#r_PLpgSQL-conditionals-case)
+ [Loops](#r_PLpgSQL-loops)
+ [Cursor](#r_PLpgSQL-cursors)
+ [RAISE](#r_PLpgSQL-messages-errors)
+ [Transaktionskontrolle](#r_PLpgSQL-transaction-control)

## Zuweisung
<a name="r_PLpgSQL-assignment"></a>

Die Zuweisungsanweisung ordnet einer Variablen einen Wert zu. Der Ausdruck muss einen einzelnen Wert zurückgeben.

```
identifier := expression;
```

Die Verwendung des nicht standardmäßigen `=` für die Anweisung, anstelle von `:=`, wird auch akzeptiert.

Wenn der Datentyp des Ausdrucks nicht mit dem Datentyp der Variablen übereinstimmt oder die Variable eine Größe oder Genauigkeit aufweist, wird der Ergebniswert implizit konvertiert.

Es folgen Beispiele.

```
customer_number := 20;
tip := subtotal * 0.15;
```

## SELECT INTO
<a name="r_PLpgSQL-select-into"></a>

Die SELECT INTO-Anweisung weist das Ergebnis mehrerer Spalten (jedoch nur eine Zeile) einer Datensatzvariablen oder Liste von skalaren Variablen zu.

```
SELECT INTO target select_expressions FROM ...;
```

In der vorhergehenden Syntax kann *Ziel* eine Datensatzvariable oder eine durch Kommata getrennte Liste einfacher Variablen und Datensatzfelder sein. Die *select\$1expressions*-Liste und der Rest des Befehls sind die gleichen wie bei regulärem SQL.

Wenn eine Variablenliste als *Ziel* verwendet wird, müssen die ausgewählten Werte genau der Struktur des Ziels entsprechen oder ein Laufzeitfehler tritt auf. Wenn eine Datensatzvariable das Ziel ist, konfiguriert sie sich automatisch für den Zeilentyp der Abfrageergebnisspalten.

Die INTO-Klausel kann fast überall in der SELECT-Anweisung erscheinen. Sie wird normalerweise direkt nach der SELECT-Klausel oder direkt vor der FROM-Klausel angezeigt. Das heißt, sie erscheint direkt vor oder nach der *select\$1expressions*-Liste.

Wenn die Abfrage null Zeilen ausgibt, werden dem *Ziel* NULL-Werte zugewiesen. Wenn die Abfrage mehrere Zeilen ausgibt, wird die erste Zeile dem *Ziel* zugewiesen und der Rest wird verworfen. Sofern die Anweisung kein ORDER BY enthält, ist die erste Zeile nicht deterministisch.

Um festzustellen, ob die Anweisung mindestens eine Zeile zurückgegeben hat, verwenden Sie die spezielle FOUND-Variable.

```
SELECT INTO customer_rec * FROM cust WHERE custname = lname;
IF NOT FOUND THEN
  RAISE EXCEPTION 'employee % not found', lname;
END IF;
```

Um herauszufinden, ob ein Datensatzergebnis null ist, können Sie die IS NULL-Bedingung verwenden. Es gibt keine Möglichkeit, zu bestimmen, ob zusätzliche Zeilen verworfen wurden. Das folgende Beispiel behandelt den Fall, bei dem keine Zeilen zurückgegeben wurden.

```
CREATE OR REPLACE PROCEDURE select_into_null(return_webpage OUT varchar(256))
AS $$
DECLARE
  customer_rec RECORD;
BEGIN
  SELECT INTO customer_rec * FROM users WHERE user_id=3;
  IF customer_rec.webpage IS NULL THEN
    -- user entered no webpage, return "http://"
    return_webpage = 'http://';
  END IF;
END;
$$ LANGUAGE plpgsql;
```

## No-op
<a name="r_PLpgSQL-no-op"></a>

Die no-op-Anweisung (`NULL;`) ist eine Platzhalteranweisung, die nichts tut. Eine no-op-Anweisung kann anzeigen, dass eine Verzweigung einer IF-THEN-ELSE-Kette leer ist.

```
NULL;
```

## Dynamisches SQL
<a name="r_PLpgSQL-dynamic-sql"></a>

Zum Generieren dynamischer Befehle, die jedes Mal verschiedene Tabellen oder unterschiedliche Datentypen umfassen können, wenn sie von einer gespeicherten PL/pgSQL-Prozedur ausgeführt werden, verwenden Sie die `EXECUTE`-Anweisung.

```
EXECUTE command-string [ INTO target ];
```

Im vorhergehenden Beispiel ist *command-string* ein Ausdruck, der eine Zeichenfolge (vom Typ Text) zum Ergebnis hat, die den auszuführenden Befehl enthält. Dieser *command-string*-Wert wird an die SQL-Engine gesendet. Es wird keine Ersetzung von PL/pgSQL-Variablen für die Befehlszeichenfolge vorgenommen. Die Werte von Variablen müssen in die Befehlszeichenfolge eingefügt werden, während sie erstellt wird.

**Anmerkung**  
Sie können COMMIT- und ROLLBACK-Anweisungen nicht innerhalb von dynamischem SQL verwenden. Informationen zur Verwendung von COMMIT- und ROLLBACK-Anweisungen innerhalb eines gespeicherten Verfahrens finden Sie unter [Verwalten von Transaktionen](stored-procedure-transaction-management.md). 

Bei der Arbeit mit dynamischen Befehlen müssen Sie sich häufig um das Escaping von einfachen Anführungszeichen kümmern. Wir empfehlen, dass Sie festen Text im Funktionstext mit der Dollaranführung in Anführungszeichen einschließen. Dynamische Werte, die in eine erstellte Abfrage eingefügt werden sollen, erfordern eine spezielle Vorgehensweisen, da sie selber Anführungszeichen enthalten können. Das folgende Beispiel setzt die Dollaranführung für die gesamte Funktion voraus, daher müssen keine doppelten Anführungszeichen verwendet werden.

```
EXECUTE 'UPDATE tbl SET '
  || quote_ident(colname)
  || ' = '
  || quote_literal(newvalue)
  || ' WHERE key = '
  || quote_literal(keyvalue);
```

Das vorhergehende Beispiel zeigt die Funktionen `quote_ident(text)` und `quote_literal(text)`. Dieses Beispiel leitet Variablen, die Spalten- und Tabellenkennungen enthalten, an die `quote_ident`-Funktion weiter. Es übermittelt auch Variablen, die Literalzeichenfolgen im erstellten Befehl enthalten, an die `quote_literal`-Funktion. Beide Funktionen unternehmen alle erforderlichen Schritte, um den in doppelten oder einfachen Anführungszeichen eingeschlossenen Eingabetext entsprechend zurückzugeben. Dabei sind alle eingebetteten speziellen Zeichen ordnungsgemäß mit einem Escape-Zeichen versehen.

Die Dollaranführung ist nur nützlich, wenn Sie Anführungszeichen für festen Text setzen. Schreiben Sie das vorhergehende Beispiel nicht in folgendem Format.

```
EXECUTE 'UPDATE tbl SET '
  || quote_ident(colname)
  || ' = $$'
  || newvalue
  || '$$ WHERE key = '
  || quote_literal(keyvalue);
```

Sie tun dies nicht, weil im Beispiel Fehler auftreten, wenn der Inhalt von `newvalue` zufällig \$1\$1 enthält. Dasselbe Problem gilt für alle anderen Dollaranführungstrennzeichen, die Sie auswählen können. Verwenden Sie die `quote_literal`-Funktion, um vorher nicht bekannten Text sicher mit Anführungszeichen zu versehen.

## Ergebnis
<a name="r_PLpgSQL-return"></a>

Die RETURN-Anweisung wird aus einer gespeicherten Prozedur zum Aufrufer zurückgegeben.

```
RETURN;
```

Es folgt ein Beispiel.

```
CREATE OR REPLACE PROCEDURE return_example(a int)
AS $$  
BEGIN
  FOR b in 1..10 LOOP
    IF b < a THEN
      RAISE INFO 'b = %', b;
    ELSE
      RETURN;
    END IF;
  END LOOP;
END;
$$ LANGUAGE plpgsql;
```

## Bedingungen: IF
<a name="r_PLpgSQL-conditionals-if"></a>

Die IF-Bedingungsanweisung kann folgende Formen in der PL/pgSQL-Sprache annehmen, die Amazon Redshift verwendet:
+ IF ... THEN

  ```
  IF boolean-expression THEN
    statements
  END IF;
  ```

  Es folgt ein Beispiel.

  ```
  IF v_user_id <> 0 THEN
    UPDATE users SET email = v_email WHERE user_id = v_user_id;
  END IF;
  ```
+ IF ... THEN ... ELSE

  ```
  IF boolean-expression THEN
    statements
  ELSE
    statements
  END IF;
  ```

  Es folgt ein Beispiel.

  ```
  IF parentid IS NULL OR parentid = ''
  THEN
    return_name = fullname;
    RETURN;
  ELSE
    return_name = hp_true_filename(parentid) || '/' || fullname;
    RETURN;
  END IF;
  ```
+ IF ... THEN ... ELSIF ... THEN ... ELSE 

  Das Schlüsselwort ELSIF kann auch als ELSEIF angegeben werden.

  ```
  IF boolean-expression THEN
    statements
  [ ELSIF boolean-expression THEN
    statements
  [ ELSIF boolean-expression THEN
    statements
      ...] ]
  [ ELSE
    statements ]
  END IF;
  ```

  Es folgt ein Beispiel.

  ```
  IF number = 0 THEN
    result := 'zero';
  ELSIF number > 0 THEN
    result := 'positive';
  ELSIF number < 0 THEN
    result := 'negative';
  ELSE
    -- the only other possibility is that number is null
    result := 'NULL';
  END IF;
  ```

## Bedingungen: CASE
<a name="r_PLpgSQL-conditionals-case"></a>

Die CASE-Bedingungsanweisung kann folgende Formen in der PL/pgSQL-Sprache annehmen, die Amazon Redshift verwendet:
+ Einfaches CASE 

  ```
  CASE search-expression
  WHEN expression [, expression [ ... ]] THEN
    statements
  [ WHEN expression [, expression [ ... ]] THEN
    statements
    ... ]
  [ ELSE
    statements ]
  END CASE;
  ```

  Eine einfache CASE-Anweisung stellt eine Bedingungsausführung basierend auf der Gleichheit von Operanden bereit.

  Der *search-expression*-Wert wir ein Mal ausgewertet und aufeinanderfolgend mit jedem *Ausdruck* in der WHEN-Klausel verglichen. Bei einer Übereinstimmung werden die entsprechenden *Anweisungen* ausgeführt und die Kontrolle wird an die nächste Anweisung nach END CASE übergeben. Nachfolgende WHEN-Ausdrücke werden nicht ausgewertet. Bei keiner Übereinstimmung werden die ELSE-*Anweisungen* ausgeführt. Wenn ELSE jedoch nicht vorhanden ist, wird eine CASE\$1NOT\$1FOUND-Ausnahme ausgelöst.

  Es folgt ein Beispiel.

  ```
  CASE x
  WHEN 1, 2 THEN
    msg := 'one or two';
  ELSE
    msg := 'other value than one or two';
  END CASE;
  ```
+ Gesuchtes CASE 

  ```
  CASE
  WHEN boolean-expression THEN
    statements
  [ WHEN boolean-expression THEN
    statements
    ... ]
  [ ELSE
    statements ]
  END CASE;
  ```

  Die gesuchte CASE-Anweisung stellt Bedingungsausführungen basierend auf der Wahrheit von booleschen Ausdrücken bereit. 

  Der *boolean-expression* jeder WHEN-Klausel wird dann ausgewertet, bis einer gefunden wird, der als Ergebnis „true“ zurück gibt. Anschließend werden die entsprechenden Anweisungen ausgeführt und die Kontrolle wird an die nächste Anweisung nach END CASE übergeben. Nachfolgende WHEN-*Ausdrücke* werden nicht ausgewertet. Wenn kein „true“-Ergebnis gefunden wird, werden die ELSE-*Anweisungen* ausgeführt. Wenn ELSE jedoch nicht vorhanden ist, wird eine CASE\$1NOT\$1FOUND-Ausnahme ausgelöst.

  Es folgt ein Beispiel.

  ```
  CASE
  WHEN x BETWEEN 0 AND 10 THEN
    msg := 'value is between zero and ten';
  WHEN x BETWEEN 11 AND 20 THEN
    msg := 'value is between eleven and twenty';
  END CASE;
  ```

## Loops
<a name="r_PLpgSQL-loops"></a>

Loop-Anweisungen können folgende Formen in der PL/pgSQL-Sprache annehmen, die Amazon Redshift verwendet:
+ Einfacher Loop 

  ```
  [<<label>>]
  LOOP
    statements
  END LOOP [ label ];
  ```

  Ein einfacher Loop definiert einen bedingungslosen Loop, der unbegrenzt wiederholt wird, bis er von einer EXIT- oder RETURN-Anweisung beendet wird. Die optionale Bezeichnung kann von EXIT- und CONTINUE-Anweisungen in verschachtelten Loops verwendet werden, um anzugeben, auf welchen Loop sich die EXIT- und CONTINUE-Anweisungen beziehen.

  Es folgt ein Beispiel.

  ```
  CREATE OR REPLACE PROCEDURE simple_loop()
  LANGUAGE plpgsql
  AS $$
  BEGIN
    <<simple_while>>
    LOOP
      RAISE INFO 'I am raised once';  
      EXIT simple_while;
      RAISE INFO 'I am not raised';
    END LOOP;
    RAISE INFO 'I am raised once as well';
  END;
  $$;
  ```
+ Exit-Loop

  ```
  EXIT [ label ] [ WHEN expression ];
  ```

  Wenn *Bezeichnung* nicht vorhanden ist, wird der innerste Loop beendet und die Anweisung als nächstes ausgeführt, die dem END LOOP folgt. Wenn *Bezeichnung* vorhanden ist, muss es sich um die Bezeichnung des aktuellen oder eines verschachtelten Loops oder Blocks der äußeren Ebene handeln. Anschließend wird der benannte Loop oder Block beendet und die Kontrolle fährt mit der Anweisung nach dem entsprechenden END des Loops oder Blocks fort.

  Wenn WHEN angegeben ist, wird der Loop nur beendet, wenn *Ausdruck* „true“ lautet. Andernfalls wird die Kontrolle an die Anweisung nach EXIT weitergeleitet.

  Sie können EXIT mit allen Arten von Loops verwenden. Es ist nicht auf die Nutzung mit bedingungslosen Loops beschränkt.

  Bei Verwendung mit einem BEGIN-Block übergibt EXIT die Kontrolle an die nächste Anweisung nach dem Ende des Blocks. Zu diesem Zweck muss eine Bezeichnung verwendet werden. Ein nicht gekennzeichnetes EXIT gilt nie als übereinstimmend mit einem BEGIN-Block.

  Es folgt ein Beispiel.

  ```
  CREATE OR REPLACE PROCEDURE simple_loop_when(x int)
  LANGUAGE plpgsql
  AS $$
  DECLARE i INTEGER := 0;
  BEGIN
    <<simple_loop_when>>
    LOOP
      RAISE INFO 'i %', i;
      i := i + 1;
      EXIT simple_loop_when WHEN (i >= x);
    END LOOP;
  END;
  $$;
  ```
+ Continue-Loop 

  ```
  CONTINUE [ label ] [ WHEN expression ];
  ```

  Wenn *Bezeichnung* nicht angegeben ist, springt die Ausführung zur nächsten Iteration des innersten Loops. Das heißt, alle im Loop-Text verbleibenden Anweisungen werden übersprungen. Die Kontrolle geht dann an den Loop-Kontrollausdruck (falls vorhanden) zurück, um festzulegen, ob eine weitere Loop-Iteration erforderlich ist. Wenn *Bezeichnung* vorhanden ist, wird die Bezeichnung des Loops angegeben, dessen Ausführung fortgesetzt wird.

  Wenn WHEN angegeben ist, wird die nächste Iteration des Loops nur dann begonnen, wenn *Ausdruck* „true“ lautet. Andernfalls wird die Kontrolle an die Anweisung nach CONTINUE weitergeleitet.

  Sie können CONTINUE mit allen Arten von Loops verwenden. Es ist nicht auf die Nutzung mit bedingungslosen Loops beschränkt.

  ```
  CONTINUE mylabel;
  ```
+ WHILE-Loop 

  ```
  [<<label>>]
  WHILE expression LOOP
    statements
  END LOOP [ label ];
  ```

  Die WHILE-Anweisung wiederholt eine Reihenfolge von Anweisungen solange der *boolean-expression* als „true“ ausgewertet wird. Der Ausdruck wird kurz vor jedem Eintritt in den Loop-Text geprüft.

  Es folgt ein Beispiel.

  ```
  WHILE amount_owed > 0 AND gift_certificate_balance > 0 LOOP
    -- some computations here
  END LOOP;
  
  WHILE NOT done LOOP
    -- some computations here
  END LOOP;
  ```
+ FOR-Loop (Ganzzahlvariante) 

  ```
  [<<label>>]
  FOR name IN [ REVERSE ] expression .. expression LOOP
    statements
  END LOOP [ label ];
  ```

  Der FOR-Loop (Ganzzahlvariante) erstellt einen Loop, der über einen Bereich von Ganzzahlwerten iteriert. Der Variablenname wird automatisch als Typ Ganzzahl definiert und existiert nur innerhalb des Loops. Jede vorhandene Definition des Variablennamen wird innerhalb des Loops ignoriert. Die zwei Ausdrücke, welche die Unter- und Obergrenze des Bereichs angeben, werden beim Eintritt in den Loop einmal ausgewertet. Wenn Sie REVERSE angeben, wird der Schrittwert nach jeder Iteration eher subtrahiert als addiert.

  Wenn die Untergrenze größer ist als die Obergrenze (oder kleiner, im REVERSE-Fall), wird der Loop-Text nicht ausgeführt. Es wird kein Fehler ausgegeben.

  Wenn eine Bezeichnung einem FOR-Loop angefügt ist, können Sie unter Verwendung dieser Bezeichnung mit einem qualifizierten Namen auf die Ganzzahl-Loop-Variable verweisen.

  Es folgt ein Beispiel.

  ```
  FOR i IN 1..10 LOOP
    -- i will take on the values 1,2,3,4,5,6,7,8,9,10 within the loop
  END LOOP;
  
  FOR i IN REVERSE 10..1 LOOP
    -- i will take on the values 10,9,8,7,6,5,4,3,2,1 within the loop
  END LOOP;
  ```
+ FOR-Loop (Ergebnissatzvariante) 

  ```
  [<<label>>]
  FOR target IN query LOOP
    statements
  END LOOP [ label ];
  ```

  Das *Ziel* ist eine Datensatzvariable oder eine durch Kommata getrennte Liste skalarer Variablen. Das Ziel wird jeder Zeile aufeinanderfolgend zugewiesen, die aus der Abfrage resultiert, und der Loop-Text wird für jede Abfrage ausgeführt.

  Der FOR-Loop (Ergebnissatzvariante) ermöglicht einer gespeicherten Prozedur, die Ergebnisse einer Abfrage zu durchlaufen und diese Daten entsprechend zu bearbeiten.

  Es folgt ein Beispiel.

  ```
  CREATE PROCEDURE cs_refresh_reports() AS $$
  DECLARE
    reports RECORD;
  BEGIN
    FOR reports IN SELECT * FROM cs_reports ORDER BY sort_key LOOP
      -- Now "reports" has one record from cs_reports
      EXECUTE 'INSERT INTO ' || quote_ident(reports.report_name) || ' ' || reports.report_query;
    END LOOP;
    RETURN;
  END;
  $$ LANGUAGE plpgsql;
  ```
+ FOR-Loop mit dynamischem SQL

  ```
  [<<label>>]
  FOR record_or_row IN EXECUTE text_expression LOOP 
    statements
  END LOOP;
  ```

  Der FOR-Loop mit dynamischem SQL ermöglicht einer gespeicherten Prozedur, die Ergebnisse einer dynamischen Abfrage zu durchlaufen und diese Daten entsprechend zu bearbeiten.

  Es folgt ein Beispiel.

  ```
  CREATE OR REPLACE PROCEDURE for_loop_dynamic_sql(x int)
  LANGUAGE plpgsql
  AS $$
  DECLARE
    rec RECORD;
    query text;
  BEGIN
    query := 'SELECT * FROM tbl_dynamic_sql LIMIT ' || x;
    FOR rec IN EXECUTE query
    LOOP
      RAISE INFO 'a %', rec.a;
    END LOOP;
  END;
  $$;
  ```

## Cursor
<a name="r_PLpgSQL-cursors"></a>

Statt eine ganze Abfrage auf einmal auszuführen, können Sie einen Cursor einrichten. Ein *Cursor *kapselt eine Abfrage und liest jeweils wenige Zeilen des Abfrageergebnisses. Ein Grund hierfür ist das Vermeiden von Speicherüberlauf, wenn das Ergebnis eine große Anzahl von Zeilen enthält. Ein weiterer Grund ist die Rückgabe einer Referenz an einen Cursor, den eine gespeicherte Prozedur erstellt hat. Dies erlaubt dem Aufrufer, die Zeilen zu lesen. Dieser Ansatz bietet eine effiziente Methode, große Zeilensätze von gespeicherten Prozeduren zurückzugeben.

Um Cursor in einer gespeicherten NONATOMIC-Prozedur zu verwenden, platzieren Sie die Cursor-Schleife zwischen START TRANSACTION...COMMIT.

Zum Einrichten eines Cursors deklarieren Sie zuerst eine Cursor-Variable. Jeder Zugriff auf Cursor in PL/pgSQL durchläuft Cursor-Variablen, die immer vom speziellen Datentyp sind `refcursor`. Ein `refcursor`-Datentyp hält einfach eine Referenz auf einen Cursor. 

Sie können eine Cursor-Variable erstellen, indem Sie sie als Variable des Typs deklarieren `refcursor`. Alternativ können Sie die folgende Cursor-Deklarationssyntax verwenden.

```
name CURSOR [ ( arguments ) ] FOR query ;
```

Im vorhergehenden Beispiel ist *Argumente* (wenn angegeben) eine durch Kommata getrennte Liste von *Name-Datentyp*-Paaren, die jeweils Namen definieren, die in *Abfrage* durch Parameterwerte ersetzt werden sollen. Die tatsächlichen Werte, durch die diese Namen ersetzt werden sollen, werden später beim Öffnen des Cursors angegeben.

Es folgen Beispiele.

```
DECLARE
  curs1 refcursor;
  curs2 CURSOR FOR SELECT * FROM tenk1;
  curs3 CURSOR (key integer) IS SELECT * FROM tenk1 WHERE unique1 = key;
```

Alle drei dieser Variablen haben den Datentyp `refcursor`, aber die erste kann mit jeder Abfrage verwendet werden. Im Gegensatz dazu verfügt die zweite über eine vollständig angegebene Abfrage, die bereits an sie gebunden ist, und die letzte über eine an sie gebundene parametrisierte Abfrage. Der `key`-Wert wird durch einen Ganzzahl-Parameterwert ersetzt, wenn der Cursor geöffnet wird. Die Variable `curs1` gilt als *ungebunden, * weil sie nicht an eine bestimmte Abfrage gebunden ist.

Bevor Sie einen Cursor zum Abrufen von Zeilen verwenden können, muss er geöffnet werden. PL/pgSQL verfügt über drei Formen der OPEN-Anweisung. Zwei davon verwenden ungebundene Cursor-Variablen und die dritte eine gebundene Cursor-Variable:
+ Öffnen zum Auswählen: Die Cursor-Variable wird geöffnet und die angegebene Abfrage zur Ausführung zugeteilt. Der Cursor darf nicht bereits geöffnet sein. Außerdem muss er als ungebundener Cursor deklariert worden sein (das heißt, als eine einfache `refcursor`-Variable). Die SELECT-Abfrage wird genauso wie andere SELECT-Anweisungen in PL/pgSQL behandelt. 

  ```
  OPEN cursor_name FOR SELECT ...;                     
  ```

  Es folgt ein Beispiel.

  ```
  OPEN curs1 FOR SELECT * FROM foo WHERE key = mykey;    
  ```
+ Öffnen zum Ausführen: Die Cursor-Variable wird geöffnet und die angegebene Abfrage zur Ausführung zugeteilt. Der Cursor darf nicht bereits geöffnet sein. Außerdem muss er als ungebundener Cursor deklariert worden sein (das heißt, als eine einfache `refcursor`-Variable). Die Abfrage wird auf die gleiche Art und Weise als Zeichenfolgeausdruck angegeben wie im EXECUTE-Befehl. Dieser Ansatz bietet Flexibilität, sodass die Abfrage von einer Ausführung zur nächsten variieren kann.

  ```
  OPEN cursor_name FOR EXECUTE query_string;
  ```

  Es folgt ein Beispiel.

  ```
  OPEN curs1 FOR EXECUTE 'SELECT * FROM ' || quote_ident($1);
  ```
+ Öffnen eines gebundenen Cursors: Diese Form von OPEN wird zum Öffnen einer Cursor-Variablen verwendet, deren Abfrage beim Deklarieren an sie gebunden wurde. Der Cursor darf nicht bereits geöffnet sein. Eine Liste der tatsächlichen Argumentwertausdrücke muss angezeigt werden, wenn und nur wenn der Cursor zur Verwendung von Argumenten deklariert wurde. Diese Werte werden in der Abfrage ersetzt. 

  ```
  OPEN bound_cursor_name [ ( argument_values ) ];
  ```

  Es folgt ein Beispiel.

  ```
  OPEN curs2;
  OPEN curs3(42);
  ```

Nachdem ein Cursor geöffnet wurde, können Sie mit ihm arbeiten, indem Sie die Anweisungen verwenden, die im Folgenden beschrieben sind. Diese Anweisungen müssen nicht in derselben gespeicherten Prozedur ausgeführt werden, die den Cursor geöffnet hat. Sie können einen `refcursor`-Wert aus einer gespeicherten Prozedur zurück geben und den Aufrufer mit dem Cursor arbeiten lassen. Alle Portale werden am Transaktionsende implizit geschlossen. Daher können Sie einen `refcursor`-Wert für das Referenzieren eines offenen Cursors nur bis zum Ende der Transaktion verwenden.
+ FETCH überträgt die nächste Zeile aus dem Cursor in ein Ziel. Dieses Ziel kann eine Zeilenvariable, eine Datensatzvariable oder eine durch Kommata getrennte Liste von einfachen Variablen wie bei SELECT INTO sein. Wie bei SELECT INTO können Sie in der speziellen FOUND-Variable überprüfen, ob eine Zeile bezogen wurde.

  ```
  FETCH cursor INTO target;
  ```

  Es folgt ein Beispiel.

  ```
  FETCH curs1 INTO rowvar;
  ```
+ CLOSE schließt das Portal, das einem offenen Cursor zugrunde liegt. Sie können diese Anweisung verwenden, um Ressourcen noch vor dem Ende der Transaktion freizugeben. Sie können diese Anweisung auch verwenden, um die Cursor-Variable zu entblocken, damit sie wieder geöffnet werden kann.

  ```
  CLOSE cursor;
  ```

  Es folgt ein Beispiel.

  ```
  CLOSE curs1;
  ```

## RAISE
<a name="r_PLpgSQL-messages-errors"></a>

Verwenden Sie die `RAISE level`-Anweisung zum Melden von Nachrichten und zum Auslösen von Fehlern.

```
RAISE level 'format' [, variable [, ...]];
```

Mögliche Ebenen sind NOTICE, INFO, LOG, WARNING und EXCEPTION. EXCEPTION meldet einen Fehler, der die aktuelle Transaktion in der Regel abbricht. Die anderen Ebenen generieren nur Nachrichten mit unterschiedlichen Prioritätsstufen. 

Innerhalb der Formatzeichenfolge wird % durch die Zeichenfolgedarstellung des nächsten optionalen Arguments ersetzt. Schreiben Sie %% zum Übermitteln des Literals %. Derzeit müssen optionale Argumente einfache Variablen sein und nicht Ausdrücke, und das Format muss ein einfaches Zeichenfolgeliteral sein.

Im folgenden Beispiel ersetzt der Wert von `v_job_id` das % in der Zeichenfolge.

```
RAISE NOTICE 'Calling cs_create_job(%)', v_job_id;
```

Verwenden Sie die `RAISE`-Anweisung zum erneuten Auslösen der Ausnahme, die vom Ausnahmebehandlungsblock abgefangen wurde. Diese Anweisung ist nur in Ausnahmebehandlungsblöcken von gespeicherten Prozeduren im NONATOMIC-Modus gültig.

```
RAISE;
```

## Transaktionskontrolle
<a name="r_PLpgSQL-transaction-control"></a>

Sie können mit Transaktionskontroll-Anweisungen in der PL/pgSQL-Sprache arbeiten, die Amazon Redshift verwendet. Informationen zur Verwendung von COMMIT-, ROLLBACK- und TRUNCATE-Anweisungen innerhalb eines gespeicherten Verfahrens finden Sie unter [Verwalten von Transaktionen](stored-procedure-transaction-management.md). 

Verwenden Sie für gespeicherte Prozeduren im NONATOMIC-Modus `START TRANSACTION`, um einen Transaktionsblock zu starten.

```
START TRANSACTION;
```

**Anmerkung**  
Die PL/pgSQL-Anweisung START TRANSACTION unterscheidet sich folgendermaßen vom SQL-Befehl START TRANSACTION:  
In gespeicherten Prozeduren ist START TRANSACTION nicht gleichbedeutend mit BEGIN.
Die PL/pgSQL-Anweisung unterstützt keine optionalen Schlüsselwörter für Isolationsstufe und Zugriffsberechtigungen.