Rechts

PostgreSQL
Das Offizielle Handbuch

LINKS

Rechts
Peter Eisentraut

PostgreSQL
Das Offizielle Handbuch

LINKS
Bibliografische Information Der Deutschen Bibliothek – Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über <http://dnb.ddb.de> abrufbar.

ISBN 3-8266-1337-6 1. Auflage 2003

Alle Rechte, auch die der Übersetzung, vorbehalten. Kein Teil des Werkes darf in irgendeiner Form (Druck, Fotokopie, Mikrofilm oder einem anderen Verfahren) ohne schriftliche Genehmigung des Verlages reproduziert oder unter Verwendung elektronischer Systeme verarbeitet, vervielfältigt oder verbreitet werden. Der Verlag übernimmt keine Gewähr für die Funktion einzelner Programme oder von Teilen derselben. Insbesondere übernimmt er keinerlei Haftung für eventuelle, aus dem Gebrauch resultierende Folgeschäden. Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichenund Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.

Copyright © 1996-2003 PostgreSQL Global Development Group PostgreSQL ist Copyright © 1996-2002 PostgreSQL Global Development Group und wird unter der unten gezeigten Lizenz der Universität von Kalifornien verteilt. Postgres95 ist Copyright © 1994-95 Regents of the University of California. Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN „AS-IS“ BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

Printed in Germany © Copyright 2003 by mitp-Verlag GmbH/Bonn, ein Geschäftsbereich der verlag moderne industrie Buch AG&Co.KG/Landsberg
Lektorat: Sabine Schulz Sprachkorrektorat: Friederike Daenecke Satz und Layout: G&U e.Publishing Services GmbH, Flensburg Druck: Media-Print, Paderborn

Inhaltsverzeichnis

Einleitung
Was ist PostgreSQL? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die kurze Geschichte von PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . Über diese Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konventionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Weitere Informationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Richtlinien für Fehlerberichte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehler identifizieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Was berichtet werden sollte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wo Fehler berichtet werden können . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21
21 22 23 24 24 25 25 25 27

Teil I Kapitel 1:
1.1 1.2 1.3 1.4

Tutorial Ein Einstieg
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grundlagen der Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datenbank erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Auf eine Datenbank zugreifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

29 31
31 31 32 34

Kapitel 2:
2.1 2.2 2.3 0.1 2.4 2.5 2.6 2.7 2.8 2.9

Die SQL-Sprache
Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konzepte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine neue Tabelle erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine neue Tabelle erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Tabelle mit Zeilen füllen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Tabelle abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verbunde zwischen Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aggregatfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten aktualisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37
37 37 38 38 39 39 41 43 44 45

Kapitel 3:
3.1 3.2

Fortgeschrittene Funktionen
Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47
47 47

5

Inhaltsverzeichnis

3.3 3.4 3.5 3.6

Fremdschlüssel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Transaktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schlussfolgerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

48 48 50 51

Teil II Kapitel 4:
4.1

Die SQL-Sprache SQL-Syntax
Lexikalische Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Namen und Schlüsselwörter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.2 Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.3 Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.4 Sonderzeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.5 Kommentare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.6 Vorrang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wertausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Spaltenverweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2 Positionsparameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3 Operatoraufrufe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.4 Funktionsaufrufe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.5 Aggregatausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.6 Typumwandlungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.7 Skalare Unteranfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.8 Auswertung von Ausdrücken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53 55
55 56 57 59 60 60 60 62 62 63 63 63 64 64 65 65

4.2

Kapitel 5:
5.1 5.2 5.3 5.4

Datendefinition
Tabellengrundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Systemspalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vorgabewerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Check-Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.2 NOT-NULL-Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.3 Unique Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.4 Primärschlüssel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.5 Fremdschlüssel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tabellen verändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.1 Eine Spalte hinzufügen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.2 Eine Spalte entfernen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.3 Einen Constraint hinzufügen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.4 Einen Constraint entfernen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.5 Den Vorgabewert ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.6 Eine Spalte umbenennen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.7 Eine Tabelle umbenennen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Privilegien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

67
67 69 70 70 71 72 73 74 75 77 78 78 78 78 79 79 79 79 80

5.5

5.6 5.7

6

Inhaltsverzeichnis

5.8 5.9

5.7.1 Ein Schema erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.2 Das Schema public . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.3 Der Schema-Suchpfad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.4 Schemas und Privilegien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.5 Das Systemkatalogschema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.6 Verwendungsmöglichkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.7 Portierbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Andere Datenbankobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verfolgung von Abhängigkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81 82 82 83 84 84 84 85 85

Kapitel 6:
6.1 6.2 6.3

Datenmanipulation
Daten einfügen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten aktualisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten löschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

87
87 88 89

Kapitel 7:
7.1 7.2

Anfragen
Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tabellenausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.1 Die FROM-Klausel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.2 Die WHERE-Klausel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2.3 Die GROUP BY- und HAVING-Klauseln . . . . . . . . . . . . . . . . . . . . . . . . Select-Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.1 Elemente der Select-Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.2 Ergebnisspaltennamen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.3 DISTINCT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anfragen kombinieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeilen sortieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . LIMIT und OFFSET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91
91 92 92 98 99 103 103 104 104 105 105 106

7.3

7.4 7.5 7.6

Kapitel 8:
8.1

Datentypen
Numerische Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 Ganzzahlentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.2 Zahlen mit beliebiger Präzision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.3 Fließkommatypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.4 Selbstzählende Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Typen für Geldbeträge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichenkettentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Typen für binäre Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datums- und Zeittypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.5.1 Eingabeformate für Datum und Zeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.5.2 Ausgabeformate für Datum und Zeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.5.3 Zeitzonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.5.4 Interna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Typ boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Geometrische Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

109
110 111 112 112 113 113 114 116 117 118 121 122 123 123 124

8.2 8.3 8.4 8.5

8.6 8.7

7

Inhaltsverzeichnis

8.7.1 Punkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.7.2 Strecken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.7.3 Rechtecke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.7.4 Pfade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.7.5 Polygone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.7.6 Kreise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.8 Typen für Netzwerkadressen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.8.1 inet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.8.2 cidr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.8.3 inet vs. cidr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.8.4 macaddr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.9 Bitkettentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.10 Objekt-Identifikator-Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.11 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.11.1 Deklaration von Arraytypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.11.2 Eingabe von Arraywerten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.11.3 Verweise auf Arraywerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.11.4 In Arrays suchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.11.5 Array-Eingabe- und Ausgabesyntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.11.6 Sonderzeichen in Arrayelementen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.12 Pseudotypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

125 125 125 125 126 126 126 126 127 127 127 128 129 130 130 130 130 132 133 133 134

Kapitel 9:
9.1 9.2 9.3 9.4 9.5 9.6

Funktionen und Operatoren
Logische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vergleichsoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mathematische Funktionen und Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zeichenkettenfunktionen und -operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen und Operatoren für binäre Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . Mustervergleiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6.1 LIKE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6.2 SIMILAR TO und reguläre Ausdrücke nach SQL99 . . . . . . . . . . . . . . . . 9.6.3 Reguläre Ausdrücke nach POSIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datentyp-Formatierungsfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen und Operatoren für Datum und Zeit . . . . . . . . . . . . . . . . . . . . . . . . . 9.8.1 EXTRACT, date_part . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.8.2 date_trunc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.8.3 AT TIME ZONE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.8.4 Aktuelle Zeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Geometrische Funktionen und Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen für Netzwerkadresstypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen zur Bearbeitung von Sequenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konditionale Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.12.1 CASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.12.2 COALESCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.12.3 NULLIF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Diverse Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

135
135 136 137 140 145 146 147 147 148 151 156 158 161 161 162 164 166 167 169 169 170 171 171

9.7 9.8

9.9 9.10 9.11 9.12

9.13

8

Inhaltsverzeichnis

9.14 Aggregatfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15 Ausdrücke mit Unteranfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.1 EXISTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.2 IN (skalare Form) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.3 IN (Unteranfrageform) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.4 NOT IN (skalare Form) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.5 NOT IN (Unteranfrageform) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.6 ANY/SOME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.7 ALL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15.8 Zeilenweiser Vergleich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

175 176 176 177 177 178 178 179 179 180

Kapitel 10: Typumwandlung
10.1 10.2 10.3 10.4 10.5 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wertspeicherung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . UNION- und CASE-Konstruktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

181
181 183 185 188 189

Kapitel 11: Indexe
11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indextypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mehrspaltige Indexe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexe für Unique Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionsindexe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Operatorklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Partielle Indexe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexverwendung überprüfen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

191
191 192 193 194 194 195 195 198

Kapitel 12: Konsistenzkontrolle im Mehrbenutzerbetrieb
12.1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 Transaktionsisolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.1 Der Isolationsgrad Read Committed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.2 Der Isolationsgrad Serializable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3 Ausdrückliche Sperren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.1 Tabellensperren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.2 Zeilensperren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.3 Verklemmungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4 Konsistenzkontrolle auf der Anwendungsseite . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.5 Sperren und Indexe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

201
201 201 202 203 204 204 206 206 206 208

Kapitel 13: Tipps zur Leistungsverbesserung
13.1 13.2 13.3 13.4 EXPLAIN verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vom Planer verwendete Statistiken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Den Planer mit expliziten JOIN-Klauseln kontrollieren . . . . . . . . . . . . . . . . . . . Eine Datenbank füllen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

209
209 213 215 217

9

Inhaltsverzeichnis

13.4.1 13.4.2 13.4.3 13.4.4

Autocommit ausschalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . COPY FROM verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indexe entfernen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Danach ANALYZE ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

217 217 217 217

Teil III

Server-Administration

219 221
221 221 224 224 225 231 231 232 232

Kapitel 14: Installationsanweisungen
14.1 14.2 14.3 14.4 14.5 14.6 Kurzversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Voraussetzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Quellen erhalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Wenn Sie eine alte Version aktualisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installationsvorgang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einrichtung nach der Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.6.1 Dynamische Bibliotheken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.6.2 Umgebungsvariablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.7 Unterstützte Plattformen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Kapitel 15: Installation auf Windows Kapitel 16: Laufzeitverhalten des Servers
16.1 Der PostgreSQL-Benutzerzugang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.2 Einen Datenbankcluster erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3 Den Datenbankserver starten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3.1 Fehler beim Starten des Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3.2 Probleme bei Client-Verbindungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4 Laufzeit-Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4.1 Planer- und Optimierereinstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4.2 Log- und Debug-Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4.3 Allgemeine Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4.4 WAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4.5 Kurze Optionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.5 Verwaltung von Kernelressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.5.1 Shared Memory und Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.5.2 Ressourcenbegrenzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.6 Den Server herunterfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.7 Sichere TCP/IP-Verbindungen mit SSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.8 Sichere TCP/IP-Verbindungen mit SSH-Tunneln . . . . . . . . . . . . . . . . . . . . . . . .

237 239
239 239 241 242 243 244 245 247 250 256 257 258 258 262 263 264 265

Kapitel 17: Datenbankbenutzer und Privilegien
17.1 17.2 17.3 17.4 Datenbankbenutzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzerattribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gruppen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Privilegien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

267
267 268 269 269

10

Inhaltsverzeichnis

17.5 Funktionen und Trigger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

270

Kapitel 18: Datenbanken verwalten
18.1 18.2 18.3 18.4 18.5 18.6 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datenbank erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Template-Datenbanken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbankkonfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alternativer Speicherplatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Datenbank zerstören . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

271
271 272 273 274 274 275

Kapitel 19: Clientauthentifizierung
19.1 Die Datei pg_hba.conf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2 Authentifizierungsmethoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2.1 Freier Zugang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2.2 Passwort-Authentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2.3 Kerberos-Authentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2.4 Ident-Authentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2.5 PAM-Authentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.3 Authentifizierungsprobleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

277
277 282 282 282 283 283 285 285

Kapitel 20: Lokalisierung
20.1 Locale-Unterstützung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.1.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.1.2 Nutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.1.3 Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2 Zeichensatz-Unterstützung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2.1 Unterstützte Zeichensätze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2.2 Den Zeichensatz einstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2.3 Automatische Zeichensatzkonvertierung zwischen Client und Server . . . 20.2.4 Weitere Informationsquellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.3 Einbyte-Zeichensatz-Konvertierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

287
287 287 289 289 289 290 291 292 294 294

Kapitel 21: Routinemäßige Datenbankwartungsaufgaben
21.1 Routinemäßiges Vacuum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1.1 Speicherplatz wiedergewinnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1.2 Planerstatistiken aktualisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1.3 Transaktionsnummernüberlauf verhindern . . . . . . . . . . . . . . . . . . . . . . . . 21.2 Routinemäßiges Reindizieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.3 Logdateiverwaltung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

295
295 296 296 297 299 299

Kapitel 22: Datensicherung und wiederherstellung
22.1 SQL-Dump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.1.1 Den Dump wiederherstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

301
301 302

11

Inhaltsverzeichnis

22.1.2 pg_dumpall verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.1.3 Große Datenbanken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.1.4 Vorbehalte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.2 Archivierung auf Dateisystemebene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.3 Umstieg zwischen PostgreSQL-Versionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

302 303 303 304 304

Kapitel 23: Überwachung der Datenbankaktivität
23.1 Unix-Standardwerkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23.2 Der Statistikkollektor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23.2.1 Konfiguration des Statistikkollektors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23.2.2 Ansehen der gesammelten Statistiken . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23.3 Ansehen der Sperren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

307
307 308 308 309 312

Kapitel 24: Überwachung des Festplattenplatzverbrauchs
24.1 Ermittlung des Festplattenplatzverbrauchs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24.2 Verhalten bei voller Festplatte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

315
315 316

Kapitel 25: Write-Ahead Logging (WAL)
25.1 25.2 25.3 25.4 Nutzen aus WAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zukünfiger Nutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . WAL-Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Interna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

317
317 318 318 320

Kapitel 26: Regressionstests
26.1 Die Tests ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.2 Testauswertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.2.1 Unterschiede bei Fehlermeldungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.2.2 Unterschiede durch Locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.2.3 Unterschiede bei Datum und Zeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.2.4 Unterschiede bei Fließkommaberechnungen . . . . . . . . . . . . . . . . . . . . . . 26.2.5 Unterschiede bei Polygonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.2.6 Unterschiede bei der Zeilenreihenfolge . . . . . . . . . . . . . . . . . . . . . . . . . . 26.2.7 Der Test random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.3 Plattformspezifische Vergleichsdateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

321
321 322 323 323 323 324 324 324 325 325

Teil IV

Client-Schnittstellen

327 329
329 337 337 339 339 340

Kapitel 27: libpq: Die C-Bibliothek
27.1 Funktionen zur Datenbankverbindung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.2 Funktionen zur Ausführung von Befehlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.2.1 Hauptfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.2.2 Zeichenketten für SQL-Befehle vorbereiten . . . . . . . . . . . . . . . . . . . . . . . 27.2.3 Binäre Daten für SQL-Befehle vorbereiten . . . . . . . . . . . . . . . . . . . . . . . . 27.2.4 Ermittlung von Informationen über Anfrageergebnisse . . . . . . . . . . . . . .

12

Inhaltsverzeichnis

27.2.5 Auslesen von Anfrageergebnissen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.2.6 Ermittlung von Ergebnissen anderer Befehle . . . . . . . . . . . . . . . . . . . . . . 27.3 Asynchrone Befehlsverarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.4 Die Fastpath-Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.5 Asynchrone Benachrichtigung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.6 Funktionen für den COPY-Befehl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.7 Funktionen zur Nachverfolgung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.8 Verarbeitung von Hinweismeldungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.9 Umgebungsvariablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.10Die Passwortdatei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.11Thread-Verhalten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.12libpq-Programme bauen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.13Beispielprogramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

341 343 343 346 347 348 350 350 351 352 352 353 354

Kapitel 28: Large Objects
28.1 Geschichte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.2 Implementierungsmerkmale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3 Clientschnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.1 Ein Large Object erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.2 Ein Large Object importieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.3 Ein Large Object exportieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.4 Ein bestehendes Large Object öffnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.5 Daten in ein Large Object schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.6 Daten aus einem Large Object lesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.7 In einem Large Object suchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.8 Die aktuelle Schreibposition eines Large Object ermitteln . . . . . . . . . . . . 28.3.9 Einen Large-Object-Deskriptor schließen . . . . . . . . . . . . . . . . . . . . . . . . . 28.3.10Ein Large Object entfernen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.4 Serverseitige Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28.5 Beispielprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

365
365 366 366 366 366 367 367 367 367 367 368 368 368 368 369

Kapitel 29: pgtcl: Die Tcl-Bindungsbibliothek
29.1 29.2 29.3 29.4 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pgtcl in eine Anwendung laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pgtcl-Befehlsreferenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Beispielprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

375
375 376 376 393

Kapitel 30: ECPG: Eingebettetes SQL in C
30.1 30.2 30.3 30.4 30.5 30.6 30.7 Das Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Zum Datenbankserver verbinden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eine Verbindung schließen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQL-Befehle ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Daten übergeben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dateien einbinden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

395
395 396 396 396 397 398 401

13

Inhaltsverzeichnis

30.8 Eingebettete SQL-Programme verarbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30.9 Bibliotheksfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30.10Interna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

402 403 403

Kapitel 31: Die JDBC-Schnittstelle
31.1 Einrichtung des JDBC-Treibers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1.1 Den Treiber besorgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1.2 Den Klassenpfad einrichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1.3 Den Datenbankserver auf JDBC vorbereiten . . . . . . . . . . . . . . . . . . . . . . 31.2 Initialisierung des Treibers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2.1 JDBC importieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2.2 Den Treiber laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2.3 Mit der Datenbank verbinden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2.4 Die Verbindung schließen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.3 Ausführung von Anfragen und Verarbeitung der Ergebnisse . . . . . . . . . . . . . . . 31.3.1 Verwendung der Interfaces Statement oder PreparedStatement . . . . . . . 31.3.2 Verwenden des Interface ResultSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.4 Ausführung von Aktualisierungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.5 Erzeugung und Modifizierung von Datenbankobjekten . . . . . . . . . . . . . . . . . . . . 31.6 Speicherung binärer Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.7 Verwendung des Treibers in einer Multithread- oder Servlet-Umgebung . . . . . . 31.8 Verbindungspools und Data Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.8.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.8.2 Anwendungsserver: ConnectionPoolDataSource . . . . . . . . . . . . . . . . . . . 31.8.3 Anwendungen: DataSource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.8.4 Data Sources und JNDI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.9 Weitere Informationsquellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

405
405 405 405 406 406 406 406 407 408 408 409 409 409 410 410 413 414 414 414 415 417 418

Kapitel 32: PyGreSQL: Die Python-Schnittstelle
32.1 32.2 32.3 32.4 32.5 32.6 Das pg-Modul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funktionen im pg-Modul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Verbindungsobjekt: pgobject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbank-Wrapper-Klasse: DB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anfrageergebnisobjekt: pgqueryobject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Large Object: pglarge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

419
419 420 428 437 444 448

Teil V

Server-Programmierung

457 459
459 460 460 460 461

Kapitel 33: SQL erweitern
33.1 33.2 33.3 33.4 Wie die Erweiterbarkeit funktioniert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Das PostgreSQL-Typensystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benutzerdefinierte Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQL-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.4.1 SQL-Funktionen mit Basistypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

Inhaltsverzeichnis

33.4.2 SQL-Funktionen mit zusammengesetzten Typen . . . . . . . . . . . . . . . . . . . 33.4.3 SQL-Funktionen als Tabellenquelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.4.4 SQL-Funktionen mit Mengenergebnissen . . . . . . . . . . . . . . . . . . . . . . . . . 33.5 Funktionen in prozeduralen Sprachen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.6 Interne Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.7 C-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.7.1 Dynamisches Laden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.7.2 Basistypen in C-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.7.3 Aufrufskonvention Version 0 für C-Funktionen . . . . . . . . . . . . . . . . . . . . 33.7.4 Aufrufskonvention Version 1 für C-Funktionen . . . . . . . . . . . . . . . . . . . . 33.7.5 Code schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.7.6 Kompilieren und Linken von dynamisch ladbaren Funktionen . . . . . . . . 33.7.7 Argumente aus zusammengesetzten Typen in C-Funktionen . . . . . . . . . . 33.7.8 Rückgabe von Zeilen (zusammengesetzten Typen) aus C-Funktionen . . 33.7.9 Rückgabe von Ergebnismengen aus C-Funktionen . . . . . . . . . . . . . . . . . 33.8 Funktionen überladen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.9 Handler für prozedurale Sprachen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.10Benutzerdefinierte Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.11Benutzerdefinierte Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.12Operator-Optimierungsinformationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.12.1COMMUTATOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.12.2NEGATOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.12.3RESTRICT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.12.4JOIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.12.5HASHES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.12.6MERGES (SORT1, SORT2, LTCMP, GTCMP) . . . . . . . . . . . . . . . . . . . 33.13Benutzerdefinierte Aggregatfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.14Erweiterungen für Indexe vorbereiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.14.1Indexmethoden und Operatorklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.14.2Indexmethodenstrategien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.14.3Indexmethoden-Unterstützungsroutinen . . . . . . . . . . . . . . . . . . . . . . . . . . 33.14.4Ein Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.14.5Optionale Merkmale von Operatorklassen . . . . . . . . . . . . . . . . . . . . . . . .

462 464 465 466 466 467 467 468 471 473 476 477 480 481 483 488 489 491 493 494 494 495 495 496 497 497 498 500 500 501 502 503 505

Kapitel 34: Server Programming Interface
34.1 34.2 34.3 34.4 Schnittstellenfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schnittstellenunterstützungsfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Speicherverwaltung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sichtbarkeit von Datenveränderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

507
508 518 523 531

Kapitel 35: Trigger
35.1 35.2 35.3 35.4 Triggerdefinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Umgang mit dem Triggermanager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sichtbarkeit von Datenveränderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ein vollständiges Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

535
535 536 538 539

15

Inhaltsverzeichnis

Kapitel 36: Das Regelsystem
36.1 Der Anfragebaum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.2 Sichten und das Regelsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.2.1 Wie SELECT-Regeln funktionieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.2.2 Sichtregeln in Nicht-SELECT-Befehlen . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.2.3 Die Leistungsfähigkeit von Sichten in PostgreSQL . . . . . . . . . . . . . . . . . . 36.2.4 Sichten aktualisieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.3 Regeln für INSERT, UPDATE und DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.3.1 Wie Update-Regeln funktionieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.3.2 Zusammenarbeit mit Sichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.4 Regeln und Privilegien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.5 Regeln und der Befehlsstatus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.6 Regeln und Trigger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

543
543 545 545 551 552 552 552 553 557 564 565 565

Kapitel 37: Prozedurale Sprachen
37.1 Installation von prozeduralen Sprachen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

569
569

Kapitel 38: PL/pgSQL: SQL prozedurale Sprache
38.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.1.1 Vorteile von PL/pgSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.1.2 Entwickeln in PL/pgSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.2 Umgang mit Apostrophen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.3 Die Struktur von PL/pgSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.4 Deklarationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.4.1 Aliasnamen für Funktionsparameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.4.2 Typen kopieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.4.3 Zeilentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.4.4 Record-Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.5 Ausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.6 Einfache Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.6.1 Zuweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.6.2 SELECT INTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.6.3 Einen Ausdruck oder eine Anfrage ohne Ergebnis ausführen . . . . . . . . . 38.6.4 Dynamische Befehle ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.6.5 Ergebnisstatus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.7 Kontrollstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.7.1 Aus einer Funktion zurückkehren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.7.2 Auswahlanweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.7.3 Einfache Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.7.4 Schleifen durch Anfrageergebnisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.8 Cursor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.8.1 Cursorvariablen deklarieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.8.2 Cursor öffnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.8.3 Cursor verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.9 Fehler und Meldungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

571
571 572 572 573 574 575 576 577 577 578 578 579 579 580 581 581 582 583 583 584 586 588 589 590 590 591 593

16

Inhaltsverzeichnis

38.10Triggerprozeduren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.11Portieren von Oracle PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.11.1Portierungsbeispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.11.2Andere zu beachtende Dinge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38.11.3Anhang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

594 595 596 601 602

Kapitel 39: PL/Tcl: Tcl prozedurale Sprache
39.1 39.2 39.3 39.4 39.5 39.6 39.7 39.8 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PL/Tcl-Funktionen und Argumente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenwerte in PL/Tcl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Globale Daten in PL/Tcl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbankzugriff aus PL/Tcl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Triggerprozeduren in PL/Tcl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Module und der Befehl unknown . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tcl-Prozedurnamen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

605
605 606 607 607 607 610 611 612

Kapitel 40: PL/Perl: Perl prozedurale Sprache
40.1 40.2 40.3 40.4 40.5 PL/Perl-Funktionen und Argumente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenwerte in PL/Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbankzugriff aus PL/Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Trusted und Untrusted PL/Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fehlende Funktionalität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

613
613 615 615 615 616

Kapitel 41: PL/Python: Python prozedurale Sprache
41.1 41.2 41.3 41.4 PL/Python-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Triggerfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Datenbankzugriff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eingeschränkte Umgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

617
617 618 618 619

Teil VI

Referenz
I. SQL-Befehle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II. PostgreSQL-Clientanwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . III. PostgreSQL-Serveranwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

621
625 786 843

Teil VII

Anhänge

861 863
863 864 869

Anhang A: Interna der Datums- und Zeitunterstützung
A.1 Eingabeinterpretation von Datum und Zeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.2 Schlüsselwörter in Datums- und Zeitangaben . . . . . . . . . . . . . . . . . . . . . . . . . . . A.3 Geschichte der Kalendersysteme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

Inhaltsverzeichnis

Anhang B: SQL-Schlüsselwörter Anhang C: SQL-Konformität
C.1 Unterstützte Leistungsmerkmale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.2 Nicht unterstützte Leistungsmerkmale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

871 887
888 894

Anhang D: Versionsgeschichte
D.1 Version 7.3.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.1.1 Umstieg auf Version 7.3.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.1.2 Änderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.2 Version 7.3.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.2.1 Umstieg auf Version 7.3.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.2.2 Änderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.3 Version 7.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.3.1 Umstieg auf Version 7.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.3.2 Änderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.4 Version 7.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.4.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.4.2 Umstieg auf Version 7.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.4.3 Änderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.5 Version 7.2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.6 Version 7.2.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.7 Version 7.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.8 Version 7.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.8.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.8.2 Umstieg auf Version 7.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.9 Version 7.1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.10 Version 7.1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.11 Version 7.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.12 Version 7.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.13 Version 7.0.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.14 Version 7.0.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.15 Version 7.0.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.16 Version 7.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.16.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.16.2 Umstieg auf Version 7.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.17 Version 6.5.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.18 Version 6.5.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.19 Version 6.5.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.20 Version 6.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.20.1 Umstieg auf Version 6.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.21 Version 6.4.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.22 Version 6.4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.23 Version 6.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D.24 Version 6.3.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

901
901 901 901 903 903 903 904 904 904 905 905 906 906 914 914 914 914 914 915 915 915 916 916 917 917 917 917 917 918 918 918 918 919 920 920 921 921 921

18

Inhaltsverzeichnis

D.25 D.26 D.27 D.28 D.29 D.30 D.31

Version 6.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 6.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 6.2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 6.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 6.1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 6.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 6.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

922 922 922 922 922 923 923

Anhang E: Systemkataloge
E.1 E.2 E.3 E.4 E.5 E.6 E.7 E.8 E.9 E.10 E.11 E.12 E.13 E.14 E.15 E.16 E.17 E.18 E.19 E.20 E.21 E.22 E.23 E.24 E.25 E.26 E.27 E.28 E.29 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_aggregate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_am . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_amop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_amproc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_attrdef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_constraint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_depend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_inherits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_largeobject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_listener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_opclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_proc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_rewrite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_shadow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_statistic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_trigger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pg_type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

925
925 926 927 928 928 929 929 930 931 932 933 934 935 936 936 936 937 938 938 939 939 939 940 941 942 942 943 944 945

Literaturverzeichnis

949
19

VAKAT VAKAT .

❏ Teil IV beschreibt die Programmierschnittstellen für PostgreSQL-Clientprogramme.und Serverprogrammen. der einen PostgreSQL-Server betreibt. Es unterstützt SQL92 und SQL99 und bietet viele moderne Fähigkeiten: ❏ ❏ ❏ ❏ ❏ ❏ komplexe Anfragen Fremdschlüssel Trigger Sichten transaktionale Integrität Multiversionskontrolle 21 . sollte diesen Teil lesen.2. Datentypen. Version 4. Client. Themen sind zum Beispiel benutzerdefinierte Datentypen und Funktionen.Einleitung Dieses Buch ist die offizielle Dokumentation von PostgreSQL. egal ob nur für sich selbst oder für andere. Es wird parallel zur Entwicklung der PostgreSQL-Software von den Entwicklern und anderen Freiwilligen geschrieben und aktualisiert. Jeder PostgreSQL-Benutzer sollte diesen Teil lesen. die erst später in einigen kommerziellen Datenbanken zur Verfügung standen. PostgreSQL ist ein Open-Source-Nachfolger dieses Codes von Berkeley. Es beschreibt sämtliche Funktionalität. ❏ Teil I ❏ Teil II Was ist PostgreSQL? PostgreSQL ist ein objektrelationales Datenbankverwaltungssystem auf Basis von POSTGRES. Dieser Teil unterstützt die anderen Teile mit nach Befehl oder Programm sortierten strukturierten Informationen. Jeder. welches in der Informatikfakultät der Universität von Kalifornien in Berkeley entwickelt wurde. beschreibt die Sprache SQL. Um bei diesem umfassenden Anspruch übersichtlich zu bleiben. die der Leser zu unterschiedlichen Zeiten zurate ziehen wird: ist eine informelle Einführung für neue Anwender. POSTGRES hat viele Konzepte eingeführt. Funktionen und Tipps zur Leistungsverbesserung auf Benutzerebene. ist dieses Buch in mehrere Teile aufgeteilt. ❏ Teil VI enthält Informationen über die Syntax von SQL-Befehlen. ❏ Teil III beschreibt die Installation und Verwaltung des Servers. die die vorliegende PostgreSQL-Version offiziell unterstützt. ❏ Teil V enthält Informationen für fortgeschrittene Benutzer über die Erweiterungsfähigkeiten des Servers.

benutzt. POSTGRES wurde für die Implementierung von vielen verschiedenen Forschungs. wurde gesponsert von der Defense Advanced Research Projects Agency (DARPA). Goh 1990) und im Juni 1990 wurde Version 2 mit dem neuen Regelsystem freigegeben. was jetzt zu IBM gehört) den Code genommen und kommerzialisiert. POSTGRES wurde auch als Lehrwerkzeug an mehreren Universitäten verwendet. zum Beispiel mit ❏ ❏ ❏ ❏ ❏ ❏ Datentypen Funktionen Operatoren Aggregatfunktionen Indexmethoden prozeduralen Sprachen Und wegen der liberalen Lizenz kann PostgreSQL von allen kostenlos für alle Zwecke. ob privat. verändert und weitergegeben werden. Die Implementierung von POSTGRES begann 1986. Hirohama 1990. Das erste „Demoware“-System war 1987 einsatzbereit und wurde 1988 auf der ACM-SIGMOD-Konferenz gezeigt. dem Army Research Office (ARO). Hearst. dass die Wartung des Prototypcodes und der Support eine Menge Zeit in Anspruch nahmen. Die kurze Geschichte von PostgreSQL Das heutzutage als PostgreSQL bekannte objektrelationale Datenbankverwaltungssystem stammt vom POSTGRES-Paket der Universität von Kalifornien in Berkeley ab. Hong 1987 beschrieben. um seinen eigenen Weg als Open-Source-Nachfolger des ursprünglichen POSTGRES-Codes zu finden. unter Anleitung von Professor Michael Stonebraker. Postgres95 Im Jahr 1994 bauten Andrew Yu und Jolly Chen einen SQL-Interpreter in POSTGRES ein.2 offiziell eingestellt. geschäftlich oder akademisch. der National Science Foundation (NSF) und ESL. beschrieben in Stonebraker. Das POSTGRES-Projekt in Berkeley Das POSTGRES-Projekt. Die Architektur des Storagemanagers wurde in Stonebraker 1987 beschrieben. ein Paket zur Überwachung der Leistung von Düsentriebwerken. Rowe. Schließlich hat Illustra Information Technologies (später fusioniert mit Informix. Der Entwurf des Regelsystems zu dieser Zeit wurde in Stonebraker. 22 . einem verbesserten Anfrage-Executor und einem neu geschriebenen Umschreiberegelsystem. Jhingran. Version 1. Als Reaktion auf eine Kritik des ersten Regelsystems (Stonebraker. Potamianos 1989) wurde das Regelsystem neu entworfen (Stonebraker. Seitdem hat POSTGRES mehrere Hauptversionen erlebt. Im Verlauf des Jahres 1993 hatte sich die Größe der externen Benutzergemeinde nahezu verdoppelt. Nach mehr als einem Jahrzehnt Entwicklungsarbeit ist es jetzt das fortschrittlichste Open-Source-Datenbanksystem. Es wurde zunehmend klar.und Produktionsanwendungen verwendet. wurde im Juni 1989 einigen externen Benutzern zugänglich gemacht. eine Datenbank zur Verfolgung von Asteroiden und eine medizinische Informationsdatenbank. Um diese Last zu verringern wurde das POSTGRES-Projekt in Berkeley mit Version 4. Version 3 erschien 1991 mit Unterstützung für mehrere Storagemanager. Im Jahr 1992 wurde POSTGRES der primäre Datenmanager des wissenschaftlichen Computing-Projekts Sequoia 2000. Inc. Die folgenden Versionen bis Postgres95 (siehe unten) haben sich dann hauptsächlich auf Portierbarkeit und Zuverlässigkeit konzentriert. Die anfänglichen Konzepte wurden in Stonebraker & Rowe 1986 vorgestellt und die Definition des Datenmodells erschien in Rowe & Stonebraker 1987.Einleitung Außerdem ist PostgreSQL auf einzigartige Weise vom Benutzer erweiterbar. Hanson. Unter anderem: ein System zur Analyse von finanziellen Daten. die eigentlich der Datenbankforschung gewidmet werden sollte. Unter neuem Namen wurde Postgres95 im Web freigegeben.

Mit PostgreSQL verschob sich die Konzentration auf neue Features und Fähigkeiten.) ❏ Das Regelnsystem auf Instanzebene wurde entfernt. der das Verhältnis zwischen dem ursprünglichen POSTGRES und den neueren Versionen mit SQL-Unterstützung widerspiegelt. Die Inversion-Large-Objects waren jetzt der einzige Mechanismus für Large Objects. ❏ GNU Make (anstatt BSD Make) wurde für die Compilierung verwendet. welches GNU Readline verwendete. um von Tcl-Programmen aus auf den Postgres95-Server zugreifen zu können. Und natürlich wurden sämtliche Fakten noch einmal überprüft. Gleichzeitig wurde die Versionsnummer auf 6.0 gesetzt. Postgres95 Version 1. unterstützte Clients auf Tcl-Basis. Allerdings ist die Dokumentation für diese Buchausgabe vollständig überarbeitet worden. Die Kapitel wurden methodisch sinnvoller angeordnet und ganze Abschnitte umgeschrieben. Insbesondere wurde die alte Aufteilung der PostgreSQL-Dokumentation in mehrere Bände aufgegeben. Das Stichwortverzeichnis wurde erheblich erweitert. dass der Name „Postgres95“ dem Test der Zeit nicht standhalten würde. Version 4. Aggregatfunktionen wurden neu implementiert. Was sich seither in PostgreSQL im Einzelnen getan hat. ❏ Eine neue Clientbibliothek. Unterstützung für die Anfrageklausel GROUP BY wurde ebenfalls hinzugefügt. PostgreSQL. Viele interne Veränderungen haben die Leistung und die Wartungsfreundlichkeit des Codes verbessert. ❏ Ein kurzes Tutorial mit einer Einführung in SQL und Postgres95 wurde mit dem Quellcode verteilt. Sämtliche Änderungen sind auch in die Originalversion der PostgreSQL-Dokumentation eingeflossen und werden in der nächsten öffentlichen PostgreSQL-Version enthalten sein. können Sie in Anhang D sehen. Neben berichtigten Fehlern waren dies die bedeutenden Verbesserungen: ❏ Die Anfragesprache PostQUEL wurde durch SQL ersetzt (im Server implementiert). libpgtcl. (Dieses Buch hat also diesbezüglich gewissermaßen Weltpremierencharakter. PostgreSQL Im Jahre 1996 wurde klar. bot neue Tcl-Befehle.Einleitung Der Postgres95-Code war komplett in ANSI C und die Größe wurde um 25 % reduziert.0. Unteranfragen wurden erst in PostgreSQL (siehe unten) unterstützt. ❏ Neben dem „Monitor“-Programm wurde ein neues Programm (psql) für interaktive SQL-Anfragen angeboten. wenn die Informationen aus der aktuellsten Entwicklerversion verwendet werden. wodurch die Nummern die in Berkeley begonnene Reihe fortsetzten. Eine Beispiel-Shell. ❏ Die Large-Object-Schnittstelle wurde überholt. aber sie konnten in Postgres95 mit benutzerdefinierten SQL-Funktionen nachgeahmt werden. weil diese Informationen nur für Entwickler von PostgreSQL selbst sinnvoll sind. Regeln waren immer noch als Umschreiberegeln verfügbar. Über diese Ausgabe Diese Buchausgabe hat die Dokumentation von PostgreSQL Version zur Grundlage. pgtclsh. 23 . obwohl die Arbeit in allen Bereichen weiterging. (Das Inversion-Dateisystem wurde entfernt. Also haben wir einen neuen Namen.) Weggelassen wurden in dieser Ausgabe nur einige Kapitel aus dem Interna-Teil.x war in der Wisconsin Benchmark etwa 30–50% schneller als POSTGRES. ausgewählt.2. Außerdem konnte Postgres95 mit einem ungepatchten GCC kompiliert werden (Datenausrichtung von double-Werten wurde repariert). Außerdem wurde aus Platzgründen die Versionsgeschichte bei den älteren Versionen etwas gekürzt. und dann auch nur. Während der Entwicklung von Postgres95 lag die Betonung auf dem Verstehen von bestehenden Problemen in Servercode.

Einleitung Konventionen Dieses Buch verwendet folgende typografische Konventionen. dass Sie eine Alternative auswählen müssen. Wenn es der Klarheit dient. entweder durch die Dokumentation oder durch Mailinglisten. denn dieses Buch macht keine Annahmen über die Systemverwaltungsprozeduren.. Programmcode und Bildschirmausgaben. In der Regel werden die Eingabeaufforderungen aber nicht mit angegeben. das in der Dokumentation unzureichend erklärt wird. um bestimmte Textteile hervorzuheben: Neue Begriffe. Innerhalb solcher Textteile bedeutet kursive Schrift (Beispiel). Gelegentlich werden Stellen in Programmcode durch fette Schrift (Beispiel) hervorgehoben. Im Übrigen ist in diesem Buch jeder ein Benutzer. Wenn Sie anfangen. dann schicken Sie Patches an die Entwickler.) bedeuten. Diese Begriffe sollten aber nicht zu eng gesehen werden. dass das vorherige Element wiederholt werden kann. Daher baut es darauf. Mailinglisten Die Mailinglisten sind ein guter Ort. dass Sie an dieser Stelle einen konkreten Wert anstelle des Platzhalters einsetzen müssen. Wenn Sie den Code erweitern. werden Sie die Hilfe anderer benötigen. Ein Administrator ist im Allgemeinen die Person. (In der Synopsis eines Tcl-Befehls werden stattdessen Fragezeichen (?) verwendet.) Geschweifte Klammern ({ und }) und senkrechte Striche (|) bedeuten. Lesen Sie die Mailinglisten und beantworten Sie Fragen. wird in einer nicht proportionalen Schrift dargestellt (Beispiel). wie es bei Tcl üblich ist. Fremdwörter (die nicht als Fachwörter übernommen wurden) und sonstige wichtige Stellen werden kursiv hervorgehoben. insbesondere Befehle. READMEs Für einige Extrapakete gibt es README-Dateien im Quellcodebaum. das heißt diesem Buch. Weitere Informationen Neben der Dokumentation. Wenn Sie etwas erfahren. was eine Eingabe in oder eine Ausgabe aus dem Computer darstellt.. gibt es weitere Informationsquellen über PostgreSQL: FAQ Die FAQ-Liste enthält laufend aktualisierte Antworten auf häufig gestellte Fragen. Punkte (. Ihre Erfahrungen mit anderen teilen oder mit den Entwicklern in Verbindung treten können. dass sich die Benutzer gegenseitig unterstützen. dann sollten Sie diese wiederum mit anderen teilen. dann steht vor SQL-Befehlen die Eingabeaufforderung => und vor ShellBefehlen $. Einrichtung und Überwachung des Servers verantwortlich ist. die für die Installierung. Website Die PostgreSQL-Website enthält Einzelheiten über neue Versionen und andere Informationen. dann schreiben Sie darüber und schicken es ein. wo Sie Antworten auf Ihre Fragen erhalten. Einzelheiten dazu erfahren Sie auf der PostgreSQL-Website. Wenn Sie Erfahrungen gesammelt haben. der irgendeinen Teil des PostgreSQL-Systems verwendet oder verwenden möchte. wenn sie gegenüber dem vorangegangenen Beispiel hinzugefügt oder verändert worden sind. PostgreSQL zu verwenden. In der Synopsis eines Befehls werden folgende Konventionen verwendet: Eckige Klammern ([ und ]) zeigen optionale Teile an. 24 . Alles. die Ihre Arbeit oder Ihr Vergnügen mit PostgreSQL produktiver machen können. Sie selbst! PostgreSQL ist ein Open-Source-Projekt.

dann stehen die Chancen gut. wirklich zulässig ist. Ihre Fehlerberichte spielen eine wichtige Rolle bei der Entwicklung von PostgreSQL. prüfen Sie die “TODO”-Liste und die FAQ. ob Ihr Fehler schon bekannt ist.oder Fehlermeldung. Was berichtet werden sollte Am wichtigsten ist es bei einem Fehlerbericht. das ist nämlich ein Fehler in der Dokumentation. dann ist das nicht unbedingt ein Fehler. ob der Fehler dort auch auftritt. die auf ein Problem im Programm hindeutet. Oder wir könnten zu dem Schluss kommen. Wir können Ihnen nicht versprechen. abgebrochen. wenn ein größeres. Wenn der Fehler offensichtlich oder gefährlich ist oder viele Benutzer betrifft. ob etwas zulässig ist. dann wollen wir das wissen. Fehlerberichte zusammenzustellen. ❏ PostgreSQL kann nicht entsprechend den Installationsanweisungen auf einer unterstützten Plattform kompiliert. Die folgende Liste enthält mögliche Fehlerumstände. Die folgenden Vorschläge sollen Ihnen dabei helfen.) ❏ Ein Programm erzeugt die falsche Ausgabe für irgendeine Eingabe. um Unterstützung bei der Feinabstimmung Ihrer Anwendungen zu erhalten. dann sollten Sie kommerzielle Unterstützung suchen. Lesen Sie die Dokumentation oder fragen Sie auf einer der Mailinglisten nach. aber es ist meist für alle Seiten von Vorteil. Mangelhafte Konformität mit dem SQL-Standard ist auch kein Fehler. Wenn Sie die Informationen auf der TODO-Liste nicht entziffern können. Wenn es aus der Dokumentation nicht klar hervorgeht. dann ist das ein Fehler. die Konformität wurde in einem bestimmten Bereich ausdrücklich angegeben. gültige Eingaben anzunehmen (wobei gültige Eingaben in der Dokumentation definiert sind). Bevor Sie weitermachen. dass ein Programm etwas anderes tut. dass die Festplatte voll ist. es sei denn. dass jeder Teil von PostgreSQL unter allen Umständen und auf jeder Plattform funktioniert. Zumindest könnten wir dann die TODO-Liste etwas klarer machen. lesen Sie bitte die Dokumentation gründlich. Es könnte auch sein. was Sie versucht haben. weil selbst die größte Sorgfalt nicht garantieren kann. sich daran zu halten. dass Sie alle Fakten und nur Fakten angeben. Aber bedenken Sie. ist aber nicht abschließend. Fehler identifizieren Bevor Sie über einen Fehler berichten. dass der Fehler erst repariert werden kann.Einleitung Richtlinien für Fehlerberichte Wenn Sie einen Fehler in PostgreSQL finden. um zu überprüfen. Niemand ist verpflichtet. ❏ Ein Programm wird von einem Signal oder mit einer Fehlermeldung aus dem Betriebssystem. dann berichten Sie Ihr Problem trotzdem. (Ein Gegenbeispiel wäre eine Meldung. ❏ Ein Programm weigert sich. Wenn Sie sofort Hilfe benötigen. dann sollten Sie das auch berichten. was wohl schiefgegangen ist oder was es “anscheinend” 25 . dass sich jemand die Sache anschauen wird. dass Ihre Vorstellung von ungültiger Eingabe unsere Vorstellung von einer Erweiterung oder Kompatibilität mit alten Gewohnheiten sein könnte. weil Sie das Problem selber lösen müssen. die effektiv bearbeitet werden können. dass wir Ihnen sagen werden. eine neuere Version auszuprobieren und festzustellen. Fangen Sie nicht an. als die Dokumentation aussagt. Wenn es sich herausstellt. Vermutungen darüber anzustellen. Wenn ein Programm zu langsam ist oder zu viele Ressourcen verbraucht. Hier bezieht sich “Programm” auf jedes Programm. nicht nur auf den Server. geplantes Codeprojekt abgeschlossen ist. gebaut oder installiert werden. jeden Fehler sofort zu reparieren. ob das. Oder es ist einfach zu kompliziert und es gibt wichtigere Dinge auf der Tagesordnung. um zu sehen. ❏ Ein Programm akzeptiert ungültige Eingaben ohne Warn.

wenn die Ausgabe von Daten in einer Tabelle abhängig sein soll. so eine Datei zusammenzustellen. wie das geschieht. dann wäre dies eine gute Gelegenheit. dass es auf unseren Plattformen anders ausgeht. Wenn Sie einfach schreiben: “Dieser Befehl erzeugt diese Ausgabe. (Wenn Ihr Problem ein Programmabsturz ist. einfach nur zu sagen. aber viel zu oft werden wichtige Einzelheiten weggelassen. (Achten Sie darauf. und denken. dass wir die Bedeutung Ihrer Befehle entziffern werden. Sie gegenüber der Standardeinstellung verändert haben. dann müssen Sie auch die vorangegangenen CREATE TABLE. und wir wissen auch nicht. ❏ Welche Ausgabe Sie erwartet haben. Das beste Format für ein Testbeispiel eines Problems. aber kein Ersatz für Fakten. dann müssen wir ihn erst selbst auftreten sehen. mit denen das Problem reproduziert werden kann.) Eine einfache Möglichkeit. wenn möglich. 26 . dass Sie nichts in der Startdatei ~/. Wenn Sie sich in der Implementierung nicht auskennen. ist ganz wichtig. dann zeigen Sie sie. Wenn es eine Fehlermeldung gibt. das mit SQL zu tun hat. dann wird Ihre Vermutung wahrscheinlich falsch sein und uns kein bisschen weiterhelfen. dann sagen Sie das. Wenn gar nichts passiert. die Sie erhalten haben. selbst wenn Sie sie nicht verstehen. dann werden wir es vielleicht selbst probieren. ist ziemlich einfach (Sie können sie wahrscheinlich direkt vom Bildschirm kopieren). Seien Sie wiederum genau. dass das Problem bei “großen Dateien” oder “mittelgroßen Datenbanken” auftritt. Wenn Sie eine Paketdistribution verwenden. Bitte schauen Sie auch in die Logausgabe des Datenbankservers. dann werden wir das Problem wahrscheinlich nicht entdecken. Ihr Datenbankschema zu erraten. dann müssen Sie hierzu logischerweise nichts angeben. dann sind wohl begründete Erklärungen eine großartige Ergänzung zu. ist nicht besonders unterhaltsam. weil solche Informationen nutzlos sind. Diese Informationen sollten vollständig sein. dass sie nicht wichtig sind oder dass der Bericht trotzdem verstanden werden würde. die Ausgabe vom Terminal zu kopieren.) ❏ Welche Kommandozeilenoptionen und andere Startparameter. Wenn der Fehler reproduzierbar ist. dann werden wir ihn so oder so finden. die Größe Ihres Beispiels auf ein Minimum zu reduzieren. Wenn das Programm mit einem Betriebssystemfehler abbricht. Die folgenden Elemente sollten in jedem Fehlerbericht enthalten sein: ❏ Die genaue Reihenfolge der Schritte vom Programmstart an. dass etwas “nicht funktioniert” oder “abgestürzt” ist. einschließlich Umgebungsvariablen und Konfigurationsdateien.” Das richtige Verhalten aus dem SQL-Standard herauszusuchen. die den Datenbankserver beim Booten startet. Wenn Ihre Anwendung eine andere Clientschnittstelle verwendet. Denken Sie auf jeden Fall daran. ❏ Die Ausgabe. weil jemand dachte. ein einzelner SELECT-Befehl reicht nicht aus. Anmerkung Bei schweren Fehlern.Einleitung gemacht hat oder welcher Teil des Programms einen Fehler hat. Stellen Sie keine ungenauen Vermutungen an.” oder “Dieses Ergebnis habe ich nicht erwartet. dann sollten Sie herausfinden. etwa PHP. die genauen Eingabedateien mitzuschicken.psqlrc haben. dann versuchen Sie bitte. Selbst wenn das Ergebnis Ihres Testbeispiels ein Programmabsturz oder anderweitig offensichtlich ist. die Ausgabe kurz prüfen. Sie sollten nicht erwarten. um Ihr Problem zu entdecken.”. Sie sollten auch davon absehen.” oder “Oracle macht es anders. Die reinen Fakten zu berichten. “Das stimmt nicht mit dem SQL-Standard überein. die problematischen Anfragen herauszufinden. Sie sollten versuchen. könnte es sein. Am einfachsten ist es. Aber selbst wenn Sie sich auskennen. die die Datenbanksitzung abbrechen. und wenn wir unsere eigenen Daten erfinden sollen. damit anzufangen. Wir haben keine Zeit. Schreiben Sie bitte nicht. Wir werden wahrscheinlich nicht erst einen Webserver einrichten. enthält die im Client sichtbare Fehlermeldung möglicherweise nicht alle verfügbaren Informationen. ist eine Datei. dass alles in Ordnung ist und dass wir es genau so erwartet hätten.und INSERT-Befehle angeben. dann zeigen Sie den ebenfalls. Wenn Sie die Logausgabe des Servers nicht speichern. ist mit pg_dump die Tabellendeklarationen und Daten in einer Datei zu speichern und dann die problematische Anfrage hinzuzufügen. die mit dem Clientprogramm psql ausgeführt werden kann und so das Problem aufzeigt. Wenn wir den Fehler berichtigen sollen. aber das ist nicht unbedingt nötig. wie all die anderen relationalen Datenbanken dieser Welt funktionieren.

❏ Plattforminformationen. Wenn Ihre Eingabedateien allerdings riesig sind. Wenn die Funktion oder die Optionen nicht vorhanden sind.oder der Serverseite liegt. Wenn Sie einen CVS-Schnappschuss verwenden. dann wird er automatisch an die Mailingliste pgsqlbugs@postgresql. dann werden Sie immer noch Zeit haben. ob sich jemand die Sache ansehen will.org oder pgsql-general@postgresql. Eine weitere Möglichkeit ist das Ausfüllen des entsprechenden Web-Formulars auf der Projektwebsite . Bitte geben Sie genau an. dann sollten Sie das sagen und auch eine eventuelle Unterversion des Pakets angeben. aber Sie sollten nicht davon ausgehen.Einleitung ❏ Jegliche Abweichungen von den Installationsanweisungen. was in “Debian” enthalten ist oder dass jeder Pentiums verwendet. Mit dem Befehl SELECT version(). durch welche Änderungen in der Eingabe das Problem verschwindet. manchmal auch kurz “Postgres”. dann ist Ihre Version mehr als alt und sollte unbedingt aktualisiert werden. 27 . Bitte senden Sie keinen Fehlerbericht an Benutzer-Mailinglisten wie pgsql-sql@postgresql. Diese Liste ist für Diskussionen über die Entwicklung von PostgreSQL. können Sie die Version des Servers herausfinden. Diese Mailinglisten sind für die Beantwortung von Benutzerfragen. dann könnten wir eine Diskussion über das Problem auf pgsql-hackers aufnehmen. dann sagen Sie das und nicht einfach “PostgreSQL stürzt ab”. Es ist besser. Wenn Sie eine Paketdistribution verwenden.org geschickt.org senden. und die Leser wollen dort normalerweise keine Fehlerberichte erhalten. wenn nur ein einzelner Serverprozess abgestürzt ist. ob das Problem auf der Client. zumindest sollte postmaster --version und psql --version funktionieren. deswegen bringen wir neue Versionen heraus. vielleicht einen Teil der Fehlermeldung. dann benötigen wir auch Informationen über den Compiler. dann sollten Sie Datum und Zeit dazu angeben. Wenn Sie Installationsprobleme haben. und es wäre nett. ❏ Die PostgreSQL-Version. bitte schreiben Sie nicht “Der Postmaster ist abgestürzt”. wenn Sie alles beim ersten Mal mit angeben. Wenn Ihre Version älter ist als . dann ist es vertretbar. In den meisten Fällen reicht es aus. Wenn Ihr Problem einer ausführlicheren Prüfung bedarf. Und höchstwahrscheinlich werden die Leser die Fehler auch nicht berichtigen können. Außerdem sind Clientprogramme wie “psql” vollkommen getrennt vom Server. Das werden wir schon früh genug herausfinden. dann werden wir Ihnen höchstwahrscheinlich raten. Senden Sie bitte auch keine Fehlerberichte an die Entwickler-Mailingliste pgsql-hackers@postgresql. Das wird bei der Lösung wahrscheinlich nicht helfen. dass Sie erstmal nachfragen. Wenn Sie einen Fehlerbericht schreiben. dass jeder weiß. zum Beispiel ein RPM-Paket. Prozessor und Speicherinformationen. C-Bibliothek. Und noch einmal sei gesagt: Verschwenden Sie Ihre Zeit nicht damit. dass der Fehler nicht sofort berichtigt werden kann.org. Das ist halt so. den Hersteller und die Version anzugeben. Wenn ein Bericht dort eingegeben wird. Ein Absturz eines einzelnen Serverprozesses ist etwas ganz anderes als ein Absturz des “postmaster”-Prozesses. Das bedeutet Kernelname und -version. eine neuere Version zu verwenden. Sie sollten sich nicht scheuen. wenn Ihr Fehlerbericht ziemlich lang wird. Wenn Sie konkret vom Serverprogramm sprechen. einen vorübergehenden Ausweg zu finden und mitzuteilen. Das Softwarepaket selbst heißt “PostgreSQL”. das Make-Programm usw. wenn wir die Fehlerberichte getrennt halten könnten. Wo Fehler berichtet werden können Prinzipiell sollten Sie Fehlerberichte an die dafür gedachte Mailingliste pgsql-bugs@postgresql. zu raten. mit dem Sie verbunden sind. herauszufinden. Die meisten Programme unterstützen auch eine Option -version. Verschwenden Sie Ihre Zeit nicht damit. als dass wir die Fakten aus Ihnen herausquetschen müssen. Wenn es sich herausstellt. dann verwenden Sie bitte klare Terminologie. Bitte wählen Sie eine beschreibende Betreffzeile. In jeder neuen Version werden eine Menge Fehler berichtigt.org. warum der Fehler auftritt. und auch nicht umgekehrt.

aber selbst keine Post bekommen wollen. (Für das Web-Formular müssen Sie sich aber nicht irgendwo anmelden. mit dem Sie ein Problem haben. Bitte geben Sie den genauen Teil der Dokumenation an. damit wir (und Sie) an der Unterstützung für Ihre Plattform arbeiten können. Sie müssen sich erst bei der Liste anmelden.) Wenn Sie an die Listen schreiben wollen. dann können Sie sich anmelden und dann Ihre Anmeldung auf nomail setzen.Einleitung Wenn Sie ein Problem mit der Dokumentation haben. Das heißt. schreiben Sie eine E-Mail an majordomo@postgresql.org mit nur dem Wort help im Text. 28 . dann schreiben Sie am besten an die Dokumentations-Mailingliste pgsql-docs@postgresql. dann schreiben Sie an pgsql-ports@postgresql. Wenn Ihr Problem ein Portierungsproblem auf einer nicht unterstützten Plattform ist. Um weitere Informationen zu erhalten. um dort posten zu dürfen.org.org. Anmerkung Weil leider viel zu viel Spam umhergeht. sind alle oben genannten E-Mail-Adressen geschlossene Mailinglisten.

Wenn Sie Ihren eigenen Server einrichten und verwalten wollen. Keine besonderen Erfahrung mit Unix oder mit Programmieren ist vonnöten. dass die Behandlung der Themen vollständig und tiefgründig ist. dann sollten Sie auch Teil III lesen. oder Teil IV um zu erfahren. Sie benötigen nur etwas allgemeines Wissen. 29 . Sie sollten nicht davon ausgehen. Dieser Teil soll Ihnen vor allem praktische Erfahrung mit den wichtigen Teilen des PostgreSQL-Systems geben.3 Teil I Tutorial Willkommen zum PostgreSQL-Tutorial. wie man Computer verwendet. relationale Datenbanken und die Sprache SQL geben. wie Sie Anwendungen für PostgreSQL entwickeln können. wenn Sie mit einem dieser Bereiche noch nicht vertraut sind. Die folgenden Kapitel sollen Ihnen eine Einführung in PostgreSQL. um die Sprache SQL genauer kennen zu lernen. können Sie Teil II lesen. Wenn Sie dieses Tutorial durchgearbeitet haben.

VAKAT VAKAT .

ob Ihre Umgebungsvariablen richtig gesetzt sind.1 1 Ein Einstieg 1. Möglicherweise ist PostgreSQL bei Ihnen schon installiert. sollten Sie ein grundlegendes Verständnis der Systemarchitektur von PostgreSQL haben. die nicht den Standardvorgaben entsprechen. Wenn Sie verstehen. In diesem Fall sollten Sie Ihren Systemadministrator um Informationen bitten. Wenn der Systemadministrator Einrichtungen vorgenommen hat. Wenn Sie nicht sicher sind. lesen Sie den nächsten Abschnitt. dann müssen Sie die Umgebungsvariable PGHOST auf den Namen der Datenbankservermaschine setzen. In der Sprache der Datenbanktechnik verwendet PostgreSQL ein Client/Server-Modell. Das ist nicht schwer und kann eine gute Übung sein. Kehren Sie zu diesem Tutorial zurück. PostgreSQL kann von jedem unprivilegierten Benutzer installiert werden. Wenn zum Beispiel der Datenbankserver ein anderer Computer ist. dann sollten Sie die Dokumentation zurate ziehen um zu prüfen. oder weil der Systemadministrator es schon installiert hat. Mit Sorgfalt sollten Sie den Abschnitt lesen.2 Grundlagen der Architektur Ehe wir fortfahren. Die Umgebungsvariable PGPORT muss möglicherweise auch gesetzt werden. Eine PostgreSQL-Sitzung besteht aus den folgenden kooperierenden Prozessen (Programmen): 31 . Wenn Sie den vorangegangenen Absatz nicht verstanden haben. finden Sie die Installationsanweisungen in Kapitel 14. wie Sie auf PostgreSQL zugreifen können. wird dieses Kapitel etwas klarer. müssen Sie es natürlich installieren. ob PostgreSQL bereits verfügbar ist oder ob Sie es zum Ausprobieren verwenden können. sollten Sie sich mit Ihrem Systemadministrator in Verbindung setzen.1 Installation Bevor Sie PostgreSQL verwenden können. entweder. dann können Sie es selbst installieren. weil es in Ihrer Betriebssystem-Distribution enthalten war. wie man die passenden Umgebungsvariablen einrichtet. wenn die Installation abgeschlossen ist. der beschreibt. oder wenn Sie das selbst sind. wie die Teile von PostgreSQL zusammenarbeiten. haben Sie eventuell noch etwas Arbeit vor sich. sich dass es nicht zur Datenbank verbinden kann. Wenn Sie PostgreSQL selbst installieren. Letztendlich gilt: Wenn Sie ein Anwendungsprogramm starten und es beschwert. 1. Superuser-Rechte (root) sind nicht erforderlich.

ein Webserver. sind möglicherweise auf der Datenbankserver-Maschine nicht zugänglich (oder nur unter einem anderen Namen). der die Datenbankdateien überwacht. in diesem Beispiel mit Namen meinedb. können sich Client und Server auf verschiedenen Rechnern befinden. Danach kommunizieren der Client und der neue Serverprozess ohne das Eingreifen des ursprünglichen postmaster-Prozesses. Das Datenbankserverprogramm heißt postmaster. verwenden Sie den folgenden Befehl: $ createdb meinedb Das sollte folgende Antwort erzeugen: CREATE DATABASE Wenn ja. um die Situation zu bereinigen. Ein laufender PostgreSQL-Server kann mehrere Datenbanken verwalten. Versuchen Sie. eine grafische Anwendung. Setzen Sie sich mit dem Systemadministrator in Verbindung oder prüfen Sie noch einmal die Installationsanweisungen. Dazu startet er einen neuen Prozess für jede Verbindung (mit dem Systemaufruf fork). die auf der Clientmaschine zur Verfügung stehen. zu erstellen. Clientanwendungen können sehr verschiedener Natur sein: Ein Client könnte ein textorientiertes Tool sein. (AlPostgreSQLl das ist natürlich für Benutzer unsichtbar. der auf die Datenbank zugreift um Webseiten darzustellen. Wie es bei Client/Server-Anwendungen typisch ist. die Datenbankoperationen vornehmen will. ❏ Die Clientanwendung des Benutzers. Einige Clientanwendungen sind in der PostgreSQL-Distribution enthalten. Verbindungen von Clientanwendungen akzeptiert und Aktionen in der Datenbank für den Client ausführt. ist. Der PostgreSQL-Server kann mehrere gleichzeitige Verbindungen von Clients handhaben. aber die meisten werden von Benutzern entwickelt. während Client. Folglich läuft der postmaster immer und wartet auf Verbindungen. ob Sie auf den Datenbankserver zugreifen können. eine Datenbank zu erzeugen. Um eine neue Datenbank. dann ist PostgreSQL nicht ordnungsgemäß installiert worden. oder eine spezialisiertes Datenbankverwaltungswerkzeug. was der Name dieser Datenbank ist. Wir erwähnen es hier nur der Vollständigkeit halber. Normalerweise verwendet man eine separate Datenbank für jedes Projekt oder für jeden Benutzer. den Befehl mit einem absoluten Pfad aufzurufen: $ /usr/local/pgsql/bin/createdb meinedb Der Pfad mag bei Ihnen ein anderer sein. 32 .und die zugehörigen Serverprozesse entstehen und wieder verschwinden. Sie sollten das im Hinterkopf behalten. um zu sehen.) 1.Kapitel 1 ❏ Ein Server-Prozess. Wenn Sie eine Mitteilung ähnlich wie createdb: command not found sehen. Er sollte Ihnen dann mitgeteilt haben. In diesem Fall kommunizieren sie über eine TCP/IP-Netzwerkverbindung. dann war dieser Schritt erfolgreich und Sie können den Rest dieses Abschnitts überspringen.3 Eine Datenbank erzeugen Der erste Test. Möglicherweise hat der Systemadministrator schon eine Datenbank für Sie erstellt. In diesem Fall können Sie diesen Schritt auslassen und zum nächsten Abschnitt springen. denn Dateien. Entweder wurde es überhaupt nicht installiert oder der Suchpfad wurde nicht richtig gesetzt.

die zum Erzeugen einer Datenbank erforderlich sind. dann können Sie sie mit dem folgenden Befehl zerstören: $ dropdb meinedb (Bei diesem Befehl ist der Vorgabewert für den Datenbanknamen nicht der Benutzername. Wenn Sie zum Beispiel der Eigentümer (Erzeuger) der Datenbank meinedb sind. Der Datenbankname muss immer angegeben werden. Eine Erklärung warum das funktioniert: PostgreSQL-Benutzernamen sind getrennt von den Benutzernamen des Betriebssystems. Datenbanken zu erzeugen. geben Sie einfach ein: $ createdb Wenn Sie Ihre Datenbank nicht mehr verwenden wollen. Wenn Sie PostgreSQL selbst installiert haben.PGSQL.s. dann werden Sie Folgendes sehen: ERROR: CREATE DATABASE: permission denied createdb: database creation failed Nicht jeder Benutzer hat die Autorisierung. 1. wo createdb ihn erwartete. Wenn PostgreSQL sich weigert. dass der Server nicht gestartet wurde oder dass er nicht dort gestartet wurde. können Sie sie entfernen. und passenderweise hat dieser Benutzer auch immer das Recht. schauen Sie nochmal in den Installationsanweisungen nach oder fragen Sie den Systemadministrator. können Sie auch überall die Option -U verwenden. Wenden Sie sich an den Systemadministrator. 1 Sie können auch Datenbanken mit anderen Namen erzeugen.) Diese Aktion entfernt alle Dateien. Anstelle sich als dieser Benutzer anzumelden. und kann nicht rückgängig gemacht werden. Auch in diesem Fall gilt. Er sollte daher nur nach sorgfältiger Überlegung angPostgreSQLewendet werden. dann muss Ihnen Ihr Systemadministrator die Erlaubnis erteilen. 33 . als welcher PostgreSQL-Benutzer Sie verbinden wollen. können Sie bestimmen. sollten Sie sich für dieses Tutorial als der Benutzer anmelden. falls das passiert. Die Namen von Datenbanken müssen einen Buchstaben als erstes Zeichen haben und sind auf maximal 63 Zeichen Länge begrenzt. Viele Programme nehmen diesen Namen als Vorgabe an und können Ihnen somit etwas Tipparbeit ersparen.5432"? createdb: database creation failed Das bedeutet. Datenbanken erzeugen zu dürfen. wenn Sie das nicht tun. als der Sie verbinden wollen.Ein Einstieg Eine andere Antwort könnte diese sein: psql: could not connect to server: Connection refused Is the server running locally and accepting connections on Unix domain socket "/tmp/. als der Sie den Server gestartet haben. PostgreSQL erlaubt die Erzeugung von beliebig vielen Datenbanken in einer Installation. dann wird der Benutzername des Betriebssystems als Vorgabe verwendet. neue Datenbanken zu erzeugen. für Sie neue Datenbanken zu erzeugen. Wenn Sie zu einer Datenbank verbinden. Um eine solche Datenbank zu erzeugen. Wenn Sie die Rechte nicht haben. um einen PostgreSQL-Benutzer zu bestimmen. Eine günstige Wahl ist eine Datenbank mit dem gleichen Namen wie Ihr Benutzername. die zu dieser Datenbank gehören. Passenderweise gibt es immer einen PostgreSQL-Benutzer der den gleichen Namen hat wie der Betriebssystembenutzer der den Server gestartet hat.

Wenn Sie Probleme damit haben. Diese Möglichkeiten werden ausführlicher in Teil IV besprochen. und der zeigt an.4 Auf eine Datenbank zugreifen Wenn Sie eine Datenbank erstellt haben. Sie möchten wahrscheinlich psql starten. wird Ihr Benutzername als Vorgabe verwendet. the PostgreSQL interactive terminal. zu bearbeiten und auszuführen. indem Sie ❏ das interaktive PostgreSQL-Terminalprogramm. sollte Letzteres das auch tun. Das psql-Programm begrüßt Sie mit der folgenden Mitteilung: Welcome to psql . Probieren Sie diese Befehle aus: meinedb=> SELECT version(). und wenn Ersteres funktioniert hat. dann umgehen Sie alle Kontrollen der Zugriffsrechte. dass Sie ein Datenbank-Superuser sind. Type: \copyright for distribution terms \h for help with SQL commands \? for help on internal slash commands \g or terminate with semicolon to execute query \q to quit meinedb=> Die letzte Zeile könnte auch meinedb=# sein.Kapitel 1 1. dass psql darauf wartet. können Sie darauf zugreifen. um die Beispiele in diesem Tutorial auszuprobieren. Um es für die Datenbank meinedb zu aktivieren. Für dieses Tutorial ist das nicht erheblich. psql zu starten. was wahrscheinlich der Fall ist. verwenden. compiled by GCC 2. ❏ eine bestehende grafische Anwendung wie PgAccess oder ein Office-Paket mit ODBC-Unterstützung verwenden.3devel on i586-pc-linux-gnu. ist der Prompt. um Datenbanken zu erstellen und zu verändern. Das würde bedeuten. gehen Sie zurück zum vorigen Abschnitt. geben Sie diesen Befehl ein: $ psql meinedb Wenn Sie den Datenbanknamen auslassen. Die Mitteilungen von psql und createdb sind ähnlich. SQL-Befehle interaktiv einzugeben. Diese Möglichkeiten werden in diesem Tutorial nicht besprochen. die von psql ausgegeben wurde. Wenn Sie ein Superuser sind. welches Ihnen erlaubt. version ---------------------------------------------------------------PostgreSQL 7. ❏ eine neue Anwendung schreiben unter Anwendung der verschiedenen verfügbaren Sprachanbindungen.96 (1 row) 34 . Dieses System wurde im vorigen Abschnitt besprochen. wenn Sie PostgreSQL selbst installiert haben. dass Sie SQL-Befehle in den Arbeitsbereich von psql eingeben. genannt psql. Die letzte Zeile.

indem Sie eingeben: meinedb=> \h Um psql zu verlassen. können Sie auch am Shell-Prompt des Betriebssystems man psql eingeben um die Anleitung zu sehen. geben Sie am psql-Prompt \? ein. wenn Sie es passend finden. aber Sie können Sie anwenden. In diesem Tutorial werden wir diese Fähigkeiten nicht ausdrücklich nutzen.Ein Einstieg meinedb=> SELECT current_date. geben Sie ein: meinedb=> \q und psql wird beendet und Sie kehren zu Ihrer Shell zurück. Einige dieser Befehle wurden in der Willkommensmeldung aufgelistet. ?column? ---------4 (1 row) Das psql-Programm hat eine Anzahl von internen Befehlen. 35 . date -----------2002-08-31 (1 row) meinedb=> SELECT 2 + 2. (Um weitere interne Kommandos zu sehen. Zum Beispiel können Sie Hilfe zur Syntax der verschiedenen SQL-Befehle in PostgreSQL erhalten. Sie fangen mit dem Backslash-Zeichen (»\«) an. Wenn PostgreSQL richtig installiert ist. die keine SQL-Befehle sind.) Die gesamten Fähigkeiten von psql sind in Teil VI beschrieben.

.

ist heutzutage so gewöhnlich. befinden sich in der Datei basics. 2. um einfache Operationen auszuführen. Daten in Tabellen zu speichern. Dieses Tutorial ist nur eine Einführung und in keiner Weise ein kompletter SQL-Lehrgang. geben Sie Folgendes ein: $ cd . welches Daten verwaltet. dass Sie eine Datenbank namens meinedb erzeugt haben. dass sie eigentlich offensichtlich erscheint. Das bedeutet. wie Sie SQL verwenden.2 Konzepte PostgreSQL ist ein relationales Datenbankverwaltungssystem (englisch relational database management system.. die in Relationen gespeichert sind.. Eine modernere Entwicklung ist die objektorientierte Datenbank.sql. meinedb=> \i basics. die in diesem Kapitel verwendet werden. welcher jedes Mal eine Pause verursacht. dass manche PostgreSQL-Features Erweiterungen gegenüber dem SQLStandard sind. und dass sie psql gestartet haben.sql Der Befehl \i liest Befehle von der angegebenen Datei. In den folgenden Beispielen nehmen wir an./src/tutorial $ psql -s meinedb . Um das Tutorial zu starten. Die Befehle. Die Option -s schaltet den Einzelschrittmodus ein... Datenbanken zu organisieren. 37 . Die Datei README in diesem Verzeichnis enthält weitere Anweisungen.. Die Bespiele in diesem Tutorial können Sie auch im PostgreSQL-Quelltextpaket im Verzeichnis src/ tutorial/ finden. wie im vorigen Kapitel beschrieben. dass es ein System ist. Relation ist im Prinzip ein mathematischer Begriff für eine Tabelle.2 2 Die SQL-Sprache 2. aber es gibt eine Anzahl anderer Möglichkeiten. RDBMS). Dateien und Verzeichnisse in Unix-ähnlichen Betriebssystemen bilden ein Beispiel einer hierarchischen Datenbank. Sie sollten sich auch darüber im Klaren sein.1 Einführung Dieses Kapitel gibt Ihnen einen Überblick. bevor ein Befehl an den Server geschickt wird. Die Idee. wie die Dateien zu verwenden sind.

1 2. bis zum Zeilenende. psql erkennt. Das bedeutet. temp_lo int.und Kleinschreibung zu erhalten (oben nicht der Fall).Kapitel 2 Jede Tabelle ist eine mit einem Namen versehene Sammlung von Zeilen. date ist natürlich für Datumsangaben. Das zweite Beispiel wird Städte und ihre geographische Position speichern: CREATE TABLE cities ( name varchar(80). Namen werden in doppelte Anführungszeichen gesetzt. Schließlich sollten wir erwähnen.t um Sonderfälle im SQL-Standard zu unterstützen. wird ignoriert. 0. dass sie den Befehl auch mit einer anderen Formatierung oder gar auf einer einzigen Zeile eingeben könnten. real. Jede Zeile einer Tabelle hat dieselbe Menge von benannten Spalten und jede Spalte hat einen bestimmten Datentyp. es sei denn.Höchsttemperatur -. Sie können das in psql mit den Zeilenumbrüchen eingeben. prcp real. Leerzeichen. dass die Befehle erst mit dem Semikolon abgeschlossen sind. dass SQL die Reihenfolge der Zeilen in einer Tabelle in keiner Weise garantiert. die von einem einzigen PostgreSQL-Server verwaltet werden. location point ). wenn Sie eine Tabelle nicht mehr benötigen oder Sie mit anderen Details neu erzeugen wollen. PostgreSQL kann auch mit einer beliebigen Zahl benutzerdefinierter Typen angepasst werden. der beliebige Zeichenketten bis 80 Zeichen Länge aufnehmen kann. sollten Sie sich merken. double precision. varchar(N). temp_hi int. char(N). smallint. timestamp und interval sowie weitere allgemein anwendbare und eine große Sammlung von geometrischen Typen. date date -. 38 . real ist ein Typ. Deswegen sind Typnamen keine syntaktischen Schlüsselwörter. time. Groß. englisch für Sammlung oder Traube). ergeben einen Datenbank-Cluster (cluster.Niederschlag (precipitation) ). Das mag bequem oder verwirrend sein – Ihre Wahl.und Kleinschreibung von Schlüsselwörtern und Namen ist in SQL unerheblich. date. Zwei Minuszeichen (“--”) zeigen den Start eines Kommentars an. außer wenn das erforderlich is. (Die Spalte vom Typ date heißt selbst auch date. um die Groß. (Sie können aber für die Ausgabe ausdrücklich sortiert werden.) PostgreSQL unterstützt die gewöhnlichen SQL-Datentypen int. int ist der normale Typ für ganze Zahlen. Tabs und Zeilenumbrüche können in SQL-Befehlen beliebig verwendet werden. Alles was danach folgt. indem Sie den Namen der Tabelle sowie die Namen und Datentypen aller Spalten angeben: CREATE TABLE weather ( city varchar(80). Sie sie dann mit dem folgenden Befehl entfernen können: DROP TABLE tabellenname.Tiefsttemperatur -. varchar(80) ist ein Datentyp.3 Eine neue Tabelle erzeugen Sie können eine neue Tabelle erzeugen.) Tabellen werden in Datenbanken zusammengefasst und eine Sammlung von Datenbanken. Der Typ point ist ein Beispiel eines besonderen Typs in PostgreSQL. der Fließkommazahlen mit einfacher Präzision aufnimmt. Während Spalten in jeder Zeile eine feste Ordnung haben. dass.

Sie könnten auch COPY verwenden. date) VALUES ('San Francisco'. von denen die Daten zu entnehmen sind) und eine wahlfreie Qualifizierung (der Teil. 0. Der Typ date ist sehr flexibel bezüglich der Werte.0.txt'. '1994-11-29'). die keine einfachen numerischen Werte sind. temp_lo) VALUES ('1994-11-29'. weil der Server die Datei direkt liest. temp_lo. aber weniger Flexibilität als INSERT erlaubt. mit denen wir in den folgenden Abschnitten arbeiten können. 43. 0. prcp. Viele Entwickler finden. die er akzeptiert. 54. geben Sie ein: SELECT * FROM weather. 53. damit Sie einige Daten haben. anstatt sich auf die Ordnung zu verlassen. '1994-11-27'). temp_hi. der die auszugebenden Spalten auflistet). Dazu wird der SQL-Befehl SELECT verwendet.25. Für numerische Werte muss ein Punkt anstelle des Kommas verwendet werden. Bitte geben Sie alle oben gezeigten Befehle ein. müssen von einfachen Anführungszeichen (') eingeschlossen werden. dass es stilistisch besser ist. dass man die Spalten ausdrücklich aufzählt: INSERT INTO weather (city. eine Tabellenliste (der Teil. Mehr über COPY können Sie auf Seite 646 lesen.4 Eine Tabelle mit Zeilen füllen INSERT INTO weather VALUES ('San Francisco'. '(-194. nicht auf der Clientmaschine. Der Befehl INSERT wird verwendet. Der Typ point erfordert als Eingabewert ein Koordinatenpaar.Die SQL-Sprache 2. 57. wird eine Anfrage ausgeführt. Konstanten. Das ist normalerweise schneller. wenn zum Beispiel der Niederschlag unbekannt ist: INSERT INTO weather (date. Ein Beispiel wäre: COPY weather FROM '/home/user/weather. Das bisher verwendete Format des INSERT-Befehls erfordert. der die Tabelle auflistet. 2. um eine Tabelle mit Zeilen zu füllen: Alle Datentypen haben einigermaßen klare Eingabeformate. temp_hi. aber in diesem Tutorial werden wir das hier gezeigte unzweideutige Format verwenden. 46. Ein alternatives Format ermöglicht. 'Hayward'.5 Eine Tabelle abfragen Um Daten aus einer Tabelle zu lesen. Der Befehl teilt sich auf in eine Select-Liste (der Teil. Der Dateiname der Quelldatei muss auf der Maschine des Datenbankservers zur Verfügung stehen. 39 . Um zum Beispiel alle Zeilen der Tabelle weather abzurufen. 37). Sie können die Spalten auch in einer anderen Reihenfolge aufzählen oder sogar einige Spalten weglassen. dass man sich die Reihenfolge der Spalten gemerkt hat. wie hier: INSERT INTO cities VALUES ('San Francisco'.0.0)'). wie im Beispiel. weil der COPY-Befehl für diese Anwendung optimiert ist. der etwaige Einschränkungen angibt). 50. city. die Spalten immer aufzuzählen. um große Mengen Daten von einfachen Textdateien zu laden.

0. (Sie ist optional. NOT) können in der Qualifikation einer Anfrage verwendet werden.Kapitel 2 (* bedeutet hier “alle Spalten”).25 | 1994-11-27 San Francisco | 43 | 57 | 0 | 1994-11-29 Hayward | 37 | 54 | | 1994-11-29 (3 rows) Sie können beliebige Ausdrücke in der Select-Liste angeben. date FROM weather. city --------------Hayward San Francisco (2 rows) DISTINCT und ORDER BY können natürlich auch getrennt verwendet werden. Zum Beispiel können Sie Folgendes machen: SELECT city. Das Ergebnis sollte sein: city | temp_avg | date ---------------+----------+-----------San Francisco | 48 | 1994-11-27 San Francisco | 50 | 1994-11-29 Hayward | 45 | 1994-11-29 (3 rows) Die AS-Klausel wird verwendet. Das Ergebnis sollte sein: city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+-----------San Francisco | 46 | 50 | 0. Zum Beispiel ergibt die folgende Anfrage das Wetter in San Francisco an regnerischen Tagen: SELECT * FROM weather WHERE city = 'San Francisco' AND prcp > 0. OR. um der Ergebnisspalte einen Namen zu geben. 40 . dass die Ergebnisse einer Anfrage sortiert und doppelte Zeilen entfernt werden: SELECT DISTINCT city FROM weather ORDER BY city.) Beliebige Boole'sche Operationen (AND. Ergebnis: city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+-----------San Francisco | 46 | 50 | 0.25 | 1994-11-27 (1 row) Schließlich können Sie auch verlangen. (temp_hi+temp_lo)/2 AS temp_avg.

name = weather. Das ist korrekt.location FROM weather. sodass Sie die Spalten wahrscheinlich ausdrücklich aufzählen wollen. Wir werden gleich sehen. ❏ Es gibt zwei Spalten mit dem Namen der Stadt. die wir bisher gesehen haben. die auf mehrere Zeilen derselben oder verschiedener Tabellen zugreift heißt. Anmerkung Das ist nur das konzeptionelle Modell.city. location FROM weather. Verbund-Anfrage (englisch join). cities WHERE cities. Dies können wir mit der folgenden Anfrage erreichen: SELECT * FROM weather.city. temp_lo. Sie wollen alle Wetterdatensätze zusammen mit den Koordinaten der zugehörigen Stadt sehen.temp_hi. cities. SELECT city. wie das verbessert werden kann. zu welcher Tabelle sie gehörten.25 | 1994-11-27 | San Francisco | (-194.6 Verbunde zwischen Tabellen Bisher haben unsere Anfragen immer nur auf eine Tabelle zugegriffen. anstatt * zu verwenden. Der Grund ist. Die Verbundanfragen. city | temp_lo | temp_hi | prcp | date | name | location ---------------+---------+---------+------+------------+---------------+---------San Francisco | 46 | 50 | 0. Eine Anfrage.temp_lo. weather. weil die Spaltenlisten von weather und cities aneinandergehängt werden. für die es keine Paarung gibt. weather. cities WHERE city = name.53) San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194. aber das ist für den Benutzer nicht sichtbar. hat der Parser automatisch herausgefunden. date. in Verbundanfragen die Spaltennamen um die Tabellennamen zu ergänzen: SELECT weather.date. In Wirklichkeit können viele Verbundoperationen effektiver ausgeführt werden. können auch in dieser Alternativform geschrieben werden: 41 .Die SQL-Sprache 2. Da alle Spalten unterschiedliche Namen hatten. Sagen wir zum Beispiel. Dazu müssen wir die citySpalte in jeder Zeile der Tabelle weather mit der name-Spalte in allen Zeilen der Tabelle cities vergleichen und diejenigen Paare auswählen. Anfragen können auch auf mehrere Tabellen auf einmal zugreifen oder können auf eine Tabelle so zugreifen. prcp. aber es ist stilistisch besser. weather. temp_hi. dass es für Hayward keinen passenden Eintrag in der Tabelle cities gibt und der Verbund die Zeilen in weather ignoriert. bei denen die Werte gleich sind. dass mehrere Zeilen der Tabelle auf einmal verarbeitet werden.53) (2 rows) Sie werden zwei Dinge in diesem Ergebnis bemerken: ❏ Es gibt keine Ergebniszeile für die Stadt Hayward. weather.prcp. cities WHERE city = name. In der Praxis ist das unerwünscht.

die links vom Verbundoperator steht. Zum Beispiel nehmen wir an. aber wir zeigen sie hier.temp_lo < W2. um Ihnen zu helfen.city = cities.53) San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194. dann werden leere Werte (NULL) in die Spalten der rechten Tabelle eingesetzt. W1.temp_lo AS low. Wenn eine Zeile der linken Tabelle ausgegeben wird. die zu einer Zeile der linken Tabelle passen.city = cities. während die Tabelle auf der rechten Seite nur die Zeilen im Ergebnis haben wird. Übung Es gibt auch rechte äußere Verbunde (right outer join) und volle äußere Verbunde (full outer join). heißen innerer Verbund (englisch inner join. die im Temperaturbereich anderer Sätze sind. W1. sollten irgendwelche “leeren Werte” als Ersatz genommen werden. Wir können das mit der folgenden Anfrage erreichen: SELECT W1.25 | 1994-11-27 | San Francisco | (-194.53) (3 rows) Diese Anfrage heißt linker äußerer Verbund (left outer join).city.und temp_hi-Spalten aller anderen weather-Zeilen vergleichen.name). city | temp_lo | temp_hi | prcp | date | name | location ---------------+---------+---------+------+------------+---------------+--------Hayward | 37 | 54 | | 1994-11-29 | | San Francisco | 46 | 50 | 0. (Die Verbunde. für die es keine Entsprechung in der rechten Tabelle gibt.name). Das ist ein Selbstverbund.temp_hi. die folgenden Themen zu verstehen. Was wir wollen. Wir können auch einen Verbund einer Tabelle mit sich selbst ausführen. W2.temp_lo AS low. Also müssen wir die Spalten temp_lo und temp_hi von jeder Zeile in der Tabelle weather mit den temp_lo. Diese Art Anfrage heißt äußerer Verbund (englisch outer join). weil die Tabelle. jede ihrer Zeilen mindestens einmal in der Ergebnismenge haben wird. Wenn keine passende Zeile gefunden wurde. weather W2 WHERE W1. was diese machen. ist eine Anfrage. city | low | high | city | low | high ---------------+-----+------+---------------+-----+-----San Francisco | 43 | 57 | San Francisco | 46 | 50 Hayward | 37 | 54 | San Francisco | 46 | 50 (2 rows) 42 .temp_lo AND W1. Versuchen Sie herauszufinden.temp_hi AS high FROM weather W1.) Der Befehl sieht so aus: SELECT * FROM weather LEFT OUTER JOIN cities ON (weather. wie wir die Datensätze der Stadt Hayward wieder sehen können.Kapitel 2 SELECT * FROM weather INNER JOIN cities ON (weather. W2.temp_hi > W2.temp_hi AS high. Diese Form ist nicht so gebräuchlich wie die weiter oben verwendeten.city. Jetzt werden wir herausfinden. die wir bisher gesehen haben. dass wir alle Wetterdatensätze finden wollen. W2. die die Tabelle weather durchgeht und für jede Zeile die passende cities-Zeile findet.

city = c. cities c WHERE w. um das beabsichtigte Ergebnis zu erzielen. unterstützt PostgreSQL Aggregatfunktionen. in welcher Stadt (oder in welchen Städten) dieser Wert auftrat. welche Zeilen in die Aggregatphase einfließen und damit ausgewertet werden muss. FALSCH Aber das funktioniert nicht.name. weil die Unteranfrage eine unabhängige Berechnung darstellt. kann diese Anfrage aber umgeschrieben werden.(min) oder den Maximalwert (max) jeweils aus mehreren Zeilen berechnen.Die SQL-Sprache Wir haben die Tabelle weather hier als W1 und W2 bezeichnet. den Durchschnitt (avg). Aggregatfunktionen sind auch sehr nützlich in Kombination mit den GROUP BY. city --------------San Francisco (1 row) Das ist in Ordnung. hier mit einer Unteranfrage: SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather).) Wie es so oft der Fall ist. die die Anzahl der Zeilen (count). die Summe der Eingabewerte (sum). Eine Aggregatfunktion berechnet ein einzelnes Ergebnis aus mehreren Eingabezeilen. um Tipparbeit zu sparen. weil die WHERE-Klausel bestimmt. um die linke und rechte Seite des Verbunds unterscheiden zu können. Wir können zum Beispiel die maximale Tiefsttemperatur in jeder Stadt ermitteln mit: SELECT city.7 Aggregatfunktionen Wie die meisten anderen relationalen Datenbanken. die ihre Aggregatfunktionen getrennt von der äußeren Anfrage auswertet. Diesen Abkürzungsstil werden Sie häufig antreffen.und HAVING-Klauseln. würden wir vielleicht dies versuchen: SELECT city FROM weather WHERE temp_lo = max(temp_lo). 2. bevor die Aggregatfunktionen berechnet werden. Wir können zum Beispiel die höchste Tiefsttemperatur in unseren Daten mit folgender Anfrage ermitteln: SELECT max(temp_lo) FROM weather. city | max 43 . (Die Einschränkung besteht. die Minimal. weil die Aggregatfunktion max nicht in der WHERE-Klausel verwendet werden kann. Diese Art von Alias können Sie auch in anderen Anfragen verwenden. max ----46 (1 row) Wenn wir wissen wollen. Zum Beispiel gibt es Aggregatfunktionen. max(temp_lo) FROM weather GROUP BY city. Zum Beispiel: SELECT * FROM weather w.

Es ist wichtig. Die WHERE-Klausel darf also keine Aggregatfunktionen enthalten. während HAVING gruppierte Zeilen auswählt. welche Zeilen in die Aggregatberechnung einfließen). Die LIKE-Operation führt einen Mustervergleich aus und wird in Abschnitt 9.8 Daten aktualisieren Bestehende Zeilen können mit dem Befehl UPDATE aktualisiert werden. Wir können diese gruppierten Zeilen mit HAVING filtern: SELECT city.) Beachten Sie. city | max ---------+----Hayward | 37 (1 row) Das gibt uns das gleiche Ergebnis. die keine Aggregatfunktionen enthalten. aber nur mit Städten. dass wir die Einschränkung des Städtenamens in der WHERE-Klausel anwenden können. max(temp_lo) FROM weather GROUP BY city HAVING max(temp_lo) < 40.Kapitel 2 ---------------+----Hayward | 37 San Francisco | 46 (2 rows) Dies gibt uns eine Ergebniszeile pro Stadt. könnten wir Folgendes machen: SELECT city. um zu bestimmen. Die HAVING-Klausel hingegen enthält immer Aggregatfunktionen. eine Aggregatfunktion zu verwenden. 2. weil es keinen Sinn hat. Sie entdecken. nachdem Gruppen und Aggregate berechnet worden sind. Das ist effektiver. dass alle Temperaturmessungen seit sdem 28. weil wir dadurch die Gruppierung und Aggregatberechnungen der Zeilen. (Genau genommen können Sie HAVING-Klauseln schreiben. vermeiden. Wenn wir schließlich nur an Städten interessiert sind. deren Namen mit “S” beginnt.6 erklärt. die durch die WHERE-Klausel herausfiltert werden. weil sie keine Aggregatfunktion braucht. max(temp_lo) FROM weather WHERE city LIKE 'S%'(1) GROUP BY city HAVING max(temp_lo) < 40. Der grundlegende Unterschied zwischen WHERE und HAVING ist folgender: WHERE wählt Zeilen aus. Dann können Sie Ihre Daten folgendermaßen aktualisieren: 44 . Nehmen wir an. welchen Zeilen Eingabe für die Aggregatfunktionen sein werden. als die Bedingung zur HAVING-Klausel hinzuzufügen. die Wechselwirkung zwischen Aggregatfunktionen und den SQL-Klauseln WHERE und HAVING zu verstehen. aber das ist Verschwendung: Dieselben Bedingungen könnten in der WHERE-Klausel-Phase effizienter verarbeitet werden. November zwei Grad zu hoch waren. Jedes Aggregatergebnis wird aus den Tabellenzeilen für diese Stadt berechnet. die alle temp_lo-Werte unter 40 haben. bevor Gruppen und Aggregate berechnet werden (es kontrolliert also.

bevor es dies macht! 45 . dass Sie das Wetter in Hayward nicht mehr interessiert.Die SQL-Sprache UPDATE weather SET temp_hi = temp_hi .25 | 1994-11-27 San Francisco | 41 | 55 | 0 | 1994-11-29 Hayward | 35 | 52 | | 1994-11-29 (3 rows) 2. Das System verlangt keine Bestätigung. Dann können Sie diese Zeilen wie folgt aus der Tabelle löschen. Alle Datensätze in der Tabelle weather. werden entfernt. temp_lo = temp_lo . city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+-----------San Francisco | 46 | 50 | 0.25 | 1994-11-27 San Francisco | 41 | 55 | 0 | 1994-11-29 (2 rows) Man sollte vorsichtig sein mit Befehlen der Form DELETE FROM tabellenname. löscht DELETE alle Datensätze der angegebenen Tabelle und lässt die Tabelle damit leer.2. Löschoperationen werden mit dem Befehl DELETE durchgeführt: DELETE FROM weather WHERE city = 'Hayward'.2 Schauen Sie sich den neuen Stand der Daten an: SELECT * FROM weather.9 Daten löschen Nehmen wir an. Wenn keine Bedingungen angegeben sind. die zu Hayward gehören. city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+-----------San Francisco | 46 | 50 | 0. WHERE date > '1994-11-28'. SELECT * FROM weather.

.

Am Ende werden wir einige PostgreSQL-Erweiterungen anschauen. Einige Beispiele in diesem Kapitel können Sie auch in der Datei advanced. Diese Datei enthält auch einige Beispieldaten zum Laden. temp_lo. wenn Sie dieses Kapitel gelesen haben.1 Einführung Im vorigen Kapitel ging es um die Grundlagen von SQL zum Speichern und Abrufen von Daten in PostgreSQL Jetzt werden wir einige fortgeschrittene Funktionen von PostgreSQL besprechen. um sie zu ändern oder zu verbessern.3 3 Fortgeschrittene Funktionen 3. date. Es ist also von Vorteil. die dazu dienen. wodurch Sie der Anfrage einen Namen geben.2 Sichten Schauen Sie sich noch einmal die Anfragen in Abschnitt 2. temp_hi. dass die kombinierte Liste aus Wetterdatensätzen und Städtekoordinaten für Ihre Anwendung besonders interessant ist.6 an. prcp. Nehmen wir an.1 nach. 47 . die Verwaltung der Daten zu vereinfachen oder den Verlust oder die Verfälschung von Daten zu verhindern. hinter konsistenten Schnittstellen verbergen. wie Sie diese Datei verwenden können. aber Sie die Anfrage nicht jedes Mal eingeben wollen. (Sehen Sie unter Abschnitt 2. welche sich verändern könnten. cities WHERE city = name. den Sie wie eine normale Tabelle verwenden können. Dieses Kapitel wird sich gelegentlich auf die Beispiele in Kapitel 2 beziehen.) 3. die hier nicht wiederholt werden. während Ihre Anwendung wächst. Sie können eine Sicht (englisch View) für die Anfrage erzeugen. SELECT * FROM myview. location FROM weather. Mit Sichten können die Strukturdetails Ihrer Tabellen.sql im Tutorial-Verzeichnis finden. CREATE VIEW myview AS SELECT city. Die großzügige Verwendung von Sichten ist ein wichtiger Aspekt eines guten SQL-Datenbankentwurfs.

dass niemand eine Zeile in die Tabelle weather einfügen kann. dass die Transaktion beendet wird. 0. ERROR: <unnamed> referential integrity violation . aber PostgreSQL kann das für Sie übernehmen. int. einen ungültigen Datensatz einzufügen: INSERT INTO weather VALUES ('Berkeley'. wo eine richtige Tabelle verwendet werden kann. gleichzeitig ausgeführte Transaktionen nicht sichtbar. date Nun versuchen Sie. dann haben die Schritte der Transaktion überhaupt keine Auswirkung auf die Datenbank. um zu sehen. und falls irgendein Fehler passiert. und danach den neuen weather-Datensatz einfügt oder ablehnt. Die neue Deklaration der Tabellen sieht so aus: CREATE TABLE cities ( city varchar(80) primary key. In einfachen Datenbanksystemen würde man das. Dies bezeichnet man als das Erhalten der referenziellen Integrität der Daten. 48 . Auch das Erzeugen von Sichten basierend auf anderen Sichten ist nicht unüblich. Die korrekte Verwendung von Fremdschlüsseln wird die Qualität Ihrer Datenbankanwendungen ganz bestimmt verbessern. weather ( varchar(80) references cities. real. Die Stadien zwischen den Schritten sind für andere.3 Fremdschlüssel Erinnern Sie sich an die Tabellen weather und cities aus Kapitel 2.Kapitel 3 Sichten können fast überall verwendet werden. wenn überhaupt.key referenced from weather not found in cities Das Verhalten von Fremdschlüsseln kann genau auf Ihre Anwendung abgestimmt werden. 45. dass sie mehrere Schritte zu einer einzigen Alles-oder-nichts-Operation zusammenfasst. indem man in die Tabelle cities schaut. ob ein passender Datensatz existiert. der verhindert. 53. CREATE TABLE city temp_lo temp_hi prcp date ). 3. location point ).4 Transaktionen Transaktionen sind ein grundlegendes Konzept aller Datenbanksysteme.0. Diese Lösung hat eine Reihe von Problemen und ist ziemlich unbequem. Betrachten Sie folgendes Problem: Sie wollen sich versichern. die keinen passenden Eintrag in der Tabelle cities hat. Wir werden es in diesem Tutorial bei diesem einfachen Beispiel belassen und verweisen Sie auf Kapitel 5 für weitere Informationen. implementieren. '1994-11-28'). und daher sollten Sie sich unbedingt mit ihnen vertraut machen. Die wichtigste Eigenschaft einer Transaktion ist. 3. int.

die bis dahin ausgeführten Schritte nicht ausgeführt werden. dass wir die Transaktion nicht abschließen wollen (vielleicht haben wir festgestellt. während sie ablaufen.00 WHERE name = 'Bernd'. sie dann wirklich aufgezeichnet wurde und nicht durch einen Systemausfall kurze Zeit später verloren gehen kann. Es wäre sicherlich nicht akzeptabel. Unsere Banktransaktion würde also etwa so aussehen: BEGIN. die Transaktionen unterstützt.00 WHERE name = (SELECT zweig_name FROM konten WHERE name = 'Bernd'). dann haben wir diese Garantie. garantiert dass alle Aktualisierungen auf eine dauerhaftes Speichermedium (z. wenn etwas mitten in der Operation fehlschlägt. Eine Datenbank. Wir brauchen eine Garantie. Die Einzelheiten dieser Befehle sind hier nicht wichtig. dann können wir den Befehl ROLLBACK statt COMMIT ausführen und alle unsere Aktualisierungen werden verworfen. während er gerade die Bank verlässt.100. sowie die Summen der Kontostände in den Zweigstellen. Wir wollen sicher sein. die die Kontostände verschiedener Kundenkonten enthält. sondern auch in Bezug auf ihre Sichtbarkeit. Stark vereinfacht könnten die SQL-Befehle dafür etwa so aussehen: UPDATE konten SET kontostand = kontostand . wenn sie die Belastung von Annes Konto mitzählt. wenn nach einem Systemausfall Bernd 100 Euro hätte. indem man die SQL-Befehle der Transaktion mit den Befehlen BEGIN und COMMIT umschließt. UPDATE zweigstellen SET kontostand = kontostand . -. dass das Konto von Anne jetzt im Minus ist).00 WHERE name = (SELECT zweig_name FROM konten WHERE name = 'Anne'). die von Annes Konto nicht abzogen wurden.00 WHERE name = 'Anne'.B. COMMIT. dass. Die Aktualisierungen. wenn die Transaktion einmal abgeschlossen und vom Datenbanksystem bestätigt wurde. um diese relativ einfache Operation auszuführen. Eine weitere wichtige Eigenschaft einer transaktionsfähigen Datenbank ist eng mit der Idee der atomaren Akualisierungen verwandt: Wenn mehrere Transaktionen gleichzeitig ablaufen. und zu diesem Zeitpunkt werden alle Aktualisierungen gleichzeitig sichtbar. aber nicht die Gutschrift auf Bernds Konto. usw. die von einer noch nicht abgeschlossenen Transaktion gemacht wurden.usw. Festplatte) geschrieben worden sind. Außerdem möchten wir die Garantie haben. UPDATE konten SET kontostand = kontostand + 100. oder umgekehrt. dass die Belastung seines Kontos nicht in einem Systemausfall verloren geht. passiert entweder die ganze Transaktion oder gar nichts.Fortgeschrittene Funktionen Betrachten Sie zum Beispiel die Datenbank einer Bank. UPDATE konten SET kontostand = kontostand . Und Anne wäre sicherlich nicht lange ein zufriedener Kunde. Transaktionen sind atomar: Vom Standpunkt anderer Transaktionen aus gesehen. wir möchten eine Überweisung von 100 Euro von Annes auf Bernds Konto tätigen.100. dann wäre es nicht akzeptabel. wenn das Geld von ihrem Konto abgezogen würde. dass mehrere getrennte Aktualisierungen benötigt werden. das Wichtige ist.100. Nehmen wir an. dass entweder alle diese Aktualisierungen oder keine von ihnen stattfinden. dass. die unvollständigen Änderungen der anderen zu sehen. Wenn wir mitten in der Transaktion entscheiden. sind für andere Transaktionen unsichtbar. ohne dass Bernd es erhalten hätte. wollen wir sicherstellen. UPDATE zweigstellen SET kontostand = kontostand + 100. Wenn zum Beispiel Bernd Bargeld von seinem Konto abhebt. sollte es ihnen nicht möglich sein. bis erstere abgeschlossen wird. 49 . die Kontostände aller Zweigstellen zusammenzuzählen. Transaktionen müssen also nicht nur in Bezug auf ihre dauerhafte Auswirkung auf die Datenbank alles-oder-nichts sein.00 WHERE name = 'Anne'. In PostgreSQL verwendet man eine Transaktion. bevor die Transaktion als abgeschlossen bestätigt wird. Wenn zum Beispiel eine Transaktion damit beschäftigt ist. Wenn wir die Aktualisierungen in eine Transaktion zusammenfassen.

falls der Befehl erfolgreich war. population. Anmerkung Manche Clientbibliotheken führen BEGIN und COMMIT automatisch aus und erzeugen daher möglicherweise den Effekt eines Transaktionsblocks. also möchten Sie vielleicht eine Möglichkeit haben. wenn Sie mehrere Zeilen aktualisieren wollen. Das funktioniert auch gut für Anfragen. cities ( text. Eine Gruppe von Befehlen zwischen einem ausdrücklichen BEGIN und COMMIT wird manchmal Transaktionsblock genannt. die Sie verwenden möchten. aber es wird sehr umständlich. altitude FROM capitals UNION SELECT name. 3. real. dann wird vor jedem Befehl ein automatisches BEGIN und. real. capitals ( text. wenn Sie alle Städte auflisten. int. Natürlich sind Hauptstädte auch Städte.(in Fuß) char(2) non_capitals ( text.Kapitel 3 PostgreSQL führt in Wirklichkeit jeden Befehl in einer Transaktion aus.5 Vererbung Vererbung ist ein Konzept der objektorientierten Datenbanken. population. Wenn Sie keinen BEGIN-Befehl ausführen. Erzeugen wir zwei Tabellen: Eine Tabelle cities für Städte und eine Tabelle capitals für Hauptstädte. Prüfen Sie die Anleitung der Schnittstelle. CREATE TABLE name population altitude ). um nur ein Problem zu nennen. alle Hauptstädte automatisch anzuzeigen. altitude FROM non_capitals.(in Fuß) CREATE VIEW cities AS SELECT name. int -. danach ein automatisches COMMIT ausgeführt. Wenn Sie sehr raffiniert sind. -.(in Fuß) 50 . int -. ohne dass Sie dazu aufgefordert werden müssen. würden Sie vielleicht ein System wie dieses erfinden: CREATE TABLE name population altitude state ). Es eröffnet interessante neue Möglichkeiten beim Entwerfen einer Datenbank. Hier ist eine bessere Lösung: CREATE TABLE name population altitude ). real.

oder natürlich von gar keiner. dass die Anfrage nur die cities-Tabelle lesen soll und nicht die Tabelle unterhalb von cities in der Vererbungshierarchie. Diese werden in allen Einzelheiten im Rest dieses Buchs besprochen. Wenn Sie denken. Die Hauptstädte der Bundesstaaten haben eine zusätzliche Spalte. altitude FROM ONLY cities WHERE altitude > 500. zu welchem Bundesstaat die Hauptstadt gehört. Das Ergebnis: name | altitude -----------+---------Las Vegas | 2174 Mariposa | 1953 Madison | 845 (3 rows) Die folgende Anfrage andererseits findet alle Städte. besuchen Sie bitte die PostgreSQL Website. die nicht Hauptstädte und 500 Fuß oder höher gelegen sind: SELECT name. UPDATE und DELETE – unterstützen diese ONLY-Option. altitude FROM cities WHERE altitude > 500. Viele der bisher besprochenen Befehle – SELECT. dass Sie noch mehr Material zum Lernen benötigen. Die folgende Anfrage findet zum Beispiel die Namen aller Städte. population und altitude) der Elterntabelle cities. die anzeigt. In diesem System erbt (englisch to inherit) eine Zeile der Tabelle capitals alle Spalten (name. einschließlich der Hauptstädte.6 Schlussfolgerung Die Einführung war für neue Benutzer bestimmt und PostgreSQL hat viele Features. state. 51 . wo Sie Links zu weiteren Quellen finden. Der Typ der Spalte name ist text. 3.Fortgeschrittene Funktionen CREATE TABLE capitals ( state char(2) ) INHERITS (cities). In PostgreSQLkann eine Tabelle von ein oder mehreren Tabellen erben. ein eingebauter PostgreSQL-Typ für Zeichenketten mit beliebiger Länge. die hier nicht besprochen wurden. die höher als 500 Fuß gelegen sind: SELECT name. name | altitude -----------+---------Las Vegas | 2174 Mariposa | 1953 (2 rows) Das ONLY vor cities zeigt an.

.

Leser. wie Datenstrukturen erzeugt werden. dann behandeln wir.3 Teil II Die SQL-Sprache Dieser Teil beschreibt. Leser dieses Teils sollten wissen. sodass fortgeschrittene Anwender die Kapitel einzeln auswählen und lesen können. sollten zuerst Teil I lesen. die damit noch nicht vertraut sind. 53 . sollten in Teil VI nachschauen. Der Mittelteil listet die Datentypen und Funktionen. Leser. die Datenbank gefüllt wird und wie Anfragen geschrieben werden. SQL-Befehlew werden normalerweise mit dem interaktiven PostgreSQL-Terminalprogramm psql eingegeben. die eine vollständige Beschreibung eines bestimmten Befehls suchen. aber andere Programme mit ähnlicher Funktionalität können ebenso verwendet werden. Zuerst erklären wir die allgemeine Syntax von SQL. Die Informationen in diesem Teil sind so angeordnet. Andererseits sind die Kapitel unabhängig voneinander. wie die Sprache SQL in PostgreSQL verwendet wird. wie man mit einer PostgreSQL-Datenbank verbindet und SQL-Befehle ausführt. dass ein neuer Anwender sie von vorne nach hinten durcharbeiten kann und dabei ein vollständiges Verständnis der Themen erhält. die wichtig sind. In diesem Teil sind die Informationen erzählerisch in Themenbereichen aufbereitet. Der Rest des Teils behandelt verschiedene Aspekte. um eine Datenbank auf optimale Leistung abzustimmen. die in SQL-Datenbefehlen verwendet werden können. ohne zu oft nach vorne blättern zu müssen.

VAKAT VAKAT .

ein Name. Wir raten auch Benutzern. wie man SQL-Befehle verwendet. Welche Tokens Befehle anzeigen und welche Tokens Operanden oder Parameter sind. die sich mit SQL schon auskennen. Folgender Text ist zum Beispiel (syntaktisch) gültiger SQL-Text: SELECT * FROM MEINE_TABELLE.4 4 SQL-Syntax Dieses Kapitel beschreibt die Syntax der Sprache SQL. denn mehrere Regeln und Konzepte sind in verschiedenen SQL-Datenbanken unterschiedlich umgesetzt oder sind nur in PostgreSQL vorhanden. Zusätzlich können im SQL-Text Kommentare auftreten. Welche Tokens gültig sind. UPDATE MEINE_TABELLE SET A = 5. sodass man in dem Beispiel oben gewöhnlich von einem »SELECT«-. eine Konstante oder ein Sonderzeichen sein. Es bildet die Grundlage.«) abgeschlossen. Ein Token kann ein Schlüsselwort. hängt von der Syntax des jeweiligen Befehls ab. wenn ein Sonderzeichen neben einem anderen Tokentyp steht). eine Zeile kann mehrere Befehle enthalten und ein Befehl kann auch sinnvoll über mehrere Zeilen verteilt werden). einem pro Zeile (obwohl das nicht notwendig ist. ist in der SQL-Syntax nicht klar geregelt. ein Name in Anführungszeichen. um Daten zu definieren oder zu verändern. Tokens sind normalerweise durch Leerzeichen. Das Ende des Eingabestroms zeigt auch das Ende des Befehls an. INSERT INTO MEINE_TABELLE VALUES (3. 'Hallo daheim!'). Das ist eine Reihe von drei Befehlen. 55 . Ein Befehl besteht aus einer Reihe von Tokens und wird mit einem Semikolon (». welche beschreiben. Tabs oder Zeilenenden getrennt. die zum Verstehen der folgenden Kapitel notwendig ist. Die ersten paar Tokens stehen in der Regel für den Namen des Befehls. wenn dadurch keine Zweideutigkeit entsteht (was in der Regel nur der Fall ist.1 Lexikalische Struktur Eine SQL-Eingabe besteht aus einer Reihe von Befehlen.und einem »INSERT«Befehl spricht. einem »UPDATE«. dieses Kapitel sorgfältig zu lesen. Die genauen Syntaxregeln für jeden Befehl sind in Teil VI beschrieben. 4. aber das muss nicht sein. Sie sind keine Tokens und werden gewissermaßen durch Leerzeichen ersetzt. Aber der UPDATE-Befehl zum Beispiel erfordert immer auch ein SET-Token in einer bestimmten Position und diese bestimmte Variante von INSERT erfordert zur Vollständigkeit immer auch ein VALUES.

Die Umwandlung von Namen ohne Anführungszeichen in Kleinbuchstaben in PostgreSQL ist nicht mit dem SQLStandard kompatibel. dann spielt auch die Groß. wenn es dort verwendet wird. geschrieben werden.) Die Groß. aber "Foo" und "FOO" bezeichnen Namen. indem man eine beliebige Zeichenfolge in doppelte Anführungszeichen (") einschließt. Eine oft verwendete Konvention ist. Ein Name in Anführungszeichen ist immer ein Name und niemals ein Schlüsselwort. abhängig davon. genauso als uPDaTE mEine_TabeLLE SeT a = 5. Namen in Anführungszeichen können jedes Zeichen enthalten außer dem Anführungszeichen selbst. die sich von den ersten drei und voneinander unterscheiden.und Kleinschreibung eine Rolle. dass sie in Großbuchstaben umgewandelt werden sollten. das Ziffern enthält oder mit einem Unterstrich beginnt oder endet. längere Namen können verwendet werden. wenn man die Sprache kennt. das heißt Wörter. Das System verwendet nur maximal NAMEDATALEN-1 Zeichen eines Namens. also zum Beispiel UPDATE meine_tabelle SET a = 5. Das obige Beispiel kann mit Namen in Anführungszeichen folgendermaßen geschrieben werden: UPDATE "meine_tabelle" SET "a" = 5. wohingegen Namen ohne Anführungszeichen in Kleinbuchstaben umgewandelt werden. foo und "foo" derselbe Name.oder Kleinschreibung von Namen und Schlüsselwörtern ist unerheblich. Laut dem Standard sollte folglich foo gleich mit "FOO" sein und nicht mit "foo". die ansonsten nicht möglich wären. UPDATE oder VALUES im obigen Beispiel sind Beispiele für Schlüsselwörter. welcher aussagt. wohingegen ein select ohne Anführungszeichen als Schlüsselwort interpretiert würde und daher einen Parsefehler verursachen würde. also ist die Maximallänge eines Namens 63. "select" könnte also verwendet werden. Er wird geschrieben. So sind zum Beispiel FOO. 1 1. Eine komplette Liste der Schlüsselwörter ist in Anhang B zu finden.oder Spaltennamen erwartet. Also kann UPDATE MEINE_TABELLE SET A = 5.Kapitel 4 4. Die nachfolgenden Zeichen in einem Namen oder einem Schlüsselwort können Buchstaben. aber auch Umlaute und nichtlateinische Buchstaben) oder einem Unterstrich (_) beginnen. Dadurch können Sie Tabellen. wo PostgreSQL einen Tabellen. aber sie werden abgeschnitten. zum Beispiel solche mit Leerzeichen oder Punkten. dass sie für jeden Namen entweder immer oder nie Anführungszeichen verwenden. Ziffern (0-9) oder Unterstriche sein. Die Vorgabe für NAMEDATALEN ist 64. dass man Schlüsselwörter groß und Namen klein schreibt. das heißt. obwohl der SQL-Standard kein Schlüsselwort definieren wird. Es gibt noch eine zweite Art von Namen: den Namen in Anführungszeichen. die eine festgelegte Bedeutung in der SQL-Sprache haben. Um ein Anführungszeichen in einen Namen zu schreiben. Wenn man einen Namen in Anführungszeichen setzt.h verändert werden.oder Spaltennamen verwenden. Schlüsselwörter und Namen haben die gleiche lexikalische Struktur. dass man nur wissen kann. Spalten oder anderen Datenbankobjekten.1 Namen und Schlüsselwörter Tokens wie SELECT. Die Tokens MEINE_TABELLE und A sind Beispiele von Namen oder Bezeichnern. schreiben Sie es doppelt. (Wenn PostgreSQL gebaut wird. welches Token ein Name und welches ein Schlüsselwort ist. Die Längenbeschränkung gilt aber weiterhin.1. in welchem Befehl sie verwendet werden. um auf eine Spalte oder Tabelle namens select zu verweisen. SQL-Namen und -Schlüsselwörter müssen mit einem Buchstaben (a-z. 56 . Sie bezeichnen die Namen von Tabellen. Wenn Sie portierbare Anwendungen schreiben wollen dann empfehlen wir. kann NAMEDATALEN in der Datei src/include/postgres_ext.

geben Sie zwei Backslashes hintereinander ein. die von halben Anführungszeichen bzw. geschrieben werden.1. Zwei Zeichenkettenkonstanten. indem man ihn doppelt schreibt (z. \f ist ein Form-Feed.B. als ob sie als eine Konstante geschrieben worden wären.B. Beide Formen der Bitkettenkonstante können wie normale Zeichenkettenkonstanten über mehrere Zeilen verteilt werden. In PostgreSQL kann ein Apostroph auch in eine Zeichenkette eingefügt werden. Apostrophen (»'«) eingeschlossen sind. Jedes andere Zeichen nach einem Backslash wird unverändert übernommen.) Bitkettenkonstanten Bitkettenkonstanten sehen aus wie Zeichenkettenkonstanten mit einem B (groß oder klein geschrieben) direkt vor dem Anführungszeichen (ohne Leerzeichen dazwischen). Das Zeichen mit dem Code null kann nicht in einer Zeichenkettenkonstante enthalten sein. Die einzigen Zeichen.B. Zahlenkonstanten Zahlenkonstanten können in diesen allgemeinen Formen geschrieben werden: 57 . Zum Beispiel: SELECT 'foo' 'bar'. Bitketten und Zahlen. wobei xxx eine Oktalzahl ist. die in Bitkettenkonstanten erlaubt sind. Diese Schreibweise ist gleichbedeutend mit einer Bitkettenkonstante mit vier Binärziffern für jede Hexadezimalziffer. 'Dianne''s horse'). Um also ein Backslash in eine Zeichenkettenkonstante zu schreiben. die nur durch Leerzeichen.B. ist eine ungültige Syntax. \t ist ein Tab und \xxx. werden zusammengehängt und faktisch so behandelt. ist gleichbedeutend mit: SELECT 'foobar'. aber SELECT 'foo' 'bar'.2 Konstanten Es gibt drei Arten von Konstanten mit implizitem Typ in PostgreSQL: Zeichenketten. zum Beispiel 'Das ist eine Zeichenkette'. Zeichenkettenkonstanten Eine Zeichenkette in SQL ist eine Reihe von beliebigen Zeichen. PostgreSQL folgt dem Standard. Konstanten können auch mit explizitem Typ angegeben werden. die expliziten Konstanten folgen danach. Ein Apostroph kann in eine Zeichenkette eingefügt werden. sind 0 und 1. 'Dianne\'s horse'). \r ist ein Wagenrücklauf (englisch carriage return). z. Als Alternative können Bitkettenkonstanten auch in hexadezimaler Schreibweise.SQL-Syntax 4. z. ist das Zeichen mit dem entsprechenden ASCII-Code. mit einem X (groß oder klein) vor dem Anführungszeichen. indem man ihm einen Backslash (»\«) voranstellt (z. Backslash-Escape-Folgen im Stile von C sind auch möglich: \b ist ein Backspace (vorangegangenes Zeichen löschen). wodurch eine genauere und effizientere Verarbeitung im System erreicht werden kann. B'1001'. X'1FF'. Die impliziten Konstanten sind unten beschrieben. Tabs und mindestens einen Zeilenumbruch getrennt sind. (Dieses etwas wundersame Verhalten ist von SQL vorgeschrieben. \n ist ein Zeilenumbruch.

wenn der Wert in den Typ integer passt (32 Bits).6 wegen Einzelheiten. falls ein Punkt verwendet wird.Kapitel 4 ziffern ziffern. in diesem Fall wird sie automatisch umgewandelt. ansonsten wird der Typ bigint angenommen.Zeichenkettenstil 1. Hier sind einige Beispiele für gültige Zahlenkonstanten: 42 3. dann können Sie einen Zahlenwert in einen bestimmten Datentyp mit einer expliziten Typumwandlung (englisch Cast) zwingen. dass ein Zahlenwert als Typ real (float4) behandelt wird. Eine Typumwandlung kann auch mit einer Syntax ähnlich eines Funktionsaufrufs durchgeführt werden: typname ( 'zeichen' ) Aber nicht alle Typnamen können auf diese Art verwendet werden.23' -. um den Typ eines beliebigen Ausdrucks anzugeben. den die Konstante haben muss. ansonsten wird der Typ numeric verwendet.oder Minuszeichen am Anfang nicht wirklich Teil der Konstante ist. wie in Abschnitt 4.5 4. Aber die Form typ 58 .[ziffern][e[+-]ziffern] [ziffern]. siehe Abschnitt 4. In den meisten Fällen wird die Konstante automatisch je nach Zusammenhang in den passenden Typ umgewandelt. Mindestens eine Ziffer muss vor oder nach dem Punkt (der für das Komma steht) stehen. Konstanten mit Punkt oder Exponent werden anfänglich immer als Typ numeric verarbeitet. Die Formen ::. Mindestens eine Ziffer muss nach der Exponentenmarkierung (e) stehen.23::REAL -. sondern als vorgestellter Operator verarbeitet wird.2. Leerzeichen oder andere Zeichen dürfen in einer Zahlenkonstante nicht vorkommen. falls eine verwendet wird. Der anfänglich zugewiesene Datentyp einer Zahlenkonstante ist nur ein Ausgangspunkt für den Typauflösungsalgorithmus. CAST() und die funktionsaufrufähnliche Form können auch verwendet werden.2. gibt (zum Beispiel weil sie als Argument einer nicht überladenen Funktion verwendet wird). wenn es keine Zweideutigkeit bezüglich des Typs. Beachten Sie auch. indem Sie schreiben REAL '1.001 5e2 1.ziffern[e[+-]ziffern] zifferne[+-]ziffern wobei ziffern für eine oder mehrere Dezimalziffern (0 bis 9) steht.925e-3 Eine Zahlenkonstante ohne Punkt und Exponent wird anfänglich als Typ integer verarbeitet. wenn der Wert in den Typ bigint passt (64 Bits). Das Ergebnis ist eine Konstante des angegebenen Typs.PostgreSQL-Stil (historisch) Konstanten anderer Typen Eine Konstante eines beliebigen Typs kann in jeder der folgenden Schreibweisen eingegeben werden: typ 'zeichen' 'zeichen'::typ CAST ( 'zeichen' AS typ ) Der Text der Zeichenkette wird der Eingabeumwandlungsroutine des benannten Typs übergeben. Die ausdrückliche Umwandlung kann ausgelassen werden.6 besprochen. dass ein Plus. Sie können zum Beispiel erzwingen. . Wenn es erforderlich ist.

Wenn Sie zum Beispiel einen linken Präfixoperator namens @ definiert haben. müssen Sie in der Regel die Operatoren mit Leerzeichen voneinander trennen. es sei denn. weil sie als der Anfang eines Kommentars angenommen werden. zu verarbeiten.3 Operatoren Ein Operator ist eine Folge von bis zu NAMEDATALEN-1 (normalerweise 63) Zeichen aus der folgenden Liste: + . die im vorigen Abschnitt besprochen wurden.und /* können nirgendwo in einem Operatornamen auftauchen. der Name enthält mindestens eins der folgenden Zeichen: ~ ! @ # % ^ & | ` ? $ So ist zum Beispiel @.{4. können Sie nicht X*@Y schreiben. wie es in seinem pg_type-Eintrag gespeichert ist. ❏ Ein Operatorname. das aus drei Subarrays mit Ganzzahlen besteht. die dem SQL-Standard folgen. Anfragen. Eine weitere Einschränkung bezüglich typ 'zeichen' ist.6}. Diese Einschränkung erlaubt es PostgreSQL.9}}' Diese Konstante ist ein zweidimensionales 3-mal-3-Array. um Unklarheiten über Leerzeichen zu vermeiden. dass PostgreSQL den Ausdruck als zwei Operatornamen liest und nicht nur als einen. (Für alle eingebauten Typen ist das das Komma. Ohne Anführungszeichen überspringt der Arrayparser vorangestellte Leerzeichen.8.5. 59 . sondern Sie müssen X* @Y schreiben. (Arraykonstanten sind im Prinzip nur ein besonderer Fall der allgemeinen Typkonstanten. nicht aber *-.SQL-Syntax 'zeichen' kann nur verwendet werden. kann nicht auf + oder – enden.2. dass sie nicht für Arraytypen funktioniert.) 4. ohne Leerzeichen zwischen den Tokens zu erfordern.3}. um sicherzustellen. }' wobei trenn für das Trennzeichen des Typs steht. um den Typ einer Arraykonstante festzulegen. ❏ -. Die einzelnen Arrayelemente können zwischen Anführungszeichen (") gesetzt werden. der aus mehreren Zeichen besteht. Arraykonstanten Das allgemeine Format einer Arraykonstante ist das folgende: '{ wert1 trenn wert2 trenn .1. Die Konstante wird anfänglich als Textkonstante behandelt und wird dann an die Eingabeumwandlungsroutine für Arrays übergeben.* / < > = ~ ! @ # % ^ & | ` ? $ Es gibt allerdings ein paar Einschränkungen für die Operatornamen: ❏ $ (Dollarzeichen) kann nicht als einzelnes Zeichen ein Operator sein. um Unklarheiten zu vermeiden. Ein Beispiel einer Arraykonstante ist '{{1.) Jedes wert ist entweder eine Konstante des Arrayelementtyps oder ein Subarray.{7.ein zulässiger Operatorname. verwenden Sie :: oder CAST(). die nicht dem SQL-Standard folgen. Wenn Sie mit Operatornamen arbeiten.. um den Typ einer Konstante zu bestimmen.. Eine ausdrückliche Typumwandlung kann notwendig sein. Es kann allerdings Teil eines Operatornamens aus mehreren Zeichen sein.

Ausdrücke zu gruppieren und die Reihenfolge in der Auswertung der Ausdrücke zu erzwingen.) schließt einen SQL-Befehl ab. Dieser Abschnitt dient nur dazu.1 zeigt den Vorrang und die Anhänglichkeit der Operatoren in PostgreSQL.1. so haben zum Beispiel die Boole'schen Operatoren < und > einen anderen Vorrang als die Boole'schen Operatoren <= und >=. ❏ Eckige Klammern ([]) werden verwendet. (Siehe Abschnitt 8. Ein Kommentar wird vom Eingabestrom entfernt. in einer Zeichenkettenkonstante oder einem Namen in Anführungszeichen.5 Kommentare Ein Kommentar ist eine beliebige Reihe von Zeichen. die mit zwei Minuszeichen anfängt und bis zum Zeilenende geht. ❏ Der Stern (*) hat eine besondere Bedeutung. Der Vorrang und die Anhänglichkeit sind im Parser festgeschrieben. ❏ Der Punkt (. 4. wie in SQL99 vorgeschrieben. In anderen Zusammenhängen kann das Dollarzeichen Teil eines Operatornamens sein. ❏ Kommas (. ❏ Der Doppelpunkt (:) wird verwendet.6 Vorrang Tabelle 4. es sei denn. wenn er im SELECT-Befehl oder in der Aggregatfunktion COUNT verwendet wird. selbst wenn diese selbst Blockkommentare enthalten. die nicht alphanumerisch sind. Es kann sonst nirgendwo in einem SQL-Befehl auftreten. das nicht intuitiv ist. Als Alternative können Blockkommentare im C-Stil verwendet werden: /* mehrzeiliger Kommentar * mit Verschachtelung: /* verschachtelter Blockkommentar */ */ Der Kommentar beginnt mit /* und geht bis zum passenden */. Sie auf das Vorhandensein dieser Zeichen hinzuweisen und ihre Zwecke zusammenzufassen. 4.) In einigen SQL-Dialekten (wie zum Beispiel eingebettetes SQL (englisch Embedded SQL)). haben besondere Bedeutung. wo das Syntaxelement beschrieben ist. Diese Blockkommentare können verschachtelt werden. Die meisten Operatoren haben den gleichen Vorrang und sind links anhänglich. Sehen Sie in Abschnitt 8. 60 .11. steht der Doppelpunkt vor Variablennamen. ❏ Das Semikolon (. um aus Arrays »Stücke« auszuwählen. um Elemente einer Liste zu trennen. und faktisch durch Leerzeichen ersetzt. In einigen Fällen sind Klammern fester Bestandteil der Syntax bestimmter SQL-Befehle.1.1. Tabellenund Spaltennamen zu trennen. ❏ Ein Dollarzeichen ($) gefolgt von Ziffern steht für die Positionsparameter im Körper einer Funktionsdefinition.Das ist ein normaler SQL92-Kommentar. Das kann zu einem Verhalten führen.) wird in Zahlenkonstanten verwendet (anstelle des Kommas) und um Schema.) werden in einigen Zusammenhängen verwendet. aber im Gegensatz zu C. sodass man größere Blöcke Code auskommentieren kann. Einzelheiten können Sie dort finden. um Elemente aus Arrays auszuwählen.11 nach.4 Sonderzeichen Einige Zeichen. um mehr Informationen über Arrays zu erhalten. Zum Beispiel: -. bevor die Syntax weiter analysiert wird. ❏ Klammern (()) haben ihre gewöhnliche Bedeutung.Kapitel 4 4. die aber nicht einem Operatornamen entspricht.

6). 61 . Um das gewünschte Verhalten in diesem Fall zu erreichen. Diesen Preis zahlt man für die Erweiterbarkeit. Subtraktion IS TRUE. IS FALSE. dass die Operatorvorrangsregeln auch für benutzerdefinierte Operatoren gelten.SQL-Syntax Manchmal werden Sie auch Klammern hinzufügen müssen. Zum Beispiel: SELECT 5 ! . Wertzuweisung logische Negierung logische Konjunktion logische Disjunktion (alle anderen) IN BETWEEN OVERLAPS LIKE ILIKE SIMILAR < > = NOT AND OR Tabelle 4. :: [ ] ^ * / % + IS ISNULL NOTNULL Anhänglichkeit links links links rechts links links links Beschreibung Trennung von Tabellen-/Spaltennamen PostgreSQL -Stil Typumwandlung Auswahl Arrayelement unäres Minus Potenzierung Multiplikation. Modulus Addition. schreiben. Division. größer als rechts rechts links links Gleichheit. Operator/Element . wenn Sie Kombinationen von binären und unären Operatoren verwenden. ganz gleich. was Ihrer tut. müssen Sie SELECT (5 !) . dass ! als Postfixoperator und nicht als Infixoperator definiert ist. dann hat er den gleichen Vorrang wie der eingebaute »+«-Operator.6. weil der Parser keine Ahnung hat – bevor es zu spät ist -. IS NULL Test für NULL Test für nicht NULLs links alle anderen eingebauten und benutzerdefinierten Operatoren Mengenmitgliedschaft Vergleich Zeitintervall überlappt Mustervergleich von Zeichenketten kleiner als.1: Operatorvorrang (abnehmend) Beachten Sie.6. Wenn Sie zum Beispiel einen Operator »+« für einen eigenen Datentyp definieren. wird verarbeitet als SELECT 5 ! (. die die gleichen Namen haben wie die eingebauten Operatoren. IS UNKNOWN.

spaltenname[index] (Die eckigen Klammern [ ] sollen hier wortwörtlich erscheinen.2.2 Wertausdrücke Wertausdrücke werden in verschiedenen Zusammenhängen verwendet.1 mit »alle anderen« bezeichnet ist. Wertausdrücke werden daher auch als Skalarausdrücke (oder einfach Ausdrücke) bezeichnet.+) 4. Ein Wertausdruck ist eines der Folgenden: ❏ ❏ ❏ ❏ ❏ ❏ ❏ ❏ ❏ eine Konstante. Das Ergebnis eines Wertausdrucks wird manchmal als Skalar bezeichnet. Das gilt unabhängig davon. als neue Spaltenwerte in INSERT. dann hat die OPERATOR-Konstruktion den Standardvorrang. im Körper einer Funktionsdefinition ein Operatoraufruf ein Funktionsaufruf ein Aggregatausdruck eine Typumwandlung eine skalare Unteranfrage ein Wertausdruck in Klammern. Konstanten haben wir schon in Abschnitt 4. während die anderen Korrelationsnamen in jedem SQL-Befehl verwendet werden 62 . 4. mengenarithmetischen und anderen Operationen. aber keiner allgemeinen Syntaxregel folgen. die als Ausdruck klassifiziert werden können. indem man schreibt: korrelation. das in einer FROMKlausel definiert wurde. Die Syntax für Ausdrücke erlaubt die Berechnung von Werten aus einfachen Bestandteilen mit arithmetischen.oder UPDATE-Befehlen oder als Suchbedingungen in einer Reihe von Befehlen. logischen.2. so zum Beispiel in der Zielliste eines SELECT-Befehls. der in Tabelle 4.1. oder die Schlüsselwörter NEW oder OLD. 4. ein Spaltenverweis ein Verweis auf einen Positionsparameter. um es vom Ergebnis eines Tabellenausdrucks (welches eine Tabelle ist) zu unterscheiden.Kapitel 4 Wenn ein Operator mit Schemaname in der OPERATOR-Syntax verwendet wird. (NEW und OLD können nur in Umschreibungsregeln auftreten. siehe Abschnitt 4.1. welcher Operator nun genau innerhalb von OPERATOR steht. Diese ähneln in der Regel einer Funktion oder einem Operator und sind im entsprechenden Abschnitt in Kapitel 9 erläutert.spaltenname oder korrelation. Die folgenden Abschnitte besprechen die übrigen Möglichkeiten.2 besprochen. Ein Beispiel ist die IS NULL-Klausel. wie im Beispiel SELECT 3 OPERATOR(pg_catalog. um Teilausdrücke zu gruppieren und den Vorrang zu verändern Über diese Liste hinaus gibt es eine Reihe weiterer Konstruktionen.) korrelation ist der Name einer Tabelle (möglicherweise mit Schema) oder ein Alias.1 Spaltenverweise Auf eine Spalte kann man verweisen.

) Wenn spalte einen Arraytyp hat.11 für weitere Informationen über Arrays.) 4. Parameter werden in der Definition von SQL-Funktionen und in vorbereiteten Anfragen verwendet. Wenn die Funktion aufgerufen wird. OR und NOT oder ein qualifizierter Operatorname OPERATOR(schema.2.2. Die Form eines Parameterverweises ist: $zahl Betrachten Sie zum Beispiel die Definition einer Funktion. eindeutig ist. wenn der Spaltenname über alle Tabellen.3 Operatoraufrufe Es gibt drei mögliche Syntaxen für einen Operatoraufruf: ausdruck operator ausdruck (binärer Infix-Operator) operator ausdruck (unärer Präfix-Operator) ausdruck operator (unärer Postfix-Operator) wobei operator den in Abschnitt 4. wird $1 hier durch das erste Funktionsargument ersetzt. der dem SQL-Befehl von einer externen Quelle zur Verfügung gestellt wird. 4. gefolgt von der Argumentliste in Klammern: funktion ([ausdruck [.SQL-Syntax können. hängt davon ab. welche Operatoren vom System oder vom Benutzer definiert worden sind. dann kann zusätzlich index verwendet werden. als CREATE FUNCTION abteilung(text) RETURNS abteilung AS 'SELECT * FROM abteilung WHERE name = $1' LANGUAGE SQL. 4.operatorname) ist. abteilung. Wenn kein Index angegeben wird.1. ]] ) Das folgende Beispiel berechnet die Quadratwurzel (englisch square root) von 2: sqrt(2) 63 .3 beschriebenen Syntaxregeln folgt oder eines der Schlüsselwörter AND. (Siehe auch unter Abschnitt 8. Welche Operatoren im Einzelnen vorhanden sind und ob sie unär oder binär sind. (Siehe auch Kapitel 7. Kapitel 9 beschreibt die eingebauten Operatoren.4 Funktionsaufrufe Die Syntax eines Funktionsaufrufs ist der Name einer Funktion (möglicherweise mit einem Schemanamen qualifiziert).2 Positionsparameter Ein Positionsparameter ist ein Verweis auf einen Wert. dann wird das gesamte Array ausgewählt.) Der Korrelationsname und der trennende Punkt können weggelassen werden. um ein bestimmtes Element oder bestimmte Elemente aus dem Array auszuwählen.. die in der gegenwärtigen Anfrage verwendet werden. ausdruck ..2.

den der Wertausdruck produzieren muss.Kapitel 4 Die Liste der eingebauten Funktionen befindet sich in Kapitel 9. die auf eine einfache Zeichenkettenkonstante angewendet wird.6 Typumwandlungen Eine Typumwandlung (englisch type cast) beschreibt die Umwandlung eines Datentyps in einen anderen. unabhängig davon. PostgreSQL akzeptiert zwei gleichbedeutende Syntaxen für Typumwandlungen: CAST ( ausdruck AS typ ) expression::type Die Syntax mit CAST stimmt mit dem SQL-Standard überein. wie zum Beispiel die Summe oder den Durchschnitt der Werte. aber die vorgegebenen tun dies alle. Ein Beispiel: count(*) ergibt die Gesamtzahl der Eingabezeilen. Wenn eine Typumwandlung auf einen Wertausdruck mit bekanntem Typ angewendet wird. die von einer Anfrage ausgewählt wurden. besteht (wenn er zum Beispiel einer Tabellen- 64 . die Syntax mit :: ist die historische PostgreSQL-Variante. Eine Aggregatfunktion reduziert mehrere Eingabewerte auf einen einzelnen Wert. wenn eine passende Umwandlungsfunktion verfügbar ist.2. Die Umwandlung ist nur erfolgreich. Die dritte Form führt die Aggregatfunktion für alle unterschiedlichen Nicht-NULL-Werte. Die letzte Form führt die Aggregatfunktion einmal für jede Eingabezeile aus. Das ist auf subtile Weise anders als die Verwendung von Typumwandlungen mit Konstanten. count(distinct f1) ergibt die Gesamtzahl der unterschiedlichen Werte von f1. Da kein bestimmter Eingabewert angegeben wird. ist die anfängliche Zuweisung eines Typs für die Konstante und ist mit jedem Typ erfolgreich (wenn der Inhalt der Zeichenkette gültige Syntax für den Datentyp ist). wenn keine Zweideutigkeit über den Typ. für die der angegebene Ausdruck keinen NULL-Wert ergibt. dann ist das eine Laufzeit-Umwandlung. ob der Wert NULL ist oder nicht.14 beschrieben. aus. wie in Abschnitt Konstanten anderer Typen beschrieben. die sich aus dem Ausdruck für die Eingabezeilen ergeben. wo f1 nicht NULL ist. da ALL die Standardvorgabe ist. ob sie NULL-Werte ignorieren will. der nicht selbst einen Aggregatausdruck enthält. Eine Typumwandlung. (Tatsächlich entscheidet die Aggregatfunktion.2.5 Aggregatausdrücke Ein Aggregatausdruck steht für die Anwendung einer Aggregatfunktion über eine Menge von Zeilen. Eine ausdrückliche Typumwandlung kann normalerweise ausgelassen werden. Die erste Form des Aggregatausdrucks führt die Aggregatfunktion für alle Eingabezeilen aus. die nicht NULL sind. 4. Andere Aggregatfunktionen können von Benutzern hinzugefügt werden. ist diese Form nur für die Aggregatfunktion count() nützlich. 4. count(f1) ergibt die Gesamtzahl der Eingabezeilen. Die vordefinierten Aggregatfunktionen sind in Abschnitt 9. Andere Funktionen können vom Benutzer hinzugefügt werden.) Die zweite Form ist die gleiche wie die erste. ist. Die Syntax eines Aggregatausdrucks ist eine der folgenden: aggregat_name aggregat_name aggregat_name aggregat_name (ausdruck) (ALL ausdruck) (DISTINCT ausdruck) ( * ) wo aggregat_name eine vorab definierte Aggregatfunktion (möglicherweise mit Schemaname) und ausdruck ein beliebiger Wertausdruck.

) Die Unteranfrage kann sich auf Variablen in der äußeren Anfrage beziehen.7 Skalare Unteranfragen Eine sklare Unteranfrage ist eine normale SELECT-Anfrage in Klammern. eine Typumwandlung in einer funktionsähnlichen Syntax zu schreiben: typname ( ausdruck ) Das funktioniert allerdings nur für Typnamen. Das folgende Beispiel findet die Stadt mit der größten Einwohnerzahl in jedem Land: SELECT name. das skalare Ergebnis ist dann der NULL-Wert. Daher führt die Verwendung der funktionsähnlichen Syntax zu Ungereimtheiten und sollte wahrscheinlich in neuen Anwendungen vermieden werden. die auch als Funktionsnamen zulässig sind. Insbesondere werden die Argumente einer Funktion oder eines Operators nicht unbedingt von links nach rechts oder in einer anderen festgelegten Reihenfolge ausgewertet. dann ist das kein Fehler. aber mehr als eine Zeile oder eine Spalte ergibt. wie man Anfragen schreibt. Es ist auch möglich. Wenn man zum Beispiel schreiben würde SELECT true OR einefunktion(). double precision kann zum Beispiel auf diese Art nicht verwendet werden. wenn nur Teile davon ausgewertet werden. Es ist ein Fehler. time und timestamp aufgrund von Syntaxkonflikten so nicht verwendet werden.15. um eine Laufzeitumwandlung durchzuführen. dann würde einefunktion() (wahrscheinlich) gar nicht aufgerufen werden. sie werden von Anführungszeichen eingeschlossen. (Aber wenn in einem bestimmten Aufruf die Unteranfrage gar keine Zeilen ergibt.2. im Gegensatz zum gleichbedeutenden float8. um die Umwandlung durchzuführen. dann könnten andere Teilausdrücke womöglich gar nicht ausgewertet werden. 65 . in solchen Fällen wendet das System eine Umwandlung automatisch an. (SELECT max(einwohner) FROM städte WHERE städte. die genau eine Zeile mit einer Spalte ergibt.2.SQL-Syntax spalte zugewiesen wird). Ferner gilt: Wenn das Ergebnis eines Ausdrucks auch bestimmt werden kann. (Siehe in Kapitel 7 für Informationen. ist nicht definiert. Das Gleiche wäre der Fall wenn man schreiben würde SELECT einefunktion() OR true. Wenn einer der beiden normalen Umwandlungsyntaxen verwendet wird. 4. wenn eine Anfrage als skalare Unteranfrage verwendet wird. Diese Einschränkung besteht. die im Systemkatalog zur »automatischen Umwandlung freigegeben« sind. dass diese Umwandlungsfunktionen den gleichen Namen haben wie ihr Ergebnistyp. welche sich dann bei jeder einzelnen Auswertung der Unteranfrage als Konstanten verhalten.land = länder. dann wird intern eine eingetragene Funktion aufgerufen. (Die funktionsähnliche Syntax ist tatsächlich ein normaler Funktionsaufruf.name) FROM länder. aber portierbare Anwendungen sollten sich nicht darauf verlassen. Diese automatische Umwandlung wird allerdings nur für Umwandlungen angewendet.) Der SELECT-Befehl wird ausgeführt und der einzelne Ergebniswert wird in dem übergeordneten Wertausdruck verwendet.) 4. Siehe auch unter Abschnitt 9. Es ist Brauch. damit überraschende Umwandlung nicht ohne Benachrichtigung ausgeführt werden. Andere Umwandlungen müssen mit der ausdrücklichen Umwandlungssyntax durchgeführt werden.8 Auswertung von Ausdrücken Die Reihenfolge. in der Ausdrücke ausgewertet werden. es sei denn. Außerdem können die Namen interval.

..und HAVING-Klauseln zu verlassen. die von den Gesetzen der Boole'schen Algebra erlaubt werden. verhindert Optimierungen und sollte daher nur wenn unbedingt nötig angewendet werden. dass das nicht das Gleiche ist wie die »Short-Circuiting«-Technik von Boole'schen Operationen von links nach rechts. sich auf die Nebenwirkungen oder die Auswertungsreihenfolge in WHERE. umgeordnet werden. die auf diese Art verwendet wird. WHERE CASE WHEN x <> 0 THEN y/x > 1. Eine CASE-Konstruktion. OR. Funktionen mit Nebenwirkungen in komplexen Ausdrücken zu verwenden. die Reihenfolge der Auswertung von Ausdrücken festzulegen. WHERE x <> 0 AND y/x > 1. dann kann die CASE-Konstruktion (siehe Abschnitt 9.. eine Division durch null in einer WHERE-Klausel zu vermeiden: SELECT . Boole'sche Operationen (Kombinationen aus AND.Kapitel 4 Beachten Sie.5. Es ist besonders gefährlich.5 ELSE false END. Folglich ist es unklug. Wenn es erforderlich ist.12) verwendet werden. Hier ist zum Beispiel eine unverlässliche Methode. NOT) in diesen Klauseln können nach allen Möglichkeiten.. während der Ausführungsplan einer Anfrage entwickelt wird. 66 . die in manchen Programmiersprachen angewendet wird. da diese Klauseln umfassend umgearbeitet werden. Aber dies hier ist sicher: SELECT .

Weitere Informationen über diese Themen können Sie in Teil V finden. akzeptiert keine beliebigen Zeichenketten. wie Zeichenkettenverknüpfung. Dagegen stehen andere Operationen. Die Anzahl der Zeilen ist veränderlich: Sie hängt davon ab. PostgreSQL enthält eine Menge eingebauter Datentypen. um zu kontrollieren. es sei denn eine Sortierung wird ausdrücklich angefordert. die sich auf die Datenbankstrukturen auswirken. das SQL zugrunde liegt. Ein Spalte. die zum Beispiel als Zahlentyp deklariert wurde. aber es ist in der Regel nicht wünschenswert.1 Tabellengrundlagen Eine Tabelle in einer relationalen Datenbank ist einer Tabelle auf Papier ziemlich ähnlich: Sie besteht aus Zeilen und Spalten. welche Daten in den Tabellen gespeichert werden können. Im Gegensatz dazu kann eine Spalte. Am Schluss werden wir uns kurz weiteren Fähigkeiten. numeric für Zahlen mit möglichem 67 . die dann die zu verarbeitenden Daten enthalten. Dieser Datentyp beschränkt die Menge der möglichen Werte. Benutzer können auch ihre eigenen Datentypen definieren. wie viele Daten gerade gespeichert werden. mehrere vollständig identische Zeilen in einer Tabelle zu haben. und folglich erklärt der Großteil dieses Kapitels. und wie Zugriffsrechte für Tabellen zugewiesen werden können. sodass sie in Berechnungen verwendet werden können. erscheinen die Zeilen in zufälliger Reihenfolge. die als Zeichenkettentyp deklariert wurde. Das ist eine Folge des mathematischen Modells. Jede Spalte hat einen Datentyp. so ziemlich alle Arten von Daten aufnehmen. wie man die Datenbankstrukturen erzeugt. Die Anzahl und die Reihenfolge der Spalten ist festgelegt und jede Spalte hat einen Namen. Einige häufig verwendete Datentypen sind integer für Ganzzahlen. Wenn eine Tabelle ausgelesen wird. und weist den Daten. Außerdem weist SQL den Zeilen keine eindeutige Identifizierung zu. wie zum Beispiel Sichten.5 5 Datendefinition Dieses Kapitel behandelt. wie man Tabellen erzeugt und verändert und welche Fähigkeiten zur Verfügung stehen. Die meisten eingebauten Datentypen haben offensichtliche Namen und Bedeutungen. 5. einen semantischen Wert zu. sodass es möglich ist. indem man sie auf verschiedene Schemas verteilt. zur Verfügung. die der Spalte zugewiesen werden können. SQL gibt aber keine Garantie über die Reihenfolge der Zeilen in einer Tabelle. In einer relationalen Datenbank werden die Daten in Tabellen abgespeichert. wie wir mit diesem Problem fertig werden können. Dies ist in Kapitel 7 besprochen. Anschließend besprechen wir. Funktionen und Trigger. wie Tabellen organisiert werden können. die in der Spalte gespeichert werden. aber nicht für mathematische Berechnungen verwendet werden. die für viele Anwendungen passend sind. Später in diesem Kapitel werden wir sehen. sodass wir mit einer detaillierten Erklärung bis Kapitel 8 warten. aber die Daten in einer solchen Spalte können für mathematische Berechnungen verwendet werden. zuwenden.

Beachten Sie. in Stapeldateien mit SQL-Befehlen.5 weiter unten in diesem Kapitel. zweite_spalte integer ). Mit den bis jetzt besprochenen Werkzeugen können Sie voll funktionsfähige Tabellen erzeugen. verwenden Sie den Befehl CREATE TABLE. Wenn Sie eine bestehende Tabelle verändern wollen.) Tipp Wenn Sie viele Tabellen erstellen. Schauen wir uns also ein etwas realistischeres Beispiel an: CREATE TABLE produkte ( produkt_nr integer. die untereinander in Verbindung stehen. Die Namen der Tabelle und der Spalten müssen den in Abschnitt 4. In diesem Befehl geben Sie mindestens den Namen der neuen Tabelle. wie viele Spalten eine Tabelle enthalten kann. Normalerweise werden Sie Ihren Tabellen und Spalten Namen geben. wie sie in Preisangaben auftreten. Ein Tabelle mit so vielen Spalten zu erzeugen. Die Typnamen folgen diesen Regeln normalerweise auch. ist ein Fehler. name text. Zum Beispiel: DROP TABLE meine_erste_tabelle. In Abhängigkeit von den Spaltentypen ist diese Grenze zwischen 250 und 1600. (Der Typ numeric kann Nachkommastellen speichern. die vermitteln. date für Datumsangaben. Zum Beispiel: CREATE TABLE meine_erste_tabelle ( erste_spalte text. DROP TABLE produkte. ein einheitliches Muster für die Namen von Tabellen und Spalten zu verwenden. ist aber sehr ungewöhnlich und oft ein ziemlich fragwürdiger Entwurf. die Namen der Spalten und die Datentypen jeder Spalte an. aber es gibt Ausnahmen. time für Tageszeitangaben und timestamp für Werte mit Datum und Zeit. Das erzeugt eine Tabelle namens meine_erste_tabelle mit zwei Spalten. welche Daten sie speichern. dann können Sie sie mit dem Befehl DROP TABLE entfernen.1. text für Zeichenketten. Die erste Spalte heißt erste_spalte und hat den Datentyp text. Um eine Tabelle zu erzeugen. um 68 . preis numeric ). Es gibt zum Beispiel die Wahl zwischen Einzahl und Mehrzahl für die Tabellennamen. Trotzdem ist es gebräuchlich. Das obige Beispiel ist natürlich gekünstelt. dann schauen Sie in Abschnitt 5. wobei beides von dem einen oder anderen Theoretiker bevorzugt wird. dass die Spalteneinträge durch Kommas getrennt sind und die Spaltenliste in Klammern steht.Kapitel 5 Bruchteil.1 beschriebenen Regel für Namen folgen. die zweite Spalte heißt zweite_spalte und hat den Typ integer. eine nicht vorhandene Tabelle zu entfernen. Der Rest dieses Kapitels beschäftigt sich mit weiteren Merkmalen. Der Versuch. dann ist es sinnvoll. Tabellen vor der Erzeugung bedingungslos zu entfernen und die Fehlermeldungen zu ignorieren. die Sie Ihren Tabellen hinzufügen können. Wenn Sie eine Tabelle nicht mehr benötigen. Es gibt eine Begrenzung.

) cmin Die Befehlsnummer (englisch Command Identifier) (von null an zählend) innerhalb der einfügenden Transaktion. ob der Name ein Schlüsselwort ist. Diese Spalte ist besonders nützlich in Anfragen. um die Zeile schnell zu finden. Diese Spalte hat den Typ oid (gleicher Name wie die Spalte). dass OIDs eindeutig sind. wenn sie aktualisiert oder durch VACUUM FULL bewegt wird. die aus Vererbungshierarchien auswählen. die diese Zeilenversion eingefügt hat. aber die ctid einer Zeile ändert sich jedes Mal. außer zu wissen. dass der Zähler überläuft und wieder von vorne anfängt. dann springen Sie zu Kapitel 6 und lesen Sie den Rest dieses Kapitels später. denn ohne sie ist es schwer zu ermitteln. die von PostgreSQL jeder Zeile automatisch hinzugefügt wird (es sei denn. dass sie existieren. die Eindeutigkeit abzusichern.10 für weitere Informationen über den Typ. tableoid Die OID der Tabelle. (Beachten Sie. oid Der Objekt-Identifikator (englisch Object Identifier) einer Zeile. die Tabelle wurde mit WITHOUT OIDS erzeugt.2 Systemspalten Jede Tabelle hat mehrere Systemspalten. Beachten Sie. Die tableoid kann mit der oid-Spalte der Tabelle pg_class verbunden werden. aus welcher einzelnen Tabelle die Zeile kam. Die OID oder besser noch eine benutzerdefinierte Seriennummer sollte zur Identifizierung von logischen Zeilen verwendet werden. ctid Die physikalische Speicherungsstelle der Zeilenversion innerhalb der Tabelle. die diese Zeile enthält. Sie können diese Einschränkung nicht umgehen. Wenn Sie ungeduldig sind und Ihre Tabellen jetzt mit Daten füllen wollen. In einer großen oder langlebigen Datenbank ist es deshalb möglich. anzunehmen. Diese Spalte kann auch für eine sichtbare Zeilenversion von null verschieden sein: Das bedeutet in der Regel. außer wenn man Schritte unternimmt. xmax Die Identität (Transaktionsnummer) der löschenden Transaktion oder null. dass die löschende Transaktion noch nicht abgeschlossen oder dass das versuchte Löschen zurückgerollt wurde. dann ist diese Spalte nicht vorhanden). xmin Die Identität (Transaktionsnummer) der Transaktion. in der die 69 . Wenn man OIDs zur Zeilenidentifikation verwendet. dass ctid zwar verwendet werden kann. Daher ist die ctid als Zeilenidentifikation über längere Zeiträume hinweg nicht zu gebrauchen.) Sie müssen sich um diese Spalten nicht weiter kümmern. OIDs sind 32-Bit-Größen und werden von einem einzigen Zähler in jedem Cluster erzeugt. einen Unique Constraint für die OID-Spalte jeder Tabelle zu erzeugen. Das ist eine Seriennummer. ( Jede Aktualisierung erzeugt eine neue Version derselben logischen Zeile. die von System automatisch erzeugt werden. Daher ist es eine schlechte Strategie. indem Sie den Namen in Anführungszeichen setzen. cmax Die Befehlsnummer innerhalb der löschenden Transaktion oder null.Datendefinition die Integrität oder Sicherheit der Daten sicherzustellen oder die Datenverwaltung bequemer zu gestalten. 5. siehe unter Abschnitt 8. ist es zu empfehelen. Diese Namen können daher nicht als Namen von benutzerdefinierten Spalten verwendet werden. um den Tabellennamen zu ermitteln. wenn die Zeilenversion nicht gelöscht ist. dass diese Einschränkung nichts damit zu tun hat.

99 ). Befehlsnummern sind ebenso 32 Bit groß. In einer langlebigen Datenbank ist es daher möglich. um einen überall eindeutigen Zähler zu konstruieren.4 Constraints Mit der Auswahl des Datentyps kann man die Art der Daten. wenn Sie einen Zähler brauchen. Einzelheiten sind in Kapitel 21 zu finden. Das ist kein schwerwiegendes Problem. Daten in eine Spalte zu schreiben. Ein Spalte mit einem Produktpreis sollte zum Beispiel wahrscheinlich nur positive Werte aufnehmen dürfen. dass OIDs über mehrere Tabellen hinweg eindeutig sind. Wenn eine neue Zeile erzeugt wird und für einige Spalten keine Werte angegeben sind. wo die Daten unbekannt sind. Aber es gibt keinen Datentyp. In einer Tabellendefinition werden die Vorgabewerte nach dem Spaltendatentyp aufgelistet. wird ein Fehler ausgegeben. verwenden Sie die Kombination aus tableoid und der Zeilen-OID. welcher immer ausgewertet wird. werden die Spalten mit ihren entsprechenden Vorgabewerten gefüllt. Das ist in der Praxis kein Problem. Es ist allerdings nicht empfehlenswert. Der Vorgabewert kann ein skalarer Ausdruck sein. ohne zu wissen. Ein Datenmanipulationsbefehl kann auch ausdrücklich verlangen. die in einer Spalte gespeichert werden können. die den Constraint verletzen würde. wenn die Tabelle erzeugt wird). Aus diesem Grund erlaubt SQL es Ihnen. In einer Tabelle mit Produktinformationen sollte zum Beispiel nur eine Zeile für jede Produktnummer auftauchen. 70 . wird der NULL-Wert als Vorgabe angenommen. (Einzelheiten zu Datenmanipulationsbefehlen finden Sie in Kapitel 6. beschränken. Wenn ein Benutzer versucht. wie sie wollen.) Wenn kein Vorgabewert ausdrücklich definiert wurde. preis numeric DEFAULT 9. wenn man die Wartungsprozeduren regelmäßig durchführt. dass die Transaktionsnummern überlaufen und von vorne zu zählen anfangen. Das ist normalerweise sinnvoll. 5. (Zukünftige Versionen von PostgreSQL werden wahrscheinlich einen getrennten OID-Zähler für jede Tabelle verwenden. Constraints (englisch für Beschränkungen) für Spalten und Tabellen zu definieren. Daraus ergibt sich eine Grenze von 232 (4 Milliarden) SQLBefehlen innerhalb einer einzelnen Transaktion. Für viele Anwendungen ist diese Art der Beschränkung aber zu grob. Zum Beispiel: CREATE TABLE produkte ( produkt_nr integer. was dieser Wert ist. name text. Das gilt auch dann. 5. wenn ein Vorgabewert in die Tabelle eingefügt wird (also nicht schon. dass diese Grenze sich auf die Anzahl der SQL-Befehle bezieht und nicht die Anzahl der verarbeiteten Zeilen. der nur positive Zahlen akzeptiert. Gehen Sie niemals davon aus. Constraints geben Ihnen genau soviel Kontrolle über Ihre Daten. wenn der Wert aus der Definition des Vorgabewerts kam. Beachten Sie. sodass tableoid dann verwendet werden muss.) Transaktionsnummern sind auch 32 Bit groß. weil ein NULL-Wert eingesetzt wird. Eine andere Problematik ist.3 Vorgabewerte Einer Spalte kann ein Vorgabewert (englisch default value) zugewiesen werden.Kapitel 5 OID verwendet werden soll. dass Sie die Spaltendaten vielleicht auch in Bezug auf die Daten in anderen Spalten oder Zeilen beschränken wollen. der in der ganzen Datenbank eindeutig ist. dass eine Spalte auf ihren Vorgabewert gesetzt wird. sich auf die Eindeutigkeit von Transaktionsnummern über lange Zeiträume (mehr als eine Milliarde Transaktionen) zu verlassen.

wenn Sie ihn ändern müssen. Spalten-Constraints können auch als Tabellen-Constraints geschrieben werden. aber umgekehrt ist das nicht immer möglich. dass der Rabattpreis immer niedriger als der Normalpreis ist. Sie speichern einen normalen Preis und einen Rabattpreis und sie wollen sicherstellen.Datendefinition 5. Er steht nicht bei einer bestimmten Spalte. den jeder Wert einer Spalte erfüllen muss. Er erlaubt es Ihnen. Die ersten zwei Constraints sollten Ihnen bekannt vorkommen. Vorgabewerte und Constraints können in beliebiger Reihenfolge gelistet werden. Der dritte verwendet eine neue Syntax. steht die Constraint-Definition nach dem Datentyp. 71 . weil er getrennt von den Spaltendefinitionen geschrieben wird.1 Check-Constraints Ein Check-Constraint ist der allgemeinste Constraint-Typ. name text. Ein Check-Constraint kann sich auch auf mehrere Spalten beziehen. Man sagt. Um einen Namen für einen Constraint zu definieren. ansonsten wäre der Constraint nicht sehr sinnvoll. Ein CheckConstraint besteht aus dem Schlüsselwort CHECK. auf den Constraint zu verweisen. preis numeric CHECK (preis > 0). Nehmen wir an. CREATE TABLE produkte ( produkt_nr integer. name text. rabattpreis numeric CHECK (rabattpreis > 0). während der dritte ein TabellenConstraint ist. Um zum Beispiel positive Produktpreise zu erzwingen. könnten Sie Folgendes tun: CREATE TABLE produkte ( produkt_nr integer. preis numeric CHECK (preis > 0) ). sondern als getrenntes Element in der Spaltenliste. Spaltendefinitionen und diese Art der Constraint-Definition können in gemischter Reihenfolge aufgelistet werden. dass die ersten beiden Constraints Spalten-Constraints sind. name text. Das obige Beispiel kann auch so geschrieben werden: CREATE TABLE produkte ( produkt_nr integer. Die Syntax ist: CREATE TABLE produkte ( produkt_nr integer. einen beliebigen Ausdruck anzugeben. Wie Sie sehen.4. genauso wie die Definition des Vorgabewerts. CHECK (preis > rabattpreis) ). gefolgt von einem Ausdruck in Klammern. name text. preis numeric CONSTRAINT positiver_preis CHECK (preis > 0) ). Sie können einem Constraint auch einen getrennten Namen geben. Der Ausdruck sollte die auf diese Art beschränkte Spalte beinhalten. Das kann Fehlermeldungen klarer gestalten und erlaubt es Ihnen. schreiben Sie das Schlüsselwort CONSTRAINT gefolgt von dem Namen und der Definition des Constraints.

dass eine Spalte keine NULL-Werte enthalten kann. Um zu versichern. Sie beeinflusst auch nicht unbedingt die Reihenfolge. wenn das Ergebnis des Check-Ausdrucks logisch wahr oder der NULL-Wert ist. Es ist letztendlich Geschmackssache. wenn ein Operand der NULL-Wert ist. CHECK (preis > rabattpreis) ). der im folgenden Abschnitt beschrieben wird. sollte der NOT-NULL-Constraint. preis numeric ). Da die meisten Ausdrücke den NULL-Wert ergeben. Der Nachteil ist. 5. dass eine Spalte den NULL-Wert nicht aufnehmen darf. CHECK (preis > 0).2 NOT-NULL-Constraints Ein NOT-NULL-Constraint gibt ganz einfach an. preis numeric CHECK (preis > 0). CHECK (rabattpreis > 0). name text NOT NULL. Ein NOT-NULL-Constraint hat den gleichen Effekt wie ein Check-Constraint der Form CHECK (spaltenname IS NOT NULL).4. preis numeric NOT NULL CHECK (preis > 0) ). Ein NOT-NULL-Constraint wird immer als Spalten-Constraint geschrieben. aber in PostgreSQL ist der ausdrückliche NOT-NULL-Constraint effizienter. rabattpreis numeric. angewendet werden. Natürlich kann eine Spalte mehrere Constraints haben. in der die Constraints geprüft werden. Die Reihenfolge ist egal.Kapitel 5 preis numeric. 72 . CHECK (rabattpreis > 0 AND preis > rabattpreis) ). Schreiben Sie sie einfach hintereinander: CREATE TABLE produkte ( produkt_nr integer NOT NULL. name text. dass der Check-Constraint passiert wird. dass man dieser Art von NOT-NULL-Constraint keinen gesonderten Namen geben kann. name text NOT NULL. Man sollte beachten. rabattpreis numeric. verhindern sie keine NULL-Werte in den beschränkten Spalten. oder gar so: CREATE TABLE produkte ( produkt_nr integer. Ein Syntaxbeispiel: CREATE TABLE produkte ( produkt_nr integer NOT NULL.

dann werden die Spalten durch Kommas getrennt aufgelistet: CREATE TABLE beispiel ( a integer. Der bedeutet aber nicht. c integer.3 Tipp Unique Constraints In den meisten Datenbankentwürfen sollte die Mehrzahl der Spalten als NOT NULL markiert sein. 5. name text. und CREATE TABLE produkte ( produkt_nr integer. preis numeric. preis numeric ). dass die Spalte nur den NULL-Wert akzeptiert. wo Sie es wünschen. in einer Textdatei den Sinn des Constraint umzukehren. Unique Constraints stellen sicher. b integer. Wenn sich ein Unique Constraint auf eine Gruppe von Spalten bezieht. (Er würde nur in PostgreSQL eingebaut. UNIQUE (a. was ziemlich sinnlos wäre. dass die Daten einer Spalte oder einer Gruppe von Spalten von allen anderen Zeilen der Tabelle voneinander verschieden sind. 73 . UNIQUE (produkt_nr) ).) Einige Benutzer mögen diesen Constraints allerdings. weil er es erleichtert. dass eine Spalte den NULL-Wert aufnehmen darf. Der NULL-Constraint ist im SQLStandard nicht definiert und sollte in portierbaren Anwendungen nicht verwendet werden. um mit anderen Datenbanksystemen kompatibel zu sein.Datendefinition Der NOT-NULL-Constraint hat eine Umkehrung: den NULL-Constraint.4. und dann fügen Sie einfach daas Schlüsselwort NOT dort ein. Vielmehr drückt er einfach den Normalzustand aus. name text. wenn man es als Spalten-Constraint schreibt. Die Syntax ist CREATE TABLE produkte ( produkt_nr integer UNIQUE. name text NULL. preis numeric NULL ). c) ). Sie könnten zum Beispiel mit dieser Textdatei anfangen: CREATE TABLE produkte ( produkt_nr integer NULL. wenn man es als Tabellen-Constraint schreibt.

Kapitel 5

Man kann Unique Constraints auch Namen zuweisen:
CREATE TABLE produkte ( produkt_nr integer CONSTRAINT müssen_verschieden_sein UNIQUE, name text, preis numeric );

Generell ist ein Unique Constraint verletzt, wenn es (mindestens) zwei Zeilen in der Tabelle gibt, wo die Werte der einander entsprechenden Spalten, die Teil des Constraints sind, gleich sind. NULL-Werte werden hier allerdings nicht als gleich erachtet. Das bedeutet, dass man trotz eines mehrspaltigen Unique Constraints eine unbegrenzte Anzahl Zeilen erzeugen kann, in denen mindestens eine der beschränkten Spalten den NULL-Wert hat. Dieses Verhalten entspricht dem SQL-Standard, aber wir haben vernommen, dass einige SQL-Datenbanken dieser Regel wohl nicht folgen. Also seien Sie vorsichtig, wenn Sie Anwendungen entwickeln, die portierbar sein sollen.

5.4.4

Primärschlüssel

Technisch gesehen ist ein Primärschlüssel-Constraint (englisch primary key) einfach eine Kombination aus Unique Constraint und NOT-NULL-Constraint. Die folgenden beiden Tabellendefinitionen können also die gleichen Daten aufnehmen:
CREATE TABLE produkte ( produkt_nr integer UNIQUE NOT NULL, name text, preis numeric ); CREATE TABLE produkte ( produkt_nr integer PRIMARY KEY, name text, preis numeric );

Primärschlüssel können auch über mehrere Spalten gehen; die Syntax ist ähnlich der des Unique Constraints:
CREATE TABLE beispiel ( a integer, b integer, c integer, PRIMARY KEY (a, c) );

Ein Primärschlüssel zeigt an, dass eine Spalte oder eine Gruppe von Spalten als eindeutige Identifikation einer Zeile in der Tabelle verwendet werden kann. (Das ist eine direkte Folge aus der Definition des Primärschlüssels. Beachten Sie, dass ein Unique Constraint keine eindeutige Identifikation erlaubt, da er NULL-Werte nicht ausschließt.) Das ist sowohl zu Zwecken der Dokumentation der Datenbankstruktur als auch für Clientanwendungen nützlich. Wenn zum Beispiel eine grafische Anwendung es Ihnen erlaubt, Zeilen zu verändern, dann muss diese Anwendung höchstwahrscheinlich den Primärschlüssel der Tabelle kennen, um die Zeilen eindeutig identifizieren zu können.

74

Datendefinition

Eine Tabelle kann höchstens einen Primärschlüssel haben (aber sie kann mehrere Unique- und NOTNULL-Constraints haben). Die Theorie der relationalen Datenbanken schreibt vor, dass jede Tabelle einen Primärschlüssel haben muss. Diese Regel wird von PostgreSQL nicht durchgesetzt, aber es ist meistens am besten, ihr zu folgen.

5.4.5

Fremdschlüssel

Ein Fremdschlüssel-Constraint (englisch foreign key) gibt an, dass die Werte in einer Spalte (oder einer Gruppe von Spalten) mit den Werten in irgendeiner Zeile in einer anderen Tabelle übereinstimmen müssen. Man sagt, dass dadurch die referenzielle Integrität zwischen zwei zusammenhängenden Tabellen gesichert wird. Nehmen wir die Produkttabelle, die wir schon mehrere Male verwendet haben:
CREATE TABLE produkte ( produkt_nr integer PRIMARY KEY, name text, preis numeric );

Nehmen wir ferner an, dass Sie eine Tabelle haben, die Bestellungen dieser Produkte speichert. Wir wollen sichergehen, dass die Bestellungstabelle nur Bestellungen von tatsächlich existierenden Produkten aufnimmt. Also definieren wir einen Fremdschlüssel-Constraint in der Bestellungstabelle, der sich auf die Produkttabelle bezieht:
CREATE TABLE bestellungen ( bestell_nr integer PRIMARY KEY, produkt_nr integer REFERENCES produkte (produkt_nr), menge integer );

Jetzt ist es unmöglich, Bestellungen mit produkt_nr-Einträgen zu erzeugen, die nirgendwo in der Produkttabelle auftauchen. Bei dieser Gliederung sagt man, dass die Tabelle bestellungen auf die Tabelle produkte verweist. Genauso verweisen auch die Spalten aufeinander. Der obige Befehl kann auch abgekürzt werden:
CREATE TABLE bestellungen ( bestell_nr integer PRIMARY KEY, produkt_nr integer REFERENCES produkte, menge integer );

Wenn die Spaltenliste ausgelassen wird, dann wird der Primärschlüssel der Tabelle, auf die man verweist, als Zielspalte verwendet. Ein Fremdschlüssel kann auch eine Gruppe von Spalten beschränken bzw. auf eine Gruppe von Spalten verweisen. Er muss dann wie gewohnt als Tabellen-Constraint geschrieben werden. Hier ist ein bedeutungsloses Syntaxbeispiel:
CREATE TABLE t1 ( a integer PRIMARY KEY,

75

Kapitel 5

b integer, c integer, FOREIGN KEY (b, c) REFERENCES andere_tabelle (c1, c2) );

Die Zahl und der Typ der beschränkten Spalten muss natürlich mit der Zahl und dem Typ der Spalten übereinstimmen, auf die man verweist. Eine Tabelle kann mehrere Fremdschlüssel-Constraints enthalten. Diese Fähigkeit verwendet man, um so genannte m:n-Beziehungen (viele-zu-viele) zwischen Tabellen umzusetzen. Nehmen wir an, Sie haben Tabellen mit Produkten und mit Bestellungen, aber jetzt wollen Sie auch zulassen, dass eine Bestellung mehrere Produkte aufnehmen kann (was in der oben verwendeten Struktur nicht möglich war). Dazu könnten Sie folgende Tabellenstruktur verwenden:
CREATE TABLE produkte ( produkt_nr integer PRIMARY KEY, name text, preis numeric ); CREATE TABLE bestellungen ( bestell_nr integer PRIMARY KEY, lieferadresse text, ... ); CREATE TABLE bestell_artikel ( produkt_nr integer REFERENCES produkte, bestell_br integer REFERENCES bestellungen, menge integer, PRIMARY KEY (produkt_nr, bestell_nr) );

Sie werden auch bemerken, dass sich in der letzten Tabelle der Primärschlüssel mit den Fremdschlüsseln überschneidet. Wir haben jetzt erreicht, dass die Fremdschlüssel das Erzeugen von Bestellungen, die zu keinen Produkten passen, verhindern. Aber was passiert, wenn ein Produkt gelöscht wird, während noch eine Bestellung darauf verweist? In SQL können Sie auch das angeben. Intuitiv haben wir einige Möglichkeiten: ❏ das Löschen des Produktes verhindern ❏ die Bestellungen ebenso löschen ❏ Noch etwas? Um dies zu erklären, setzen wir folgende Regeln am obigen m:n-Beispiel um: Wenn jemand ein Produkt entfernen möchte, das noch in einer Bestellung verwendet wird (über bestell_artikel), wird das verboten. Wenn jemand eine Bestellung entfernt, dann werden die Bestellartikel auch gelöscht.
CREATE TABLE produkte ( produkt_nr integer PRIMARY KEY, name text, preis numeric

76

Datendefinition

); CREATE TABLE bestellungen ( bestell_nr integer PRIMARY KEY, lieferadresse text, ... ); CREATE TABLE bestell_artikel ( produkt_nr integer REFERENCES produkte ON DELETE RESTRICT, bestell_nr integer REFERENCES bestellungen ON DELETE CASCADE, menge integer, PRIMARY KEY (produkt_nr, bestell_nr) ); RESTRICT steht für “einschränken”, also faktisch verbieten; CASCADE bedeutet, dass die jeweilige Aktion auch in den anderen Tabellen durchgeführt wird. (Für cascade lässt sich kaum eine gute deutsche Übersetzung finden. Das Wort steht eigentlich für eine Reihe kleinerer, zusammenhängender Wasserfälle.) RESTRICT und CASCADE sind die zwei am häufigsten verwendeten Möglichkeiten. RESTRICT kann auch als NO ACTION geschrieben werden und ist auch die Vorgabe, wenn Sie gar nichts schreiben. Es gibt zwei weitere Möglichkeiten, was mit den Fremdschlüsselspalten passieren soll, wenn ein Primärschlüssel gelöscht wird: SET NULL (auf den NULL-Wert setzen) und SET DEFAULT (auf den Vorgabewert setzen). Beachten Sie, dass dadurch aber keine anderen Constraints umgangen werden können. Wenn zum Beispiel SET DEFAULT angegeben ist, aber der Vorgabewert den Fremdschlüssel-Constraint verletzen würde, dann wird das Löschen des Primärschlüssels fehlschlagen.

Analog zu ON DELETE gibt es auch noch ON UPDATE, womit bestimmt wird, was passiert, wenn ein Primärschlüssel aktualisiert wird (englisch update). Die möglichen Aktionen sind dieselben. Weitere Informationen über das Aktualisieren und das Löschen von Daten finden Sie in Kapitel 6. Am Schluss sollten wir noch erwähnen, dass ein Fremdschlüssel immer auf Spalten verweisen muss, die entweder einen Primärschlüssel oder einen Unique Constraint bilden. Wenn ein Fremdschlüssel auf einen Unique Constraint verweist, gibt es noch einige weitere Möglichkeiten, wie NULL-Werte verarbeitet werden. Diese sind in Teil VI im Eintrag für CREATE TABLE erläutert.

5.5

Tabellen verändern

Wenn Sie eine Tabelle erzeugen und feststellen, dass sie einen Fehler gemacht haben oder wenn sich die Anforderungen an Ihre Anwendung verändert haben, dann können Sie die Tabelle entfernen und neu erzeugen. Aber das ist keine passable Lösung, wenn die Tabelle bereits mit Daten gefüllt ist oder wenn die Tabelle von anderen Datenbankobjekten benötigt wird (zum Beispiel von einem Fremdschlüssel). Deswegen hat PostgreSQL eine Sammlung von Befehlen, um Änderungen an bestehenden Tabellen vorzunehmen. Sie können ❏ ❏ ❏ ❏ ❏ Spalten hinzufügen, Spalten entfernen, Constraints hinzufügen, Constraints entfernen, Vorgabewerte ändern,

77

Kapitel 5 ❏ Spalten umbenennen, ❏ Tabellen umbenennen. Die Aktionen werden alle mit dem Befehl ALTER TABLE vorgenommen.

5.5.1

Eine Spalte hinzufügen

Um eine Spalte hinzuzufügen, verwenden Sie diesen Befehl:
ALTER TABLE produkte ADD COLUMN beschreibung text;

Die neue Spalte wird in den bestehenden Zeilen anfänglich mit NULL-Werten gefüllt. Sie können für die Spalte auch gleich einen Constraint mit definieren, indem Sie die bekannte Syntax verwenden:
ALTER TABLE produkte ADD COLUMN beschreibung text CHECK (beschreibung <> '');

Eine neue Spalte kann keinen NOT-NULL-Constraint haben, da die Spalte anfänglich NULL-Werte enthalten muss. Aber Sie können einen NOT-NULL-Constraint später hinzufügen. Eine neue Spalte kann auch keinen Vorgabewert haben. Dem SQL-Standard nach müsste dann die neue Spalte in den bestehenden Zeilen auf dem Vorgabewert gesetzt werden, was so noch nicht umgesetzt ist. Aber Sie können den Vorgabewert immer noch nachher ändern.

5.5.2

Eine Spalte entfernen

Um eine Spalte zu entfernen, verwenden Sie diesen Befehl:
ALTER TABLE produkte DROP COLUMN beschreibung;

5.5.3

Einen Constraint hinzufügen

Um einen Constraint hinzuzufügen, verwenden Sie die Syntax für Tabellen-Constraints. Zum Beispiel:
ALTER TABLE produkte ADD CHECK (name <> ''); ALTER TABLE produkte ADD CONSTRAINT irgendein_name UNIQUE (produkt_nr); ALTER TABLE produkte ADD FOREIGN KEY (produktgruppen_nr) REFERENCES produktgruppen;

Um einen NOT-NULL-Constraint, der ja nicht als Tabellen-Constraint geschrieben werden kann, hinzuzufügen, verwenden Sie diese Syntax:
ALTER TABLE produkte ALTER COLUMN produkt_nr SET NOT NULL;

Der neue Constraint wird sofort geprüft, also muss die Tabelle den Constraint erfüllen, bevor dieser erstellt werden kann.

5.5.4

Einen Constraint entfernen

Um einen Constraint entfernen zu können, müssen Sie seinen Namen kennen. Wenn Sie ihm einen Namen gegeben hatten, dann ist das ganz einfach. Ansonsten hat das System einen Namen erzeugt, den

78

Datendefinition

Sie herausfinden müssen. Der psql-Befehl \d tabellenname kann hier helfen; andere Schnittstellen haben möglicherweise auch Wege, um sich die Tabellendaten anzusehen. Der Befehl ist dann: ALTER TABLE produkte CONSTRAINT irgendein_name;
DROP

Das funktioniert bei allen Constraint-Typen außer NOT-NULL-Constraints. Um einen NOT-NULL-Constraint zu entfernen, verwenden Sie
ALTER TABLE produkte ALTER COLUMN produkt_nr DROP NOT NULL;

(Erinnern Sie sich, dass NOT-NULL-Constraints keine Namen haben.)

5.5.5

Den Vorgabewert ändern

Um einer Spalte einen neuen Vorgabewert zuzuweisen, verwenden Sie einen Befehl wie diesen:
ALTER TABLE produkte ALTER COLUMN preis SET DEFAULT 7.77;

Um einen Vorgabewert zu entfernen, verwenden Sie
ALTER TABLE produkte ALTER COLUMN preis DROP DEFAULT;

Das hat die gleiche Bedeutung, als wenn man den Vorgabewert auf den NULL-Wert setzt, zumindest in PostgreSQL. Daraus folgt, dass es kein Fehler ist, einen Vorgabewert zu entfernen, wo keiner definiert war, weil der Vorgabewert automatisch der NULL-Wert ist.

5.5.6

Eine Spalte umbenennen

Der Befehl, um eine Spalte umzubenennen, ist:
ALTER TABLE produkte RENAME COLUMN produkt_nr TO produktnummer;

5.5.7

Eine Tabelle umbenennen

Der Befehl, um eine Tabelle umzubenennen, ist:
ALTER TABLE produkte RENAME TO artikel;

5.6

Privilegien

Wenn Sie ein Datenbankobjekt erzeugen, sind Sie sein Eigentümer. In der Ausgangslage kann nur der Eigentümer eines Objekts etwas damit machen. Um anderen Benutzern die Verwendung zu erlauben, müssen Sie Privilegien erteilen. (Es gibt auch Benutzer, die das Superuser-Privileg haben. Diese Benutzer können immer auf alle Objekte zugreifen.) Es gibt mehrere verschiedene Privilegien: SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCES, TRIGGER, CREATE, TEMPORARY, EXECUTE, USAGE und ALL PRIVILEGES. Vollständige Informationen

79

Kapitel 5

Anmerkung
Um den Eigentümer einer Tabelle, eines Index, einer Sequenz oder einer Sicht zu ändern, verwenden Sie den Befehl ALTER TABLE. über die verschiedenen Privilegientypen, die von PostgreSQL unterstützt werden, finden auf der GRANTReferenzseite. Die folgenden Abschnitte und Kapitel werden Ihnen auch zeigen, wie die Privilegien verwendet werden. Das Recht, ein Objekt zu verändern oder zu entfernen, ist immer das ausschließliche Privileg des Eigentümers. Um Privilegien zu gewähren, wird der Befehl GRANT verwendet. Wenn also fred ein bestehender Benutzer ist und konten eine vorhandene Tabelle, dann kann das Privileg, die Tabelle aktualisieren zu dürfen, folgendermaßen gewährt werden:
GRANT UPDATE ON konten TO fred;

Der Benutzer, der diesen Befehl ausführt, muss der Eigentümer der Tabelle sein. Um das Privileg einer Gruppe zu gewähren, verwenden Sie
GRANT SELECT ON konten TO GROUP innendienst;

Der spezielle “Benutzername” PUBLIC kann verwendet werden, um ein Privileg allen Benutzern im System zu gewähren. Wenn Sie ALL anstelle der einzelnen Privilegien schreiben, dann werden alle Arten von Privilegien gewährt. Um ein Privileg zu entziehen, verwenden Sie den Befehl REVOKE:
REVOKE ALL ON konten FROM PUBLIC;

Die besonderen Privilegien des Eigentümers (das heißt, das Recht, DROP, GRANT, REVOKE usw. auszuführen) sind dem Eigentümer immer automatisch gewährt und können nicht weitergegeben oder entzogen werden. Ein Tabelleneigentümer kann allerdings seine eigenen normalen Privilegien entziehen, um zum Beispiel zu verhindern, dass er aus Versehen in die Tabelle schreibt.

5.7

Schemas

Ein PostgreSQL-Datenbankcluster enthält eine oder mehrere benannte Datenbanken. Benutzerkonten und Gruppenkonten sind im gesamten Cluster verfügbar, aber weitere Daten haben die Datenbanken nicht gemeinsam. Jede Verbindung eines Clients kann nur auf eine einzige Datenbank zugreifen, nämlich die, die in der Verbindungsanfrage angegeben wurde.

Anmerkung
Die Benutzer eines Clusters haben nicht unbedingt das Privileg, auf jede Datenbank in dem Cluster zuzugreifen. Dass die Benutzerkonten in allen Datenbanken gelten, heißt, dass es keine unterschiedlichen Benutzer, sagen wir mit Namen fred, in zwei Datenbanken des Clusters geben kann, aber das System kann so eingestellt werden, dass fred nur auf einige Datenbanken Zugriff hat. Eine Datenbank enthält ein oder mehrere Schemas, welche wiederum Tabellen enthalten. Schemas enthalten auch andere Arten von Objekten, einschließlich Typen, Funktionen und Operatoren. Der gleiche Objektname kann in verschiedenen Schemas verwendet werden, ohne einen Konflikt zu erzeugen; zum Beispiel können sowohl schema1 also auch meinschema Tabellen namens meinetabelle enthalten. Im

80

Datendefinition

Gegensatz zu Datenbanken sind Schemas nicht strikt voneinander getrennt: Ein Benutzer kann auf Objekte in allen Schemas in der Datenbank, mit der er verbunden ist, zugreifen, vorausgesetzt, er hat die Privilegien dazu. Es gibt mehrere Gründe, warum Sie Schemas vielleicht verwenden wollen: ❏ um es mehreren Benutzern zu gestatten, eine Datenbank zu verwenden, ohne sich gegenseitig zu stören ❏ um Datenbankobjekte in logische Gruppen aufzuteilen, um sie besser verwalten zu können. ❏ Anwendungen von Fremdanbietern können in getrennten Schemas abgelegt werden, damit sie keine Konflikte mit den Namen anderer Objekte verursachen. Schemas entsprechen Verzeichnissen auf Betriebssystemebene, außer dass man Schemas nicht verschachteln kann.

5.7.1

Ein Schema erzeugen

Um ein getrenntes Schema zu erzeugen, verwenden Sie den Befehl CREATE SCHEMA. Geben Sie dem Schema einen Namen Ihrer Wahl. Zum Beispiel:
CREATE SCHEMA meinschema;

Um ein Objekt in einem Schema zu erzeugen oder auf eines zuzugreifen, schreiben Sie einen qualifizierten Namen, welcher aus dem Schemanamen und dem Tabellennamen, getrennt von einem Punkt, besteht:
schema.tabelle

Die noch allgemeinere Syntax datenbank.schema.tabelle kann im Prinzip auch verwendet werden, was aber gegenwärtig nur zur Pro-forma-Übereinstimmung mit dem SQL-Standard vorgesehen ist. Wenn Sie einen Datenbanknamen angeben, muss das der Name der Datenbank sein, mit der Sie gerade verbunden sind. Um also eine Tabelle in dem neuen Schema zu erzeugen, verwenden Sie
CREATE TABLE meinschema.meinetabelle ( ... );

Das funktioniert überall, wo ein Tabellenname erwartet wird, einschließlich der Tabellenmodifikationsbefehle und der Datenzugriffsbefehle, die in den folgenden Kapiteln besprochen werden. Um ein Schema zu entfernen, wenn es leer ist (alle darin enthaltenen Objekte sind gelöscht worden), verwenden Sie
DROP SCHEMA meinschema;

Um ein Schema einschließlich aller darin enthaltenen Objekte zu löschen, verwenden Sie
DROP SCHEMA meinschema CASCADE;

Abschnitt 5.9 beschreibt den Mechanismus, der dieser Aktion zugrunde liegt. Oft werden Sie ein Schema, das jemandem anderen gehören soll, erstellen wollen (da dies eine Möglichkeit ist, die Aktivitäten Ihrer Benutzer auf bestimmte Namensräume zu beschränken). Die Syntax dafür ist: 81

Kapitel 5

CREATE SCHEMA schemaname AUTHORIZATION benutzername;

Sie können den Schemanamen auch auslassen, wodurch der Schemaname mit dem Benutzernamen gleichgesetzt wird. In Abschnitt 5.7.6 werden Sie sehen, wie nützlich das sein kann. Schemanamen, die mit pg_ beginnen, sind für Systemaufgaben reserviert und können von Benutzern nicht erzeugt werden.

5.7.2

Das Schema public

In den vorangegangenen Abschnitten haben wir Tabellen erzeugt, ohne einen Schemanamen anzugeben. Solche Tabellen (und andere Objekte) werden in der Voreinstellung automatisch in einem Schema namens public abgelegt. Jede neue Datenbank enthält so ein Schema. Die folgenden Befehle sind also gleichbedeutend:
CREATE TABLE produkte ( ... );

und
CREATE TABLE public.produkte ( ... );

5.7.3

Der Schema-Suchpfad

Qualifizierte Namen zu schreiben kann, lästig werden und oft ist es auch besser, die Schemanamen nicht fest in eine Anwendung einzubauen. Deshalb schreibt man Tabellennamen oft als unqualifizierte Namen, welche einfach aus dem Tabellennamen bestehen. Das System ermittelt, welche Tabelle gemeint ist, indem es dem Suchpfad folgt. Der Suchpfad ist eine Liste von Schemas, in der das System nachschauen soll. Die erste passende Tabelle, die im Suchpfad gefunden wurde, wird verwendet. Wenn es keine passende Tabelle im Suchpfad gibt, dann wird ein Fehler erzeugt, selbst wenn es passende Tabellennamen in anderen Schemas der Datenbank gibt. Das erste Schema, das im Suchpfad steht, wird als das aktuelle Schema bezeichnet. Es ist nicht nur das erste Schema, das durchsucht wird, sondern dort werden auch neue mit CREATE TABLE erzeugte Tabellen abgelegt, wenn der Befehl keinen Schemanamen angibt. Um den aktuellen Schemasuchpfad anzuzeigen, verwenden Sie folgenden Befehl:
SHOW search_path;

In der Voreinstellung ergibt das:
search_path -------------$user,public

Das erste Element gibt an, dass ein Schemaname mit dem gleichen Namen wie der aktuelle Benutzer zu durchsuchen ist. Da ein solches Schema noch nicht existiert, wird dieser Eintrag ignoriert. Das zweite Element bezieht sich auf das bereits gesehene Schema public. Das erste Schema im Suchpfad, das tatsächlich existiert, ist das Schema, wo neue Objekte erstellt werden, wenn kein anderes Schema ausdrücklich angegeben ist. Deshalb werden Objekte in der Voreinstellung im Schema public erstellt. Wenn ein Objekt in einem anderen Zusammenhang (Tabellenveränderung, Datenmodifikation, Anfragebefehl) ohne Schemaqualifikation verwendet wird, dann wird der Suchpfad abgesucht, bis ein passendes Objekt gefunden wurde. Deshalb können unqualifizierte Namen in den Voreinstellungen auch nur auf das Schema public zugreifen. 82

Datendefinition

Um unser neues Schema in den Pfad zu setzen, verwenden wir
SET search_path TO meinschema,public;

(Wir haben $user hier ausgelassen, weil wir es gegenwärtig nicht brauchen.) Danach können wir auf die Tabelle ohne Qualifikation zugreifen:
DROP TABLE meinetabelle;

Da meinschema auch das erste Element im Pfad ist, würden dort neue Objekte erstellt werden, wenn kein anderes Schema angegeben wird. Wir hätten auch schreiben können
SET search_path TO meinschema;

Dann hätten wir keinen Zugriff auf das Schema public mehr gehabt, ohne es ausdrücklich zu nennen. Das Schema public ist nichts Besonderes, außer dass es in der Ausgangskonfiguration schon vorhanden ist. Sie können es auch ganz entfernen. In Abschnitt 9.13 finden Sie auch noch weitere Möglichkeiten, um auf den Schemasuchpfad zuzugreifen. Der Suchpfad funktioniert auf die gleiche Art und Weise für Datentypnamen, Funktionsnamen und Operatornamen, wie er für Tabellennamen funktioniert. Die Namen von Datentypen und Funktionen können auf die gleiche Art qualifiziert werden wie Tabellennamen. Wenn Sie in einem Ausdruck einen qualifizierten Operatornamen schreiben müssen, dann gibt es eine Sonderregel: Sie müssen schreiben
OPERATOR(schema.operator)

Das ist erforderlich, um syntaktische Zweideutigkeiten auszuschließen. Ein Beispiel wäre SELECT 3 OPERATOR(pg_catalog.+) 4; In der Praxis verwendet man normalerweise den Suchpfad für Operatoren, damit man nicht so etwas Umständliches schreiben muss.

5.7.4

Schemas und Privilegien

In der Voreinstellung kann ein Benutzer die Objekte in Schemas, die ihm nicht gehören, nicht sehen. Um das zu erlauben, muss der Eigentümer des Schemas das Privileg USAGE gewähren. Um den anderen Benutzern auch zu erlauben, die Objekte in dem Schema zu verwenden, müssen eventuell noch weitere Privilegien gewährt werden, je nach Objekttyp. Man kann einem Benutzer auch gestatten, Objekte im Schema von jemand anderem zu erzeugen. Um das zu erlauben, muss das Privileg CREATE für das Schema gewährt werden. Beachten Sie, dass in der Voreinstellung jeder das CREATE-Privileg für das Schema public hat. Das ermöglicht allen Benutzern, die es schaffen, sich mit einer bestimmten Datenbank zu verbinden, dort Objekte zu erzeugen. Wenn Sie das nicht gestatten wollen, dann können Sie das Privileg entziehen:
REVOKE CREATE ON public FROM PUBLIC;

(Das erste public ist das Schema, das zweite public bedeutet “alle Benutzer”. Im ersten Sinne ist es ein Name, im zweiten Sinne ist es ein Schlüsselwort, daher die unterschiedliche Schreibung. Erinnern Sie sich an die Richtlinien aus Abschnitt 4.1.1.)

83

Kapitel 5

5.7.5

Das Systemkatalogschema

Neben public und benutzerdefinierten Schemas enthält jede Datenbank ein Schema namens pg_catalog, welches die Systemtabellen und die eingebauten Datentypen, Funktionen und Operatoren enthält. pg_catalog ist immer automatisch Teil des Suchpfads. Wenn es im Pfad nicht ausdrücklich erwähnt wird, dann wird es automatisch vor den Schemas im Pfad durchsucht. Damit wird sichergestellt, dass die eingebauten Namen im auffindbar sind. Sie können pg_catalog allerdings ausdrücklich ans Ende Ihres Suchpfads setzen, wenn Sie möchten, dass benutzerdefinierte Namen vor den eingebauten Vorrang haben. In PostgreSQL-Versionen vor 7.3 waren Tabellennamen, die mit pg_ anfangen, reserviert. Das ist nicht mehr der Fall: Sie können solche Tabellen erzeugen, wenn Sie wünschen, außer im Systemkatalogschema. Es ist allerdings besser, solche Namen weiterhin zu vermeiden, damit auch in der Zukunft keine Konflikte entstehen, wenn einmal eine neue Systemtabelle den gleichen Namen wie eine Ihrer Tabellen haben sollte. (Mit dem voreingestellten Suchpfad würde sich ein unqualifizierter Verweis auf Ihren Tabellennamen in Wahrheit auf die Systemtabelle beziehen.) Die Systemtabellen werden weiterhin Namen haben, die mit pg_ beginnen, und somit keine Konflikte mit benutzerdefinierten Namen verursachen, wenn der Präfix pg_ von Benutzern vermieden wird.

5.7.6

Verwendungsmöglichkeiten

Mit Schemas können Sie Ihren Daten auf viele Arten organisieren. Es gibt einige Verwendungsmöglichkeiten, die empfehlenswert und mit den Voreinstellungen einfach umzusetzen sind: ❏ Wenn Sie keine Schemas erzeugen, greifen alle Benutzer automatisch auf das Schema public zu. Dadurch simulieren Sie eine Umgebung, in der gar keine Schemas vorhanden sind. Diese Gliederung ist hauptsächlich zu empfehlen, wenn Sie nur einen einzigen oder einige wenige zusammen arbeitende Benutzer haben. Mit diesen Einstellungen können Sie auch den Übergang von einer Umgebung ohne Schemas in eine Umgebung mit Schemas problemlos bewältigen. ❏ Sie können für jeden Benutzer ein Schema mit dem gleichen Namen wie der Benutzer erzeugen. Erinnern Sie sich zurück, dass der voreingestellte Suchpfad mit $user anfängt, was für den aktuellen Benutzernamen steht. Wenn also jeder Benutzer ein eigenes Schema hat, dann greift automatisch jeder auf sein eigenes zu. ❏ Wenn Sie diese Gliederung verwenden, sollten Sie vielleicht auch den Zugriff auf das Schema public entziehen (oder es gleich ganz löschen), damit die Benutzer wirklich auf ihr eigenes Schema beschränkt werden. ❏ Um Anwendungen zu installieren, die von allen verwendet werden können (zum Beispiel gemeinsame Tabellen oder zusätzliche Funktionen von Fremdanbietern), legen Sie sie in getrennten Schemas ab. Vergessen Sie nicht, die passenden Privilegien zu gewähren, damit andere Benutzer darauf Zugriff haben. Die Benutzer können dann auf diese Objekte zugreifen, indem Sie qualifizierte Namen schreiben, oder Sie können die zusätzlichen Schemas in ihren Pfad aufnehmen, je nachdem, wie sie es wünschen.

5.7.7

Portierbarkeit

Im SQL-Standard ist die Vorstellung, das Objekte im gleichen Schema verschiedene Eigentümer haben können, nicht vorhanden. Außerdem gestatten es einige Systeme nicht, Schemas zu erzeugen, deren Name nicht mit dem Name des Eigentümers übereinstimmt. Tatsächlich sind die Begriffe Schema und Benutzer in Datenbanksystemen, die nur die einfachste Schemaunterstützung, die im Standard vorgesehen ist, anbieten, nahezu gleichbedeutend. Deshalb denken viele Benutzer, dass qualifizierte Namen in Wirklichkeit so aussehen: benutzername.tabellenname. So verhält sich PostgreSQL im Endeffekt auch, wenn Sie für jeden Benutzer ein eigenes Schema erzeugen. Ferner ist darauf hinzuweisen, dass im SQL-Standard kein Schema public vorgesehen ist. Um dem Standard so weit wie möglich zu folgen, sollten Sie das Schema public nicht verwenden (und vielleicht sogar löschen). 84

Datendefinition

Natürlich bieten womöglich manche SQL-Datenbanksysteme Schemas gar nicht an oder sie erlauben die Aufteilung der Objekte in Namensräume, indem sie (möglicherweise eingeschränkten) Zugriff auf mehrere Datenbanken gleichzeitig erlauben. Wenn Sie mit solchen Systemen zusammenarbeiten müssen, erreichen Sie die beste Portierbarkeit, wenn Sie Schemas gar nicht verwenden.

5.8

Andere Datenbankobjekte

Tabellen sind die zentralen Objekte einer relationalen Datenbankstruktur, weil sie es sind, die Ihre Daten enthalten. Aber sie sind nicht die einzige Art von Objekt, dass in einer Datenbank zu finden ist. Viele andere Arten von Objekten können erzeugt werden, um die Verwendung und Verwaltung der Daten effizienter und bequemer zu gestalten. Diese werden in diesem Kapitel nicht besprochen, aber wir führen Sie hier auf, um Ihnen zu zeigen, was möglich ist. ❏ Sichten ❏ Funktionen, Operatoren, Datentypen, Domänen ❏ Trigger und Umschreiberegeln (Rules)

5.9

Verfolgung von Abhängigkeiten

Wenn Sie komplexe Datenbankstrukturen aus vielen Tabellen mit Fremdschlüsseln, Sichten, Triggern, Funktionen usw. erzeugen, dann erzeugen Sie automatisch ein Netz von Abhängigkeiten zwischen den Objekten. Eine Tabelle mit einem Fremdschlüssel ist zum Beispiel von der Tabelle abhängig, auf die der Fremdschlüssel verweist. Um die Integrität der gesamten Datenbankstruktur abzusichern, verhindert PostgreSQL, dass Sie Objekte entfernen, von denen andere Objekte abhängen. Wenn Sie zum Beispiel die Produkttabelle, die wir in Abschnitt 5.4.5 betrachtet hatten, entfernen wollen und die Bestellungstabelle ist noch von ihr abhängig, dann würde das eine Fehlermeldung wie diese verursachen:
DROP TABLE produkte; NOTICE: constraint $1 on table bestellungen depends on table produkte ERROR: Cannot drop table produkte because other objects depend on it Use DROP ... CASCADE to drop the dependent objects too

Diese Fehlermeldung enthält einen nützlichen Hinweis in der letzten Zeile: Wenn Sie die anhängigen Objekte nicht alle einzeln entfernen wollen, können Sie
DROP TABLE produkte CASCADE;

ausführen und die anhängigen Objekte werden mit entfernt. In diesem Fall wird die Bestellungstabelle dadurch nicht gelöscht, sondern nur der Fremdschlüssel-Constraint. (Wenn Sie überprüfen wollen, was DROP ... CASCADE für Auswirkungen haben würde, dann führen Sie DROP ohne CASCADE aus und lesen Sie die NOTICE-Mitteilungen.) Alle DROP-Befehle in PostgreSQL unterstützen die CASCADE-Option. Die Art der möglichen Abhängigkeiten ist natürlich bei jedem Objekttyp verschieden. Sie können statt CASCADE auch RESTRICT schreiben, um das normale Verhalten zu erreichen, welches das Entfernen von Objekten mit Abhängigkeiten verhindert.

85

Kapitel 5

Anmerkung
Laut SQL-Standard muss entweder RESTRICT oder CASCADE immer angegeben werden. Es gibt kein Datenbanksystem, das dies wirklich verlangt, aber es ist unterschiedlich, ob das Normalverhalten RESTRICT oder CASCADE entspricht.

Anmerkung
Abhängigkeiten von Fremdschlüsseln und Spalten vom Typ serial aus PostgreSQL-Versionen vor 7.3 werden im Upgrade-Prozess nicht erhalten oder erzeugt. Alle anderen Abhängigkeiten werden beim Upgrade ordnungsgemäß erstellt.

86

6

6

Datenmanipulation

Im vorangegangenen Kapitel haben wir besprochen, wie man Tabellen und andere Strukturen erzeugt, um Ihre aufzunehmen. Jetzt ist es an der Zeit, die Tabellen mit Daten zu füllen. Dieses Kapitel behandelt, wie man Tabellendaten einfügt, aktualisiert und löscht. Wir werden auch Wege vorstellen, wie man automatische Datenmanipulationen verursachen kann, wenn bestimmte Ereignisse auftreten: Trigger und Umschreiberegeln. Das Kapitel nach diesem wird dann endlich erklären, wie Sie Ihre lange verschollenen Daten wieder aus der Datenbank herausbekommen.

6.1

Daten einfügen

Wenn eine Tabelle erzeugt wird, enthält sie keine Daten. Das Erste, was man machen muss, bevor eine Datenbank von Nutzen sein kann, ist Daten einzufügen. Daten werden Zeile für Zeile eingefügt. Natürlich können Sie auch mehrere Zeilen einfügen, aber es ist nicht möglich, weniger als eine Zeile einzufügen. Selbst wenn Sie nur einige Spaltenwerte wissen, müssen Sie eine ganze Zeile erzeugen. Um eine neue Zeile einzufügen (englisch insert), verwenden Sie den Befehl INSERT. Dieser Befehl benötigt den Namen der Tabelle und Werte für jede der Spalten in der Tabelle. Betrachten Sie zum Beispiel die Produkttabelle ausKapitel 5:
CREATE TABLE produkte ( prodult_nr integer, name text, preis numeric );

Ein Beispielbefehl, um eine Zeile einzufügen, wäre:
INSERT INTO produkte VALUES (1, 'Käse', 9.99);

Die Werte werden in der Reihenfolge aufgelistet, in der die Spalten in der Tabelle angeordnet sind, und werden durch Kommas getrennt. Meistens werden die Werte Konstante sein, aber Wertausdrücke sind auch zulässig.

87

Kapitel 6

Die obige Syntax hat den Nachteil, dass man die Reihenfolge der Spalten in der Tabelle kennen muss. Um das zu vermeiden, können Sie die Spalten auch ausdrücklich aufzählen. Zum Beispiel haben beide der folgenden Befehle die gleiche Wirkung wie der obige:
INSERT INTO produkte (produkt_nr, name, preis) VALUES (1, 'Käse', 9.99); INSERT INTO produkte (name, preis, produkt_nr) VALUES ('Käse', 9.99, 1);

Viele Benutzer halten es für empfehlenswert, die Spalten immer aufzulisten. Wenn Sie nicht für alle Spalten Werte haben, können Sie einige auslassen. In diesem Fall werden die Spalten mit ihren Vorgabewerten gefüllt. Zum Beispiel:
INSERT INTO produkte (produkt_nr, name) VALUES (1, 'Käse'); INSERT INTO produkte VALUES (1, 'Käse');

Die zweite Form ist eine Erweiterung von PostgreSQL. Sie füllt die Spalten von links mit so vielen Werten auf, wie angegeben wurden, und weist den Übrigen die Vorgabewerte zu. Der Klarheit halber können Sie die Vorgabewerte auch ausdrücklich anfordern, entweder für einzelne Spalten oder für die ganze Zeile:
INSERT INTO produkte (produkt_nr, name, preis) VALUES (1, 'Käse', DEFAULT); INSERT INTO produkte DEFAULT VALUES;

Tipp
Um viele Daten auf einmal zu laden (so genanntes Bulk Load), schauen Sie sich den Befehl COPY an (siehe Teil VI). Er ist nicht ganz so vielseitig wie der INSERT-Befehl, aber effizienter..

6.2

Daten aktualisieren

Das Modifizieren von Daten, die sich bereits in der Datenbank befinden, nennt man Aktualisieren (englisch update). Sie können einzelne Zeilen, alle Zeilen einer Tabelle oder eine Teilmenge aller Zeilen aktualisieren. Jede Spalte kann getrennt aktualisiert werden; auf die anderen Spalten hat das keine Auswirkung. Um eine Aktualisierung durchzuführen, brauchen Sie drei Informationen: ❏ die Namen der Tabelle und der Spalten, die Sie aktualisieren möchten, ❏ den neuen Wert der Spalte, ❏ welche Zeile(n) Sie aktualisieren wollen. In Kapitel 5 wurde bereits erwähnt, dass SQL generell keine eindeutige Identifikation der Zeilen zulässt. Daher ist es nicht immer unbedingt möglich, direkt anzugeben, welche Zeile zu aktualisieren ist. Vielmehr geben Sie die Bedingungen an, die eine Zeile erfüllen muss, um aktualisiert zu werden. Wenn die Tabelle einen Primärschlüssel hat (ganz gleich, ob Sie Ihn ausdrücklich angegeben haben), können Sie einzelne Zeilen verlässlich auswählen, indem Sie eine Bedingung verwenden, die mit dem Primärschlüssel übereinstimmt. Anwendungen, die grafischen Zugriff auf die Datenbank gewähren, machen sich diese Tatsache zunutze, um Ihnen zu gestatten, einzelne Zeilen zu aktualisieren. Dieser Befehl zum Beispiel aktualisiert den Preis aller Produkte, die einen Preis von 5 haben, auf 10:
UPDATE produkte SET preis = 10 WHERE preis = 5;

88

Datenmanipulation

Je nach Umstand könnten dadurch null, eine oder mehrere Zeilen aktualisiert werden. Eine Aktualisierung, die am Ende auf keine Zeilen zutrifft, ist kein Fehler. Schauen wir uns den Befehl genauer an: Am Anfang steht das Schlüsselwort UPDATE gefolgt vom Namen der Tabelle. Wie gewohnt kann der Tabellenname mit einem Schemanamen qualifiziert werden, ansonsten wird er im Pfad gesucht. Als Nächstes kommt das Schlüsselwort SET gefolgt vom Spaltennamen, einem Gleichheitszeichen und dem neuen Wert der Spalte. Der neue Spaltenwert kann ein beliebiger Wertausdruck sein, nicht nur eine Konstante. Wenn Sie zum Beispiel den Preis aller Produkte um 10% erhöhen wollen, dann könnten Sie das so machen:
UPDATE produkte SET preis = preis * 1.10;

Wie Sie sehen, kann sich der Ausdruck für den neuen Wert auch auf den alten Wert beziehen. Wir haben hier auch die WHERE-Klausel ausgelassen. Wenn sie fehlt, dann werden alle Zeilen in der Tabelle aktualisiert. Wenn sie da ist, dann werden nur jene Zeilen aktualisiert, die die Bedingung nach der WHERE-Klausel erfüllen. Beachten Sie, dass das Gleichheitszeichen in der SET-Klausel eine Wertzuweisung ist, während das in der WHERE-Klausel ein Vergleich ist; aber dadurch kann keine Zweideutigkeit entstehen. Natürlich muss die Bedingung kein Test auf Gleichheit sein. Viele andere Operatoren stehen zur Verfügung (siehe Kapitel 9). Aber der Ausdruck muss ein Boole'sches Ergebnis haben. Sie können in einem UPDATE-Befehl auch mehrere Spalten aktualisieren, indem Sie mehrere Zuweisungen in der SET-Klausel auflisten. Zum Beispiel:
UPDATE meinetabelle SET a = 5, b = 3, c = 1 WHERE a > 0;

6.3

Daten löschen

Soweit haben wir erläutert, wie man Daten in Tabellen einfügt und wie man Daten ändert. Was noch übrig bleibt, ist zu besprechen, wie man Daten, die man nicht länger braucht, löschen kann (englisch delete). Genauso wie es nur möglich ist, ganze Zeilen einzufügen, kann man nur ganze Zeilen löschen. Im vorigen Abschnitt haben wir besprochen, dass es in SQL nicht möglich ist, einzelne Zeilen direkt anzusprechen. Deshalb kann man Zeilen nur löschen, indem man eine Bedingung angibt, die die zu löschenden Zeilen erfüllen müssen. Wenn die Tabelle einen Primärschlüssel hat, dann können Sie eine Zeile genau auswählen. Aber Sie können auch eine Gruppe von Zeilen, die eine Bedingung erfüllen, oder alle Zeilen in einer Tabelle auf einmal löschen. Man verwendet den Befehl DELETE, um Zeilen zu löschen; die Syntax ist dem UPDATE-Befehl sehr ähnlich. Um zum Beispiel alle Zeilen der Produkttabelle zu löschen, die eine Preis von 10 haben, verwenden Sie
DELETE FROM produkte WHERE preis = 10;

Wenn Sie einfach schreiben
DELETE FROM produkte;

werden alle Zeilen in der Tabelle gelöscht. Sein Sie vorsichtig!

89

7

7

Anfragen

Die vorangegangenen Kapitel haben erklärt, wie man Tabellen erzeugt, sie mit Daten füllt und diese Daten manipulieren kann. Jetzt besprechen wir endlich, wie man diese Daten wieder aus der Datenbank auslesen kann.

7.1

Überblick

Den Vorgang oder der Befehl, Daten aus der Datenbank auszulesen, nennt man eine Anfrage (englisch query). In SQL wird der Befehl SELECT dazu verwendet, Anfragen zu formulieren. Die allgemeine Syntax des SELECT-Befehls ist
SELECT select_liste FROM tabellen_ausdruck [sortierung]

Die folgenden Abschnitte beschreiben die Select-Liste, den Tabellenausdruck und die Sortierangabe im Einzelnen. Die einfachste Anfrage hat die Form
SELECT * FROM tabelle1;

Vorausgesetzt, es gibt eine Tabelle namens tabelle1, ergibt dieser Befehl alle Zeilen und alle Spalten aus tabelle1. (Die genaue Art und Weise der Ergebnisausgabe hängt von der Clientanwendung ab. Das psql-Programm gibt die Tabelle zum Beispiel mit ASCII-Zeichen aus und Clientbibliotheken bieten Funktionen an, um auf einzelne Zeilen und Spalten zuzugreifen.) Eine Select-Liste, die nur aus * besteht, steht für alle Spalten, die der Tabellenausdruck gerade zur Verfügung stellt. Eine Select-Liste kann auch nur einige der verfügbaren Spalten auswählen oder mit den Spalten Berechnungen vornehmen. Wenn zum Beispiel tabelle1 Spalten namens a, b und c hat (und möglicherweise noch weitere), können Sie die folgende Anfrage durchführen:
SELECT a, b + c FROM tabelle1;

(vorausgesetzt, dass b und c einen Zahlentyp haben). Einzelheiten finden Sie in Abschnitt 7.3.
FROM table1 ist ein besonders einfacher Tabellenausdruck: Er liest nur aus einer Tabelle. Prinzipiell können

Tabellenausdrücke komplexe Konstruktionen aus Basistabellen, Verbunde und Unteranfragen sein. Sie können den Tabellenausdruck auch ganz auslassen und den SELECT-Befehl als Taschenrechner verwenden: 91

Kapitel 7

SELECT 3 * 4;

Das ist aber sinnvoller, wenn die Ausdrücke in der Select-Liste veränderliche Ergebnisse haben. Sie könnten auf diese Art zum Beispiel eine Funktion aufrufen:
SELECT random();

7.2

Tabellenausdrücke

Ein Tabellenausdruck berechnet eine Tabelle. Der Tabellenausdruck enthält eine FROM-Klausel, wahlweise gefolgt von WHERE-, GROUP BY- und HAVING-Klauseln. Einfache Tabellenausdrücke beziehen sich ganz einfach auf eine Tabelle auf der Festplatte, eine so genannte Basistabelle, aber komplexere Ausdrücke können angewendet werden, um Basistabellen auf verschiedene Arten zu verändern oder zu kombinieren. Die optionalen WHERE-, GROUP BY- und HAVING-Klauseln im Tabellenausdruck ergeben sozusagen ein Fließband aufeinander folgender Transformationen, die sich auf die in der FROM-Klausel ermittelte Tabelle auswirken. Diese Transformationen erzeugen eine virtuelle Tabelle, die die Zeilen enthält, die in der Select-Liste verwendet werden, um die Ergebniszeilen der Anfrage zu berechnen.

7.2.1

Die FROM-Klausel

Die FROM-Klausel errechnet eine Tabelle aus einer oder mehreren Tabellen, die durch Kommas getrennt in der Liste aufgezählt werden.
FROM tabellen_verweis [, tabellen_verweis [, ...]]

Ein Tabellenverweis kann ein Tabellenname (möglicherweise mit Schemaname) oder eine abgeleitete Tabelle, wie zum Beispiel eine Unteranfrage, ein Tabellenverbund oder eine komplexe Kombination daraus sein. Wenn mehrere Tabellenverweise in der FROM-Klausel aufgelistet werden, wird der Kreuzverbund (cross join) der Tabellen ermittelt (siehe unten). Diese Tabelle ist dann die virtuelle Zwischentabelle, die den Transformationen in den WHERE-, GROUP BY- und HAVING-Klauseln zugeführt wird und schließlich das Ergebnis des Tabellenausdrucks ist. Wenn ein Tabellenverweis eine Tabelle nennt, die eine Übertabelle einer Vererbungshierarchie ist, dann erzeugt der Tabellenverweis nicht nur die Zeilen der Tabelle selbst, sondern auch die aller Untertabellen, außer wenn das Schlüsselwort ONLY vor dem Tabellennamen steht. Allerdings erzeugt der Tabellenverweis nur die Spalten, die in der genannten Tabelle vorhanden sind. Spalten, die in Untertabellen hinzugefügt wurden, werden nicht berücksichtigt.

Verbundene Tabellen
Eine verbundene Tabelle wird von zwei anderen (echten oder abgeleiteten) Tabellen nach den Regeln des jeweiligen Verbundtyp abgeleitet. Es gibt innere, äußere und Kreuzverbunde. Verbundtypen Kreuzverbund (cross join)
T1 CROSS JOIN T2

Für jede Kombination aus Zeilen von T1 und T2 wird die abgeleitete Tabelle eine Zeile enthalten, die aus allen Spalten in T1 gefolgt von allen Spalten in T2 besteht. Wenn die Tabellen also N beziehungsweise M Zeilen haben, dann hat die verbundene Tabelle N * M Zeilen.

92

a AND t1. genauso. Folglich hat die verbundene Tabelle auf jeden Fall eine Zeile für jede Zeile in T1. das heißt. Voller äußerer Verbund (FULL OUTER JOIN) Als Erstes wird ein innerer Verbund durchgeführt. Also ist USING (a. dann wird OUTER angenommen. die die Verbundbedingung mit Z1 erfüllt. die Verbundbedingung ist. Das Ergebnis von JOIN USING hat eine Spalte für jede der gleichgesetzten Eingabespalten. Bedingte Verbunde T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON boolescher_ausdruck T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 USING ( spaltenliste ) T1 NATURAL { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 Die Worte INNER und OUTER sind in allen Formen optional. die die Verbundbedingung mit keiner Zeile in T2 erfüllt. wenn LEFT. b. Die Verbundbedingung bestimmt. getrennt durch Kom- mas. Verbunde aller Typen können verkettet oder verschachtelt werden. gefolgt von den übrigen Spalten der Tabellen. dass all diese Spalten gleich sein müssen. eine Ergebniszeile mit NULL-Werten in den Spalten von T1 erzeugt. außer man verwendet ON. Das ist das Gegenteil eines linken Verbunds: Die Ergebnistabelle hat auf jeden Fall eine Zeile für jede Zeile in T2. USING ist eine abgekürzte Schreibweise: Sie enthält eine Liste aus Spaltennamen. wie er in einer WHERE-Klausel verwendet wird. die die Verbundbedingung mit keiner Zeile in T1 erfüllt. Ein Zeilenpaar aus T1 und T2 passt zusammen.c = t2. Um die Verbundreihenfolge zu bestimmen. Es gibt die folgenden Arten von bedingten Verbunden: Innerer Verbund (INNER JOIN) Für jede Zeile Z1 der Tabelle T1 hat die verbundene Tabelle eine Zeile für jede Zeile in T2. Es ist auch gleichbedeutend mit FROM T1 INNER JOIN T2 ON TRUE (siehe unten). b und c. Linker äußerer Verbund (LEFT OUTER JOIN) Als Erstes wird ein innerer Verbund ausgeführt. die NULL-Werte in den Spalten von T2 hat. die NULL-Werte in den Spalten von T1 hat. sowohl T1 als auch T2 können selbst verbundene Tabellen sein. RIGHT oder FULL angegeben sind. die NULL-Werte in den Spalten von T2 hat. Ebenso wird für jede Zeile in T2. Schließlich ist NATURAL eine Abkürzung von USING: Es steht für eine USING-Liste mit genau den Spaltennamen. die in beiden Tabellen vorhanden sind. Genauso wie bei USING erscheinen diese Spalten nur einmal im Ergebnis. eine Ergebniszeile erzeugt. Die ON-Klausel ist die allgemeinste Art der Verbundbedingung: Sie enthält einen Wertausdruck mit einem Ergebnis vom Typ boolean. Die Verbundbedingung wird in der ON. eine Ergebniszeile erzeugt.c). die die Verbundbedingung mit keiner Zeile in T2 erfüllt. welche beide der zu verbindenden Tabellen haben müssen. anstatt nur je eine mit USING. INNER ist die Vorgabe. Ansonsten werden die JOIN-Klauseln von links nach rechts ausgewertet. Danach wird für jede Zeile in T1. 93 .b AND t1.a = t2.oder der USING-Klausel oder implizit mit dem Wort NATURAL angegeben. T2.Anfragen FROM T1 CROSS JOIN T2 ist gleichbedeutend mit FROM T1. wie im Einzelnen weiter unten besprochen wird.b = t2. Danach wird für jede Zeile in T1. wenn der Ausdruck nach ON logisch wahr ist. dann hat das Ergebnis je zwei Spalten a. eine Ergebniszeile erzeugt. c) gleichbedeutend mit ON (t1. die die Verbundbedingung mit keiner Zeile in T1 erfüllt. Rechter äußerer Verbund (RIGHT OUTER JOIN) Als Erstes wird ein innerer Verbund ausgeführt. welche Zeilen der zwei Ausgangstabellen zusammenpassen. Danach wird für jede Zeile in T2. kann man Klammern um die JOIN-Klauseln setzen.

num = t2.Kapitel 7 Um all das zusammenzufassen. num | name | wert -----+------+-----1 | a | xxx 3 | c | yyy (2 rows) => SELECT * FROM t1 NATURAL INNER JOIN t2.num. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 3 | c | 3 | yyy (2 rows) => SELECT * FROM t1 INNER JOIN t2 USING (num). num | name | wert -----+------+-----1 | a | xxx 3 | c | yyy (2 rows) => SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 1 | a | 3 | yyy 1 | a | 5 | zzz 2 | b | 1 | xxx 2 | b | 3 | yyy 2 | b | 5 | zzz 3 | c | 1 | xxx 3 | c | 3 | yyy 3 | c | 5 | zzz (9 rows) => SELECT * FROM t1 INNER JOIN t2 ON t1. wir haben Tabellen t1 num | name -----+-----1 | a 2 | b 3 | c Dann erhalten wir folgende Ergebnisse für die verschiedenen Verbunde: => SELECT * FROM t1 CROSS JOIN t2. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 94 . nehmen wir an.num.

num. die nach ON angegeben wird.num. um auf die abgeleitete Tabelle zu verweisen.num = t2.num = t2. num | name | wert -----+------+-----1 | a | xxx 2 | b | 3 | c | yyy (3 rows) => SELECT * FROM t1 RIGHT JOIN t2 ON t1. muss aber genau durchdacht werden. Um ein Tabellenaliasnamen zu erzeugen.Anfragen 2 | b 3 | c (3 rows) | | | 3 | yyy => SELECT * FROM t1 LEFT JOIN t2 USING (num).num = t2. verwenden Sie FROM tabellen_verweis AS alias 95 .num AND t2. Das wird Tabellenaliasname genannt. Das kann in manchen Anfragen nützlich sein. der in der weiteren Verarbeitung verwendet werden kann. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 2 | b | | 3 | c | 3 | yyy | | 5 | zzz (4 rows) Die Verbundbedingung. Zum Beispiel: => SELECT * FROM t1 LEFT JOIN t2 ON t1.und Spaltenaliasnamen Man kann Tabellen und komplexen Tabellenverweisen einen vorübergehenden Namen geben. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 3 | c | 3 | yyy | | 5 | zzz (3 rows) => SELECT * FROM t1 FULL JOIN t2 ON t1. die nicht direkt mit dem Verbund zu tun haben. kann auch Bedingungen enthalten. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 2 | b | | 3 | c | | (3 rows) Tabellen.wert = 'xxx'.

was Sie in der Regel sicher nicht wollen. ist dass ein impliziter Tabellenverweis zur FROM-Klausel hinzugefügt wird...Kapitel 7 oder FROM tabellen_verweis alias Das Schlüsselwort AS kann also weggelassen werden. zum Beispiel: SELECT * FROM meine_tabelle AS a CROSS JOIN meine_tabelle AS b . wenn eine Tabelle mit sich selbst verbunden werden soll. Das ergibt einen Kreuzverbund... langen Tabellennamen kürzere Bezeichnungen zu geben.]] ) Wenn weniger Spaltenaliasnamen angegeben sind. Zum Beispiel: SELECT * FROM ein_sehr_langer_tabellenname e JOIN noch_ein_ziemlich_langer_name n ON e. Wenn dem Ergebnis eines Verbunds mit JOIN ein Aliasname zugewiesen wird. Aber man muss sie verwenden. dann werden die restlichen Spalten nicht umbenannt. spalte2 [. Tabellenaliasnamen sind hauptsächlich dafür da. Wenn ein Aliasname verwendet wird.id = n.) AS c 96 . auf die Tabelle mit ihrem ursprünglichen Namen zu verweisen.a > 5. dann werden dadurch die ursprünglichen Namen innerhalb der Verbundklausel versteckt. dann wird es der neue Name des Tabellenverweises für die gegenwärtige Anfrage. als die eigentliche Tabelle Spalten hat. Außerdem sind Aliasnamen notwendig. um die Verbundbedingungen lesbar zu halten. alias kann ein beliebiger Name sein..num. Es ist dann nicht mehr möglich... . um Anfragen übersichtlicher und kürzer schreiben zu können. Aber folgender Befehl ist ungültig: SELECT a. also wäre sie so geschrieben worden: SELECT * FROM meine_tabelle AS m.. Folgender Befehl ist zum Beispiel in Ordnung: SELECT a.a > 5.. wenn der Tabellenverweis eine Unteranfrage ist (siehe Abschnitt Unteranfragen). Was wirklich passiert (das ist eine Erweiterung von PostgreSQL gegenüber dem Standard). Klammern können verwendet werden. Eine typische Verwendung von Tabellenaliasnamen ist es. Diese Syntax ist besonders für Selbstverbunde und Unteranfragen nützlich. Der folgende Befehl weist den Aliasnamen b dem Verbundergebnis zu. im Gegensatz zum vorigen Beispiel: SELECT * FROM (meine_tabelle AS a CROSS JOIN meine_tabelle) AS b .. Zusammen mit Tabellenaliasnamen kann man auch den Spalten einer Tabelle vorübergehende Namen zuweisen: FROM tabellen_verweis [AS] alias ( spalte1 [.* FROM (meine_tabelle AS a JOIN deine_tabelle AS b ON . sodass die Anfrage verarbeitet wird. Folgendes wäre also keine gültige SQL-Syntax: SELECT * FROM meine_tabelle AS m WHERE meine_tabelle. um Zweideutigkeiten auszuschließen.* FROM meine_tabelle AS a JOIN deine_tabelle AS b ON . meine_tabelle AS meine_tabelle WHERE meine_tabelle.

Wenn eine solche Funktion in einer Anfrage verwendet wird. erhält die einzelne Ergebnisspalte denselben Namen wie die Funktion. entweder aus Basisdatentypen (skalaren Typen) oder aus zusammengesetzten Datentypen (Tabellenzeilen).fooid) z where z.und Spaltenaliasnamen. damit das System weiß. je nachdem. CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS ' SELECT * FROM foo WHERE fooid = $1. SELECT * FROM getfoo(1) AS t1. Die von einer Tabellenfunktion zurückgegebenen Spalten können genauso in SELECT-. müssen in Klammern stehen und ihnen muss eine Tabellenaliasname zugewiesen werden. Betrachten Sie dieses Beispiel: SELECT * FROM dblink('dbname=mydb'. Wenn die Tabellenfunktion einen Basisdatentyp zurückgibt.oder WHERE-Klauseln verwendet werden wie Spalten aus Tabellen. Tabellenfunktionen Tabellenfunktionen sind Funktionen. wie sie aufgerufen wird. Wenn eine Funktion in der FROM-Klausel ohne Aliasname belassen wird. ' LANGUAGE SQL.Anfragen Der Tabellenaliasname a ist außerhalb des Aliasnamen c nicht sichtbar.fooid). (Siehe Abschnitt Tabellen. prosrc from pg_proc') 97 . Unteranfragen Unteranfragen. fooname text). Eine Tabellenfunktion kann in der FROM-Klausel Aliasnamen erhalten. JOIN. Sie werden wie eine Tabelle. wie die Anfrage verstanden und geplant werden soll. die nicht auf eine einfache Verbundoperation reduziert werden können. wenn die Unteranfrage eine Gruppierung oder eine Aggregatberechnung enthält. Einige Beispiele: CREATE TABLE foo (fooid int. Sichten oder Unteranfragen. 'select proname. die eine Ergebnismenge aus mehreren Zeilen zurückgeben.) Zum Beispiel: FROM (SELECT * FROM tabelle1) AS alias_name Dieses Beispiel hat das gleiche Ergebnis wie FROM tabelle1 AS alias_name. In manchen Fällen ist es nützlich.fooid = foo. foosubid int. Interessantere Fälle. muss die erwartete Zeilenstruktur in der Anfrage selbst angegeben werden. SELECT * FROM foo WHERE foosubid IN (select foosubid from getfoo(foo. Wenn die Funktion einen zusammengesetzten Typ zurückgibt. erhalten die Ergebnisspalten dieselben Namen wie die einzelnen Attribute des Typs. einen anderen Satz Spalten zurückgibt. die als abgeleitete Tabelle aufgeführt werden. eine Tabellenfunktion zu definieren. Sicht oder Unteranfrage in der FROM-Klausel einer Anfrage verwendet. SELECT * FROM vw_getfoo. Dazu kann eine Tabellenfunktion mit dem Pseudotyp record als Rückgabetyp definiert werden. treten auf. dann wird der Name der Funktion als Name der Ergebnistabelle verwendet. die. kann aber auch ohne Aliasnamen belassen werden. CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1).

wie * interpretiert werden soll.wert > 5 oder vielleicht sogar FROM a NATURAL JOIN b WHERE b. Wenn das Ergebnis der Bedingung logisch wahr ist. 7..2. b WHERE a. ist. wie in Abschnitt 4... weil damit nicht nur Zeilen herausgefiltert.id = b. damit der Parser zum Beispiel weiß.id) WHERE b. Hier sind einige Beispiele von WHERE-Klauseln: SELECT .2 Die WHERE-Klausel Die Syntax der WHERE-Klausel ist WHERE suchbedingung wobei die suchbedingung ein beliebiger Wertausdruck.id AND b. Nachdem die Verarbeitung der FROM-Klausel abgeschlossen ist. ist hauptsächlich eine Stilfrage. Die ON /USING-Klausel eines äußeren Verbunds kann nicht als WHERE-Bedingung geschrieben werden.. prosrc text) WHERE proname LIKE 'bytea%'. das ist zwar nicht zwingend.2 definiert. 2. aber ansonsten wäre die WHEREKlausel ziemlich nutzlos. die Verbundbedingung in die WHERE-Klausel zu schreiben. FROM fdt WHERE c1 IN (SELECT c1 FROM t2) 98 . Die Funktion dblink führt eine Anfrage in einer anderen Datenbank aus (siehe contrib/dblink). weil Sie für jede Art von Anfrage verwendet werden kann. FROM fdt WHERE c1 > 5 SELECT . wird jede Zeile der virtuellen Tabelle mit der Suchbedingung geprüft.. sondern auch zum Endergebnis hinzufügt werden (für Zeilen die keine passende Zeile in der anderen Tabelle haben). der ein Ergebnis vom Typ boolean hat. Für äußere Verbunde gibt es keine Wahl: Sie müssen in der FROM-Klausel geschrieben werden.wert > 5 Welche dieser Formen Sie verwenden. dann wird sie verworfen. Die Suchbedingung bezieht sich normalerweise auf mindestens ein paar der Spalten der in der FROM-Klausel erzeugten Tabelle. Die JOIN-Syntax in der FROM-Klausel ist wahrscheinlich nicht ganz so portierbar auf andere SQL-Datenbanken. Die folgenden Tabellenausdrücke sind zum Beispiel alle gleichbedeutend: und FROM a. Die tatsächlich erwarteten Spalten müssen in der aufrufenden Anfrage angegeben werden.Kapitel 7 AS t1(proname name. Anmerkung Vor der Verwirklichung der JOIN-Syntax war es notwendig. ansonsten (das heißt das Ergebnis ist logisch falsch oder der NULL-Wert). wird die Zeile in der Ergebnistabelle behalten. Sie hat den Rückgabetyp record. FROM fdt WHERE c1 IN (1. 3) SELECT ..id = b.wert > 5 FROM a INNER JOIN b ON (a.

ist unerheblich. FROM fdt WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = fdt. in der die Spalten aufgelistet werden... Die Qualifikation von c1 als fdt. Beachten Sie die Verwendung von skalaren Unteranfragen als Wertausdrücke... Das kann man verwenden. Aber die Qualifikation des Spaltennamens fördert die Übersichtlichkeit. jede Gruppe von Zeilen.. Dieses Beispiel zeigt. kann die Tabelle mit der GROUP BYKlausel gruppiert und Gruppen mit der HAVING-Klausel eliminiert werden.c1 + 10) SELECT . jene Zeilen einer Tabelle zusammen zu gruppieren. wie der Namensraum der Spalten der äußeren Anfrage sich auf die inneren Anfragen ausdehnt. x | y ---+--a | 3 c | 2 b | 5 a | 1 (4 rows) => SELECT x FROM test1 GROUP BY x.und HAVING-Klauseln Nachdem die abgeleitete Tabelle den WHERE-Filter durchlaufen hat. die die gleichen Werte in allen aufgezählten Spalten haben. SELECT select_liste FROM . die für alle Zeilen in der Gruppe stehen kann. Unteranfragen können genauso wie andere Anfragen komplexe Tabellenausdrücke verwenden.c1 ist nur notwendig. die die gleichen Werte haben... Beachten Sie auch.. x --a b c (3 rows) 99 . FROM fdt WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = fdt.Anfragen SELECT .c1 + 10) AND 100 SELECT .2.. Der Zweck des Ganzen ist es.. die die Bedingung in der WHEREKlausel nicht erfüllen.. FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt. [WHERE . Zeilen. werden aus fdt entfernt. um doppelte Ergebniszeilen zu entfernen und/oder um Aggregatberechnungen an den Gruppen vorzunehmen. Die Reihenfolge.3 Die GROUP BY. 7. spalten_gruppierungs_verweis]. Die GROUP BY-Klausel wird dazu verwendet.] GROUP BY spalten_gruppierungs_verweis [. Zum Beispiel: => SELECT * FROM test1. wie auf fdt in den Unteranfragen Bezug genommen wird.. selbst wenn sie nicht zwingend erforderlich ist. wenn c1 auch eine Spalte in der abgeleiteten Eingabetabelle der Unteranfrage ist.c1) fdt ist hier irgendeine in der FROM-Klausel ermittelte Tabelle. auf eine Gruppenzeile zu reduzieren.

Kapitel 7 Die zweite Anfrage hätte man nicht als SELECT * FROM test1 GROUP BY x schreiben können. da sie einen bekannten Wert pro Gruppe haben.. (sum(v. Für jedes Produkt ergibt die Anfrage eine zusammenfassende Zeile für den Umsatz dieses Produkts. Im strikten SQL kann GROUP BY nur auf Spalten in der Ausgangstabelle angewendet werden.name.name und p. der der Gruppe hätte zugeordnet werden können. In diesem Beispiel müssen die Spalten produkt_nr. sum(y) FROM test1 GROUP BY x.3. Ein Beispiel mit einem Aggregatausdruck ist: => SELECT x. Das Gruppieren nach Wertausdrücken anstelle von einfachen Spaltenverweisen ist auch möglich. aber in PostgreSQL kann man GROUP BY auch mit Spalten aus der Select-Liste verwenden. aber diese Erkennung ist noch nicht verwirklicht. könnten Name und Preis völlig von der Produktnummer abhängen. Die Spalten. p. dann kann die HAVING-Klausel ähnlich wie die WHERE-Klausel verwendet werden. Hier ist noch ein Beispiel: Es berechnet den Gesamtumsatz für jedes Produkt (und nicht etwa für alle Produkte zusammen).3). HAVING boolescher_ausdruck Ausdrücke in der HAVING-Klausel können sowohl die gruppierten als auch ungruppierte Ausdrücke (welche dann notwendigerweise eine Aggregatfunktion beinhalten) verwenden. wenn eine Tabelle gruppiert wird. x | sum 100 .] GROUP BY . Die Syntax ist: SELECT select_liste FROM . Ein Beispiel: => SELECT x.preis) AS umsatz FROM produkte p LEFT JOIN verkäufe v USING (produkt_nr) GROUP BY produkt_nr. können in der Select-Liste verwendet werden.. p.preis in der GROUP BY-Klausel stehen. weil sie auch in der Select-Liste der Anfrage verwendet werden. ( Je nachdem..14 finden.preis. SELECT produkt_nr.. sum(y) FROM test1 GROUP BY x HAVING sum(y) > 3. die einen einzelnen Wert aus den Werten der gesamten Gruppe errechnet.. aber nur bestimmte Gruppen von Interesse sind. nach denen nicht gruppiert wird. weil es keinen einzelnen Wert der Spalte y gibt.. [WHERE . sodass die zusätzlichen Gruppierungen unnötig wären. welcher für den Gesamtumsatz mit einem Produkt steht. p.)) verwendet wird. wie die Produkttabelle genau aufgebaut ist. nach denen gruppiert wurde.) Die Spalte v. Wenn eine Tabelle mit GROUP BY gruppiert wurde. dann können die Spalten. p. nur in Aggregatausdrücken verwendet werden.. da sie nur in einem Aggregatausdruck (sum(. Generell gilt.menge) * p.name.menge muss nicht in der GROUP BY-Klausel stehen. um Gruppen aus der gruppierten Tabelle zu entfernen. x | sum ---+----a | 4 b | 5 c | 2 (3 rows) Hier ist sum eine Aggregatfunktion.. Das kann man auch mit der DISTINCT-Klausel erreichen (siehe Abschnitt 7. Weitere Informationen über die verfügbaren Aggregatfunktionen können Sie in Abschnitt 9. Tipp Gruppierung ohne Aggregatausdruck berechnet im Endeffekt die Menge der voreinander verschiedenen Werte in einer Spalte.

p65 Schwarz 101 28. 101..up . 12:07 ..02.08.

. Registrieren Sie sich jetzt auf www. Sie mit den aktuellsten Inhalten zu versorgen. Wir sind stets darauf bedacht.. haben wir einen besonderen Leser-Service eingeführt. kostenlosen Downloads.p65 Schwarz 102 28.vmi-buch.. 12:07 .08.und Praxisstand wieder. weil wir wissen. up . Um Sie auch über das vorliegende Buch hinaus regelmäßig über die relevanten Entwicklungen am ITMarkt zu informieren..de und Sie erhalten zukünftig einen E-Mail-Newsletter mit Hinweisen auf Aktivitäten des Verlages wie zum Beispiel unsere aktuellen.de oder www.02. Registrieren Sie sich JETZT! Unsere Bücher sind mit großer Sorgfalt erstellt.mitp. zuverlässig und fundiert auf den neuesten Stand bringen. dass Sie gerade darauf großen Wert legen. Ihr Team von mitp 101. Lassen Sie sich professionell. Unsere Bücher geben den topaktuellen Wissens. update Nutzen Sie den UPDATE-SERVICE des mitp-Teams bei vmi-Buch..

dann muss der Tabellenname auch angegeben werden. Zeilen entfernt oder gruppiert wurden usw. p. welche Spalten der Zwischentabelle tatsächlich ausgegeben werden. 103 .3. die ihnen wie in Abschnitt Tabellen.preis * v. während die HAVING-Klausel das Ergebnis auf Gruppen.menge) * (p. außer wenn eine Gruppierung vorgenommen wird.1 Elemente der Select-Liste Die einfachste Select-Liste ist *. Ansonsten ist die Select-Liste eine Liste von Wertausdrücken (wie in Abschnitt 4. ist der gleiche wie in der WHERE-Klausel. dann ist es der gleiche wie in der HAVING-Klausel. indem möglicherweise Tabellen und Sichten kombiniert wurden. p. 7. Wenn mehrere Tabellen eine Spalte mit dem gleichen Namen haben. tbl1.Anfragen ---+----a | 4 b | 5 (2 rows) => SELECT x.kosten)) AS profit FROM produkte p LEFT JOIN verkäufe v USING (produkt_nr) WHERE v. deren Umsatz größer als 5000 war. 7. beschränkt.INTERVAL '4 weeks' GROUP BY produkt_nr. c FROM .menge) > 5000.2 definiert). Sie könnte zum Beispiel eine Liste von Spaltennamen sein: SELECT a. dass die Aggregatausdrücke nicht unbedingt in allen Teilen der Anfrage gleich sein müssen.kosten HAVING sum(p.datum > CURRENT_DATE .name.. b und c sind entweder die wirklichen Namen von Spalten der in der FROM-Klausel verwendeten Tabellen oder die Aliasnamen..b FROM .. wie in ws SELECT tbl1. die der Tabellenausdruck erzeugt.3 Select-Listen Wie im vorigen Abschnitt gezeigt wurde. durch Kommas voneinander getrennt. p. (sum(v. Im obigen Beispiel wählt die WHERE-Klausel Zeilen aus. x | sum ---+----a | 4 b | 5 (2 rows) Nochmal ein etwas realistischeres Beispiel: SELECT produkt_nr. sum(y) FROM test1 GROUP BY x HAVING x < 'c'.und Spaltenaliasnamen zugewiesen wurden. Die Spaltennamen a.preis .name. b. Der Namensraum.a. tbl2.a. indem sie eine ungruppierte Spalte verwendet (der Ausdruck ist nur für Verkäufe in den letzten vier Wochen wahr).p. der in der Select-Liste zur Verfügung steht. Beachten Sie auch. Diese Tabelle wird letztendlich der Select-Liste zur Verarbeitung übergeben.. p. ermittelt der Tabellenausdruck im SELECT-Befehl eine virtuelle Zwischentabelle. Die Select-Liste bestimmt.preis. welche alle Spalten ausgibt.

können aus der Ergebnistabelle wahlweise etwaige Duplikate entfernt werden. auszuwählen.3. 7.. dass eine neue virtuelle Spalte an die Ergebnistabelle angefügt wird. NULL-Werte gelten in dieser Betrachtung als gleich. 104 . Als Alternative kann auch ein beliebiger Ausdruck bestimmen. dann wird vom System ein Name zugewiesen.. Durch diesen Ablauf können Sie eine Spalte praktisch zweimal umbenennen. Wenn man GROUP BY und Unteranfragen in der FROM-Klausel geschickt anwendet.2 Ergebnisspaltennamen Den Einträgen in der Select-Liste kann man Namen für die weitere Verarbeitung geben.]) select_liste . wenn die Ergebnistabelle ausgegeben wird). Der Ausdruck wird für jede Ergebniszeile ausgewertet. um das normale Verhalten.. (Anstelle von DISTINCT kann das Wort ALL verwendet werden. dass alle Zeilen beibehalten werden. der für alle Zeilen ausgewertet wird. Für komplexe Ausdrücke wird vom System ein Name erzeugt. Beachten Sie. 7. Anmerkung Die hier beschriebene Vergabe von Namen an die Spalten ist nicht das Gleiche wie die Vergabe von Aliasnamen in der FROM-Klausel (siehe Abschnitt Tabellen.) Wenn ein beliebiger Wertausdruck in der Select-Liste verwendet wird. und nur die erste der Zeilen wird in der Ergebnismenge behalten. damit die Zeilen in einer eindeutigen Reihenfolge am DISTINCT-Filter ankommen. Für Funktionsaufrufe ist das der Name der Funktion. dass die »erste Zeile« einer Menge nicht vorhergesagt werden kann. Zum Beispiel: SELECT a AS wert.und Spaltenaliasnamen). der in der Select-Liste bestimmt wird...) Die DISTINCT ON-Klausel ist nicht Teil des SQL-Standards und manche halten sie wegen der möglicherweise unvorhersehbaren Ergebnisse für schlechten Stil.. Wenn kein Spaltenname mit AS angegeben wird. wobei die Werte der Zeile für etwaige Spaltenverweise eingesetzt werden. Die »weitere Verarbeitung« ist in diesem Fall eine mögliche Sortierklausel und Clientanwendungen (zum Beispiel als Spaltenköpfe. wird am Ende weitergegeben. b + c AS summe FROM .. Für einfache Spaltenverweise ist das der Namen der Spalte..3 DISTINCT Nachdem die Select-Liste verarbeitet wurde.2. werden als gleich betrachtet. ausdruck . für die alle Ausdrücke gleich sind. Aber die Ausdrücke in der Select-Liste müssen nicht unbedingt eine Spalte aus dem Tabellenausdruck aus der FROMKlausel verwenden. welche Zeilen als gleich betrachtet werden sollen: SELECT DISTINCT ON (ausdruck [. Hierbei ist ausdruck ein beliebiger Wertausdruck. Dazu wird das Schlüsselwort DISTINCT gleich hinter das SELECT geschrieben: SELECT DISTINCT select_liste .2. aber sie ist oft eine bequeme Alternative. wenn sie sich in mindestens einem Spaltenwert voneinander unterscheiden.) Selbstverständlich gelten zwei Zeilen als dann verschieden voneinander. kann man sich das so vorstellen.Kapitel 7 (Siehe auch Abschnitt 7. (Die Verarbeitung von DISTINCT ON geschieht nach der Sortierung durch ORDER BY. aber der Name.3. sie können zum Beispiel auch konstante mathematische Ausdrücke sein. außer wenn die Anfrage nach ausreichend vielen Spalten sortiert wird. kann man diese Klausel vermeiden. Die Zeilen.

Eine bestimmte Reihenfolge kann nur gewährleistet werden. die von jeder der bisher beschriebenen Fähigkeiten Gebrauch machen können. die Vereinigungsmengenoperation. müssen die Anfragen vereinigungskompatibel (englisch union compatible) sein. was heißt. außer wenn INTERSECT ALL verwendet wird. Schnittmenge oder Differenzmenge zweier Anfrage berechnen zu können. wenn der Sortierschritt ausdrücklich angefordert wird. Schnittmenge (intersection) und Differenzmenge. aber darauf darf man sich auf keinen Fall verlassen.5 erklärt. die Schnittmengenoperation. 7. die Differenzmengenoperation.Anfragen 7. im Sinne von DISTINCT. Die tatsächliche Reihenfolge hängt in diesem Fall von den Scan. entfernt.4 Anfragen kombinieren Die Ergebnisse zweier Anfragen können mit Mengenoperationen vereinigt werden. spalte2 [ASC | DESC] . wie in Abschnitt 10. Darüber hinaus werden alle doppelten Zeilen. Die Syntax ist anfrage1 UNION [ALL] anfrage2 anfrage1 INTERSECT [ALL] anfrage2 anfrage1 EXCEPT [ALL] anfrage2 anfrage1 und anfrage2 sind Anfragen. dann werden die Zeilen in zufälliger Reihenfolge zurückgegeben. außer wenn UNION ALL verwendet wird. INTERSECT. ermittelt alle Zeilen.und Verbund-Plantypen und der Reihenfolge auf der Festplatte ab.5 Zeilen sortieren Nachdem eine Anfrage eine Ergebnistabelle erzeugt hat (nachdem die Select-Liste verarbeitet wurde). kann das Ergebnis wahlweise sortiert werden. hängt das Ergebnis von anfrage2 im Prinzip an das Ergebnis von anfrage1 an (obwohl es keine Gewähr dafür gibt. Doppelte Zeilen werden entfernt. die sowohl im Ergebnis von anfrage1 als auch im Ergebnis von anfrage2 sind.. wie zum Beispiel: anfrage1 UNION anfrage2 UNION anfrage3 Das bedeutet das Gleiche wie: (anfrage1 UNION anfrage2) UNION anfrage3 UNION.] 105 . dass beide die gleiche Anzahl von Spalten ergeben und dass die entsprechenden Spalten kompatible Datentypen haben. die im Ergebnis von anfrage1. Die ORDER BY-Klausel gibt die Sortierreihenfolge an: SELECT select_liste FROM tabellen_ausdruck ORDER BY spalte1 [ASC | DESC] [. aber nicht im Ergebnis von anfrage2 sind. außer wenn EXCEPT ALL verwendet wird. ermittelt alle Zeilen. dass die Zeilen auch in dieser Reihenfolge zurückgegeben werden). Wenn das Sortieren nicht gewählt wird. Um die Vereinigungsmenge. Mengenoperationen können auch verschachtelt und verkettet werden. Die möglichen Operationen sind Vereinigungsmenge (englisch union).. EXCEPT. Doppelte Zeilen werden wiederum entfernt.

dass man sehr wahrscheinlich unterschiedliche Pläne (die unterschiedliche Zeilenreihenfolgen ergeben) erhält. Aber diese Erweiterungen funktionieren nicht in Anfragen mit UNION.2) oder die Nummer einer Spalte sein. um Zeilen zu sortieren. wie in OFFSET angegeben. LIMIT ALL hat die gleiche Auswirkung. dann werden höchstens so viele Zeilen zurückgegeben (aber möglicherweise weniger. nur einen Teil der Zeilen. verweisen auf Spalten in der Select-Liste. Wenn LIMIT verwendet wird. dass so viele Zeilen ausgelassen werden. Ansonsten erhalten Sie eine nicht vorhersagbare Teilmenge der Ergebniszeilen der Anfrage. 7. aber 10 bis 20 nach welcher Reihenfolge? Die Reihenfolge ist unbekannt. SELECT a + b AS summe. dann werden die hinteren Einträge verwendet. um die Sortierrichtung auf aufsteigend (englisch ascending) bzw. was heißt. b FROM tabelle1 ORDER BY a. OFFSET 0 hat die gleiche Auswirkung. OFFSET bedeutet. Als Erweiterung gegenüber dem SQL-Standard erlaubt PostgreSQL die Sortierung nach beliebigen Ausdrücken: SELECT a.und OFFSET-Werte verändert. Die aufsteigende Reihenfolge stellt kleinere Werte an den Anfang. c FROM tabelle1 ORDER BY summe.Kapitel 7 spalte1 usw. dann werden so viele Zeilen ausgelassen. als wenn man die OFFSET-Klausel auslässt. INTERSECT oder EXCEPT und sind nicht auf andere SQL-Datenbanken portierbar. wenn ORDER BY nicht verwendet wird. zurückzugeben: SELECT select_liste FROM tabellen_ausdruck [LIMIT { zahl | ALL }] [OFFSET zahl] Wenn eine Limit-Zahl angegeben wird. sind auch erlaubt: SELECT a AS b FROM tabelle1 ORDER BY a. die der von den vorderen Einträgen festgelegten Reihenfolge nach gleich sind. Wenn sowohl OFFSET als auch LIMIT verwendet werden. Entsprechend wird die abfallende Reihenfolge durch den Operator > festgelegt. die in der Select-Liste umbenannt wurden. eine ORDER BY-Klausel zu verwenden. die von der übrigen Anfrage erzeugt werden. Wenn mehrere Spalten zum Sortieren angegeben werden. bevor Zeilen zurückgegeben werden. Der Anfrageoptimierer zieht die LIMIT-Klausel mit in Betracht. die die Ergebniszeilen in eine eindeutige Ordnung bringt. Einige Beispiele: SELECT a.3. als wenn man die LIMIT-Klausel auslässt. falls die Anfrage selbst weniger Zeilen liefert). sum(b) FROM tabelle1 GROUP BY a ORDER BY 1. Sie können entweder der Ausgabename einer Spalte (siehe Abschnitt 7. wenn man die LIMIT. wenn er einen Ausführungsplan für eine Anfrage erstellt. SELECT a.6 LIMIT und OFFSET LIMIT und OFFSET ermöglichen Ihnen. Sie könnten zum Beispiel die Zeilen 10 bis 20 anfordern. Wenn man folglich 106 . abfallend (descending) zu setzen. Verweise auf Spaltennamen aus der FROM-Klausel. wobei »kleiner« durch den Operator < festgelegt wird. b FROM tabelle1 ORDER BY a + b. Nach jeder Spaltenangabe kann wahlweise ASC oder DESC stehen. dann ist es empfehlenswert. bevor die Zählung für LIMIT beginnt.

wenn man keine voraussagbare Reihenfolge mit ORDER BY erzwingt. das Verhalten folgt aus der Tatsache. dass SQL keine Gewähr dafür gibt.Anfragen die LIMIT. wird man widersprüchliche Ergebnisse erhalten. außer wenn ORDER BY verwendet wird. 107 . um die Reihenfolge zu beeinflussen.und OFFSET-Werte variiert. Das ist kein Fehler. um verschiedene Teilmengen eines Anfrageergebnisses auszuwählen. dass das Ergebnis einer Anfrage in einer bestimmten Reihenfolge abgeliefert wird.

.

int4 float8 varchar(n) char(n) varbit(n) bool Alias int8 serial8 Beschreibung 8-Byte-Ganzzahl mit Vorzeichen selbstzählende 8-Byte-Ganzzahl Bitkette mit fester Länge Bitkette mit variabler Länge Boole'scher (logischer) Wert (wahr/falsch) Rechteck binäre Daten Zeichenkette mit variabler Länge Zeichenkette mit fester Länge IP-Netzwerkadresse Kreis in der Ebene Kalenderdatum ( Jahr. Monat. Die meisten alternativen Namen in der Spalte “Alias” sind interne Namen. Tag) Fließkommazahl mit doppelter Präzision IP-Hostadresse 4-Byte-Ganzzahl mit Vorzeichen Zeitspanne Gerade in der Ebene (nicht voll implementiert) endliche Strecke in der Ebene MAC-Adresse Tabelle 8.1 zeigt alle eingebauten. zur allgemeinen Verwendung gedachten Datentypen.1: Datentypen 109 . die von PostgreSQL aus historischen Gründen verwendet werden. Benutzer können weitere Typen mit CREATE TYPE zu PostgreSQL hinzufügen. Tabelle 8. Name bigint bigserial bit bit varying(n) boolean box bytea character varying(n) character(n) cidr circle date double precision inet integer interval(p) line lseg macaddr int.8 8 Datentypen PostgreSQL stellt seinen Benutzern eine reichhaltige Menge eingebauter Datentypen zur Verfügung. die hier nicht gezeigt sind. Darüber hinaus gibt es einige für interne Zwecke gebrauchte und einige veraltete Typen.

2 listet die verfügbaren Typen.) Kompatibilität: Die folgenden Typen (oder deren Schreibweisen) sind von SQL vorgesehen: bit. integer. interval. Name smallint integer Speichergröße 2 Bytes 4 Bytes Beschreibung ganze Zahl mit kleiner Reichweite normale Wahl für ganze Zahlen Reichweite -32768 bis +32767 -2147483648 bis +2147483647 Tabelle 8. Einige Eingabe. s) ] exakte Zahl mit wählbarer Präzision offener oder geschlossener Pfad in der Ebene geometrischer Punkt in der Ebene Polygon float4 int2 serial4 Fließkommazahl mit einfacher Präzision 2-Byte-Ganzzahl mit Vorzeichen selbstzählende 4-Byte-Ganzzahl Zeichenkette mit variabler Länge Tageszeit Tageszeit mit Zeitzone Datum und Zeit Datum und Zeit mit Zeitzone time [ (p) ] with time zone timetz timestamp [ (p) ] without time zone timestamp [ (p) ] [ with time zone ] timestamp timestamptz Tabelle 8.2: Numerische Typen 110 .und 8-Byte-Ganzzahlen (englisch integer).B. Viele eingebaute Datentypen haben offensichtliche externe Formate. char. 4. decimal. Jeder Datentyp hat eine externe Darstellung. Einige Operatoren und Funktionen (z. Einige Typen sind allerdings nur in PostgreSQL vorhanden. timestamp (beide mit und ohne with time zone). bit varying. boolean. s) ] path point polygon real smallint serial text time [ (p) ] [ without time zone ] Alias Beschreibung Geldbetrag decimal [ (p.und Zeittypen. 4. um die Geschwindigkeit zu verbessernAuf einigen Systemen können die numerischen Operationen bei einigen Datentypen zum Beispiel ohne Benachrichtigung Überlauf oder Unterlauf verursachen. Tabelle 8. character varying. Addition und Multiplikation) führen zur Laufzeit keine Fehlerprüfung durch. numeric. character. dass das Ergebnis einer Ausgabefunktion gegenüber dem ursprünglichen Wert an Genauigkeit verlieren kann.Kapitel 8 Name money numeric [ (p. varchar.1 Numerische Typen Numerische Typen bestehen aus 2-.1: Datentypen (Forts.und 8-Byte-Fließkommazahlen (floating point) und Zahlen mit Dezimalbrüchen mit fester Präzision. wie zum Beispiel offene oder geschlossene Pfade. wie zum Beispiel die Datums. Das heißt. real. double precision. oder haben mehrere mögliche Eingabeformate. time.und Ausgabefunktionen bestimmt wird. 8. die von seinen Eingabe.und Ausgabefunktionen sind nicht umkehrbar. smallint. date.

einen Wert außerhalb des Gültigkeitsbereichs zu speichern. Der Typ integer ist die häufigste Wahl. Die folgenden Abschnitte beschreiben die Typen im Einzelnen. Der Typ bigint sollte nur verwendet werden.1...Datentypen Name bigint decimal numeric real double precision serial bigserial Speichergröße 8 Bytes variabel variabel 4 Bytes 8 Bytes 4 Bytes 8 Bytes Beschreibung ganze Zahl mit großer Reichweite benutzerdefinierte Präzision. mit unterschiedlichen Reichweiten. Größe im Speicher und Effizienz bietet. exakt variable Präzision. und PostgreSQL kann gegenwärtig keine Indexe verwenden. weil er voraussetzt. da er die beste Balance zwischen Reichweite. Versuche. Der Type bigint funktioniert möglicherweise nicht auf allen Plattformen. integer und bigint speichern ganze Zahlen (englisch integer). Die numerischen Typen haben einen vollen Satz entsprechender Operatoren und Funktionen. Eine Möglichkeit. die Konstante in Apostrophe zu setzen. das System dazu zu bewegen. verursachen einen Fehler. dass der Compiler 8-Byte-Ganzzahlen unterstützt.1 Ganzzahlentypen Die Typen smallint. inexakt variable Präzision. 8. WHERE smallint_spalte = 42 hat. wie hier: . wo dies tatsächlich der Fall ist. Schauen Sie in Kapitel 9 für weitere Informationen. SQL gibt nur die Ganzzahlentypen integer (oder int) und smallint an. Der Typ bigint und die Typnamen int2. Eine Klausel. weil das System der Konstante 42 den Typ integer zuweist.1. WHERE smallint_spalte = '42' Dadurch zögert das System die Typauflösung etwas hinaus und wird der Konstante den richtigen Typ zuweisen. int4 und int8 sind Erweiterungen. von diesem Index Gebrauch zu machen.. dann werden Sie sicher auf Probleme stoßen. die PostgreSQL aber mit diversen anderen SQL-Datenbanksystemen gemeinsam hat. verhält sich bigint genau so wie integer (aber benötigt trotzdem 8 Bytes Speicherplatz).. Anmerkung Wenn Sie eine Spalte vom Typ smallint oder bigint mit einem Index haben. Auf Maschinen.2: Numerische Typen (Forts. die diese Unterstützung nicht haben. inexakt selbstzählende ganze Zahl große selbstzählende ganze Zahl Reichweite -9223372036854775808 bis 9223372036854775807 keine Begrenzung keine Begrenzung 6 Dezimalstellen Präzision 15 Dezimalstellen Präzision 1 bis 2147483647 1 bis 9223372036854775807 Tabelle 8. weil Letzterer auf jeden Fall schneller ist. ist. wenn die Reichweite des Typs integer nicht ausreicht. exakt benutzerdefinierte Präzision. die zum Beispiel eine Form wie . wenn zwei verschiedene Datentypen im Spiel sind.) Die Syntax für numerische Typen ist in Abschnitt 4. dieses Problem zu umgehen. wird den Index nicht verwenden. Allerdings kennen wir keine vernünftige Plattform. Der Typ smallint wird normalerweise nur verwendet. wenn der Speicherplatz knapp ist.2 beschrieben. 111 . das heißt Zahlen ohne Nachkommastellen.

Der Typ real hat normalerweise einen Gültigkeitsbereich von mindestens -1E+37 bis +1E+37 und eine Genauigkeit von mindestens sechs Dezimalstellen (in der gesamten Zahl). Normalerweise werden die Eingabewerte einer numeric-Spalte auf die vorgesehene Anzahl von Nachkommastellen gebracht. in der Zahlen mit einer beliebigen Anzahl Stellen vor oder nach dem Komma gespeichert werden können. Unterlauf) angewiesen sind. sodass das Speichern und wieder Auslesen eines Wertes leichte Diskrepanzen zeigen kann. doppelte Genauigkeit). dann sollten Sie die Implementierung dieser Typen ganz genau auswerten. Der Typ double precision hat 112 . die man erwarten könnte. Er ist besonders empfehlenswert für die Speicherung von Geldbeträgen und anderer Größen.1. (Der SQL-Standard sieht hier eigentlich vor. Beide Typen sind Teil des SQL-Standards. Die Typen decimal und numeric sind identisch. ❏ Wenn Sie komplizierte Berechnungen mit diesen Typen anstellen und auf ein bestimmtes Verhalten in Grenzfällen (Unendlichkeit. außer wenn die Spalte wie im letzten Fall erzeugt wurde. Der Typ numeric ist allerdings verglichen mit den im nächsten Abschnitt beschriebenen Fließkommatypen sehr langsam. Betriebssystem und Compiler unterstützt wird. dass null Nachkommastellen die Vorgabe sind. das heißt im Endeffekt eine ganze Zahl.Kapitel 8 8. dann geben Sie die gewünschte Anzahl von Stellen immer an. dass einige Werte nicht exakt in das interne Format umgewandelt werden können und als Annäherungen gespeichert werden. die der Nachkommastellen null oder positiv sein. den Wert zu runden. In der Praxis sind diese Typen normalerweise Umsetzungen des IEEE-Standards 754 für binäre Fließkomma-Arithmetik (einfache bzw. insoweit das vom Prozessor. wo Genauigkeit erforderlich ist. 8. verwenden Sie folgende Syntax: NUMERIC(gesamtstellen. nachkommastellen) Die Zahl der Gesamtstellen muss positiv.3 Fließkommatypen Die Datentypen real und double precision sind inexakte numerische Typen mit variabler Genauigkeit. Inexakt bedeutet. dass er in die Grenzen passt. dann wird das System versuchen. Um eine Spalte vom Typ numeric zu erstellen. Wenn Sie auf Portierbarkeit Wert legen. Das Verwalten dieser Abweichungen und der Art. wird eine Spalte erzeugt. Wir halten das für nicht so sinnvoll. Wir wollen lediglich folgende Hinweise geben: ❏ Wenn Sie exakte Speicherung und Berechnungen benötigen (zum Beispiel für Geldbeträge). Wenn Sie schreiben NUMERIC(stellen) werden null Nachkommastellen vorgesehen. Sowohl die Zahl der Nachkommastellen und die Zahl der insgesamt zu speichernden Zifferstellen können angegeben werden.2 Zahlen mit beliebiger Präzision Der Type numeric kann Zahlen mit bis zu 1000 Ziffern Präzision speichern und exakte Berechnungen ausführen. ist das Thema eines ganzen Zweigs der Mathematik und der Informatik und soll hier nicht weiter besprochen werden.) Wenn die Anzahl der Stellen (insgesamt oder nach dem Komma) in einem Wert die angegebenen Grenzen einer Spalte überschreitet. wie sie sich in Berechnungen verhalten. dann sollten Sie den Typ numeric verwenden. ❏ Das Vergleichen zweier Fließkommawerte (mit =) muss nicht unbedingt die Ergebnisse liefern.1. dann ist das ein Fehler. Und wenn Sie ganz einfach schreiben NUMERIC ohne irgendwelche Stellenzahlen. Wenn er nicht so gerundet werden kann.

die automatisch eine eindeutige Nummerierung erzeugen. die durch einen serial-Typ erzeugt wird. dass mehr als 231 Nummern innerhalb der Lebensdauer einer Tabelle benötigt werden. Wenn Sie einen Unique Constraint oder einen Primärschlüssel für die Spalte haben wollen. wenn die Sequenz aus einer Dumpdatei einer Datenbank vor 7. In der gegenwärtigen Umsetzung ist CREATE TABLE tabellenname ( spaltenname serial ).3 hatte serial automatisch einen Unique Constraint. die benötigt werden. Die Typnamen serial und serial4 sind gleichbedeutend: Beide erzeugen Spalten vom Typ integer. um die Abhängigkeit zwischen der Sequenz und der Spalte herzustellen. verursachen einen Fehler. die zu groß oder zu klein sind. Werte. um zu verhindern. Die Typnamen bigserial und serial8 funktionieren genauso. das passiert nicht automatisch. wenn die zugehörige Spalte entfernt wird. Die Sequenz. Anmerkung Vor PostgreSQL 7. Das heißt also. dass aus Versehen doppelte Werte eingefügt werden. gleichbedeutend mit CREATE SEQUENCE tabellenname_spaltenname_seq.1. weil die Dumpdatei die Informationen. verursachen einen Unterlauffehler. Wenn die Genauigkeit eines Eingabewerts zu hoch ist. Zahlen. außer dass sie eine Spalte vom Typ bigint erzeugen. wird automatisch wieder gelöscht. CREATE TABLE tabellenname ( spaltenname integer DEFAULT nextval('tabellenname_spaltenname_seq') NOT NULL ). eine integer-Spalte und ihr Vorgabewert werden aus einer Sequenz erzeugt.) 8. 113 . sondern abgekürzte Schreibweisen. nicht enthält.Datentypen normalerweise etwa einen Bereich von -1E+308 bis +1E+308 mit mindestens 15 Dezimalstellen Genauigkeit. dann müssen Sie es genauso wie bei jedem anderen Datentyp ausdrücklich angeben. (Das war vor PostgreSQL 7. Außerdem wird ein NOT NULL-Constraint erzeugt. In der Regel sollten Sie auch einen UNIQUE. wenn Sie erwarten. um zu verhindern. um Spalten einzurichten. Das ist nicht mehr automatisch.4 Selbstzählende Datentypen Die Datentypen serial und bigserial sind keine richtigen Datentypen. und kann auf direktem Wege nicht gelöscht werden. dann wird versucht. bigserial sollte verwendet werden. Beachten Sie.2 Typen für Geldbeträge Anmerkung Der Typ money ist veraltet.3 erzeugt wurde. die zu nahe an null sind und nicht als verschieden von null abgespeichert werden können.oder PRIMARY KEY-Constraint erzeugen. Verwenden Sie anstelle dessen numeric oder decimal in Verbindung mit der Funktion to_char. dass diese automatische Kopplung des Löschens nicht erfolgt. den Wert zu runden. 8.3 nicht der Fall. dass NULL-Werte manuell eingefügt werden können.

varchar(n) character(n). Die Ausgabe ist im Allgemeinen im letzteren Format.) Anmerkung Vor PostgreSQL 7. wenn character varying ohne Längenangabe verwendet wird. hängt allerdings von den Locale-Einstellungen ab.3 Zeichenkettentypen Name character varying(n). character ohne Längenangabe entspricht character(1). während Werte vom Typ character varying einfach den kürzeren Wert speichern. einschließlich Ganzzahlen. Lange Zeichenketten werden vom System automatisch komprimiert.000. ergibt einen Fehler. siehe Tabelle 8.4 zeigt die zur allgemeinen Verwendung gedachten Zeichenkettentypen in PostgreSQL SQL definiert zwei Zeichenkettentypen: character varying(n) und character(n).) Wenn eine Zeichenkette zugewiesen wird. der für n in der Deklaration des Datentyps ver114 . die gespeichert werden kann. haben mehrere andere SQL-Datenbankprodukte ihn auch. die überschüssigen Zeichen sind alle Leerzeichen. welcher Zeichenketten beliebiger Länge aufnehmen kann. Beide Typen können Zeichenketten bis zu n Zeichen Länge speichern. Die Speicheranforderungen für Daten dieser Typen ist 4 Bytes zuzüglich der eigentlichen Zeichen.2 wurden zu lange Zeichenketten immer ohne Fehlermeldung abgeschnitten. rund 1 GB lang. egal in welchem Zusammenhang die Umwandlung oder Zuweisung erfolgte. character(n). es sei denn. die kürzer als die angegebene Länge ist.3. (Das ist auch vom SQLStandard vorgeschrieben.Kapitel 8 Der Typ money speichert einen Geldbetrag mit einer festen Nachkommagenauigkeit. Darüber hinaus stellt PostgreSQL den Typ text zur Verfügung. Obwohl der Typ text nicht im SQL-Standard steht. Die Schreibweisen varchar(n) und char(n) sind Aliasnamen für character varying(n) bzw.47 Tabelle 8. und im Falle von character zuzüglich der auffüllenden Leerzeichen. char(n) text Beschreibung variable Länge mit Höchstgrenze feste Länge.3: Typen für Geldbeträge 8.48 bis +21474836.4: Zeichenkettentypen Tabelle 8. dann werden Werte vom Typ character mit Leerzeichen aufgefüllt. dann akzeptiert der Typ Zeichenketten beliebiger Länge. Auf jeden Fall ist die längste mögliche Zeichenkette. (Der höchste Wert. wie zum Beispiel '$1.und Fließkommazahlen-Konstanten sowie “typischen” Schreibweisen für Geldbeträge. wobei n eine positive ganze Zahl ist. Der Versuch. dann werden sie bis zur zugelassenen Länge der Zeichenkette abgeschnitten. sodass die Speicherplatzanforderungen auf der Festplatte womöglich geringer sind. Letzteres ist eine Erweiterung von PostgreSQL. mit Leerzeichen aufgefüllt variable Länge ohne Höchstgrenze Tabelle 8. dann werden zu lange Werte ohne Fehlermeldung auf n Zeichen abgeschnitten. (Diese etwas bizarre Ausnahme wird vom SQL-Standard vorgeschrieben. Außerdem werden lange Werte in separaten Tabellen gespeichert.00'. Name money Speichergröße 4 Bytes Beschreibung Geldbetrag Reichweite -21474836. Wenn ein Wert ausdrücklich in den Typ character varying(n) oder character(n) umgewandelt wird (Cast). Die Eingabe kann in verschiedenen Formaten getätigt werden. damit sie den schnellen Zugriff auf kürzere Spaltenwerte nicht erschweren. eine längere Zeichenkette zu speichern.

Der Typ "char" (achten Sie auf die Anführungszeichen) unterscheidet sich von char(1) dadurch. SELECT a. Wenn Sie längere Zeichenketten ohne bestimmte Obergrenze speichern wollen. b | char_length -------+------------ok | 2 gut | 5 zu la | 5 Listing 8. Name "char" name Speichergröße 1 Byte 64 Bytes Beschreibung interner Typ für ein Zeichen interner Typ für Objektnamen Tabelle 8. char_length(b) FROM test2. In Kapitel 4 Abschnitt Zeichenkettenkonstanten finden Sie Informationen über die Syntax von Zeichenkettenkonstanten und in Kapitel 9 Informationen über die verfügbaren Operatoren und Funktionen. dann verwenden Sie text oder character varying ohne Längenangabe. -. In den internen Systemkatalogen wird er quasi als Aufzählungstyp für Arme verwendet. ERROR: value too long for type character varying(5) INSERT INTO test2 VALUES ('zu lang'::varchar(5)). außer den höheren Speicheranforderungen des Typs character wegen der Auffüllung mit Leerzeichen. ist aber kleiner. dass er nur ein Byte Speicherplatz braucht.5: Spezielle Zeichenkettentypen 115 .5 gezeigt werden. char_length(a) FROM test1. INSERT INTO test2 VALUES ('ok').ausdrückliche Umwandlung SELECT b.1: Verwendung der Zeichenkettentypen Die Funktion char_length ist in Abschnitt 9. -a | char_length ------+------------ok | 4 CREATE TABLE test2 (b varchar(5)). Seine Länge ist 64 Bytes (63 verwendbare Bytes und eine Abschlussmarkierung) definiert und ist in der Konstante NAMEDATALEN festgelegt. Es gibt zwei weitere Typen für Zeichenketten mit fester Länge in PostgreSQL. Es wäre nicht sonderlich nützlich.Datentypen wendet werden kann.1: Verwendung der Zeichenkettentypen CREATE TABLE test1 (a character(4)). welche in Tabelle 8. der Standardwert könnte in der Zukunft einmal ein anderer sein. INSERT INTO test1 VALUES ('ok'). anstatt willkürlich eine Obergrenze zu erfinden. Die Länge wird bei der Compilierung festgelegt (und kann daher für besondere Zwecke verändert werden). denn mit mehrbytigen Zeichenkodierungen kann die Zahl der Zeichen und die Zahl der Bytes sowieso ziemlich unterschiedlich sein. INSERT INTO test2 VALUES ('zu lang'). Der Typ name existiert ausschließlich für die Speicherung von Namen in den internen Systemkatalogen und ist nicht für Endanwender vorgesehen.) Tipp Es gibt keine Leistungsunterschiede zwischen diesen Typen.4 besprochen. das zu ändern. INSERT INTO test2 VALUES ('gut '). Beispiel 8.

Wenn man zum Beispiel eine Zeichenkettenkonstante '\\001' an den Server schickt. Der Grund. Das Byte mit dem Dezimalwert 92 (Backslash) hat eine besondere Darstellung in der Ausgabe. bleibt davon nach der Verarbeitung der Zeichenkettenkonstante \001 übrig. Ausgabedarstellung \000 ' \\ Tabelle 8.6. wie in Tabelle 8. Name bytea Speichergröße 4 Bytes plus die eigentlichen Daten Beschreibung binäre Daten mit variabler Länge Tabelle 8. zwei Parseschritte im PostgreSQL-Server durchläuft. wogegen die Kodierung und Verarbeitung von Zeichenketten von Locale-Einstellungen abhängt. schreiben müssen. Einzelheiten stehen in Tabelle 8. Wenn ein bytea-Wert als Zeichenkettenkonstante in einem SQL-Befehl eingegeben wird. Die meisten “druckbaren” Bytes werden ihre normale Darstellung im Zeichensatz des Clients behalten.6: Typen für binäre Daten Binäre Daten sind eine Reihe von Bytes. dass das Ergebnis jedes Beispiels in Tabelle 8. die als Zeichenkettenkonstante geschrieben wird. SELECT '\\\\'::bytea. Beachten Sie. siehe Tabelle 8. wo er in ein einzelnes Byte mit dem Wert 1 verwandelt wird. Um ein Byte zu umschreiben. (Siehe auch Kapitel 4 Abschnitt Zeichenkettenkonstanten. wandeln Sie es in eine dreistellige Oktalzahl um und schreiben davor zwei Backslashes.7 genau eine Byte Länge hat. Prinzipiell wird jedes “nicht druckbare” Byte in seinen entsprechenden dreistelligen Oktalwert umgewandelt und ein Backslash vorangestellt.4 Typen für binäre Daten Der Typ bytea ermöglicht die Speicherung von binären Daten.7: Fluchtfolgen für bytea-Konstanten Beachten Sie.7 gezeigt. 8.8. dass eine Eingabe. SELECT '\''::bytea.Kapitel 8 Die Funktion char_length ist in Abschnitt 9. Dezimaler Bytewert 0 39 92 Beschreibung Null-Byte Apostroph Backslash Eingabedarstellung als Fluchtfolge '\\000' '\'' or '\\047' '\\\\' or '\\134' Beispiel SELECT '\\000'::bytea.7 gezeigt. ist. obwohl die Ausgabedarstellung des Null-Bytes und des Backslashes mehrere Zeichen lang ist. Der erste Backslash jedes Paars wird bei der Analyse der Zeichenkettenkonstante als Fluchtzeichen erkannt und wird entfernt. dass Sie so viele Backslashes. sondern den normalen Regeln für Zeichenkettenkonstanten folgt. Der Wert \001 wird dann an die Eingabefunktion des Typs bytea übergeben. Der verbliebene Backslash wird dann von der bytea-Eingabefunktion erkannt. dass das Apostrophzeichen von bytea nicht gesondert behandelt wird. wie in Tabelle 8. wodurch der zweite Backslash übrig bleibt. müssen bestimmte Bytewerte durch Fluchtfolgen (escape sequences) umschrieben werden (aber alle Werte dürfen so umschrieben werden). Sie unterscheiden sich von Zeichenketten durch zwei Merkmale: Erstens können binäre Daten Bytes mit dem Wert null und andere “nicht druckbare” Bytes enthalten. 116 . Einige Bytewerte haben alternative Fluchtfolgen. wo er entweder eine Folge von drei Oktalziffern anführt oder als Fluchtzeichen für noch einen Backslash steht. Zweitens beziehen sich Operationen an binären Daten auf die tatsächlichen Bytes.4 besprochen.) Bytea-Werte werden auch in der Ausgabe durch Fluchtfolgen dargestellt.

9: Datums. Wenn zum Beispiel die Zeilenumbrüche automatisch angepasst werden. 12 Bytes 4 Bytes 8 Bytes Zeitspannen nur Datum nur Tageszeit -178000000 Jahre 4713 v. Ausgabeergebnis \\ \001 ~ \\ \xxx (oktaler Wert) ASCII-Zeichen Tabelle 8.u.und Zeittypen PostgreSQL unterstützt die komplette Sammlung an Datums. Ohne diese Angabe gibt es keine ausdrückliche Beschränkung.00+12 23:59:59. 117 .Z. haben Sie vielleicht noch etwas mehr Arbeit.und Zeittypen aus dem SQL-Standard. aber die verfügbaren Funktionen und Operatoren sind im Großen und Ganzen gleich. SELECT '\\001'::bytea.u. Der erlaubte Bereich für p ist 0 bis 6 für die Typen timestamp und interval.Z. und 0 bis 13 für die time-Typen. Das Eingabeformat unterscheidet sich von bytea. 1465001 u. welche in Tabelle 8.Datentypen Dezimaler Bytewert 92 0 bis 31 und 127 bis 255 32 bis 126 Beschreibung Backslash “nicht druckbare” Bytes “druckbare” Bytes Ausgabe durch Fluchtfolge Beispiel SELECT '\\134'::bytea.5 Datums. Genauigkeit 1 Mikrosekunde / 14 Stellen 1 Mikrosekunde / 14 Stellen 1 Mikrosekunde 1 Tag 1 Mikrosekunde 8 Bytes Datum und Zeit 4713 v. SELECT '\\176'::bytea.99-12 1 Mikrosekunde Tabelle 8.Z. um das zu verhindern.9 gezeigt werden.00 178000000 Jahre 32767 u. wie viele Nachkommastellen im Sekundenfeld abgespeichert werden. 8.Z. 00:00:00. nämlich BLOB oder BINARY LARGE OBJECT. welche Clientschnittstelle für PostgreSQL Sie verwenden.Z. müssen Sie diese womöglich auch durch Fluchtfolgen darstellen. 23:59:59. Der SQL-Standard sieht einen anderen Typ für binäre Daten vor.Z.8: Fluchtfolgen in bytea-Ausgaben Je nachdem. Name timestamp [ (p) ] [ without time zone ] timestamp [ (p) ] with time zone interval [ (p) ] date time [ (p) ] [ without time zone ] time [ (p) ] with time zone Speichergröße Beschreibung 8 Bytes Datum und Zeit Niedrigster Wert Höchster Wert 4713 v.99 12 Bytes nur Tageszeit 00:00:00. 1465001 u. timestamp und interval kann wahlweise die Genauigkeit p angegeben werden.u.und Zeittypen Bei den Typen time. welche aussagt. um die bytea-Werte ordentlich verarbeiten zu können.

Das wurde geändert. Genauere Informationen finden Sie in Kapitel 4 Abschnitt Konstanten anderer Typen. bevorzugt 118 . dann wird die Genauigkeit des angegebenen Werts verwendet.Kapitel 8 Anmerkung Wenn timestamp-Werte als Fließkommazahlen gespeichert werden (gegenwärtig die Vorgabe). dass Datums. timestamp without time zone und timestamp with time zone für die Anforderungen aller Anwendungen aus. 8. Die zulässigen Werte finden Sie oben. dann ist die Mikrosekundengenauigkeit im gesamten Wertebereich verfügbar. dem traditionellen POSTGRES-Format und anderer. 1999 1999-01-08 Tabelle 8.2000 gespeichert und die Mikrosekundengenauigkeit wird für Werte innerhalb einiger Jahre um den 1.3 war timestamp gleichbedeutend mit timestamp with time zone. In der Regel reichen die Typen date.1 Eingabeformate für Datum und Zeit Datum und Zeit können in vielen verschiedenen Formaten eingegeben werden. Die genauen Parseregeln finden Sie in Anhang A.2000 herum erreicht. einschließlich ISO 8601. Wochentag und Zeitzone gelistet sind.10 zeigt mögliche Eingabewert für den Typ date. der Befehl SET datestyle TO 'US' oder SET datestyle TO 'NonEuropean' wählt die Variante “Monat vor Tag”.1. die wahlweise die Anzahl der Nachkommastellen im Sekundenfeld bestimmt. In einigen Formaten kann die Reihenfolge von Monat und Tag in Datumsangaben zweideutig sein und daher gibt es eine Möglichkeit. Die Genauigkeit kann für time. um dem SQL-Standard zu entsprechen. Sie sollten diese Typen in neuen Anwendungen nicht verwenden und etwaige alte Anwendungen auf die neuen Typen umändern. timestamp und interval angegeben werden. Anmerkung Vor PostgreSQL 7. die die Nützlichkeit dieses Typs infrage stellen. Die Werte werden als Sekunden seit dem 1. die erwartete Reihenfolge dieser Felder einzustellen. Der Typ time with time zone ist vom SQL-Standard definiert. Die Typen abstime und reltime sind Typen mit niedrigerer Genauigkeit für interne Aufgaben. time.und Zeitkonstanten wie Zeichenketten zwischen Apostrophen stehen müssen. Wenn timestamp-Werte als 8-Byte-Ganzzahlen gespeichert werden (eine Option bei der Compilierung). Der Befehl SET datestyle TO 'European' wählt die Variante “Tag vor Monat”. SQL verlangt die folgende Syntax: typ [ (p) ] 'wert' wobei p eine ganze Zahl ist. aber die Genauigkeit lässt für weiter entfernte Zeitpunkte nach. als der SQL-Standard erfordert.1. Wenn keine Genauigkeit angegeben wurde. SQL-kompatibel. aber die Definition hat einige Eigenschaften. kann die tatsächliche Genauigkeit weniger als 6 Stellen sein. PostgreSQL ist bei der Verarbeitung von Datums. date-Werte Tabelle 8. wo auch die erlaubten Werte für die Textfelder Monat. Diese internen Typen könnten in einer zukünftigen Version verschwinden. Beachten Sie.5.und Zeiteingaben viel flexibler.10: Datumseingabe Beschreibung englisch ausgeschrieben ISO-8601-Format. Beispiel January 8.

11: Zeiteingabe Der Typ time with time zone akzeptiert alle Eingabewerte.12 gezeigt. Tag Jahr und Tag innerhalb des Jahres Jahr und Tag innerhalb des Jahres Julianischer Tag Jahr 99 vor unserer Zeitrechnung time-Werte Tabelle 8. (Siehe Tabelle 8. 18. Monat. AM hat keinen Einfluss identisch mit 16:05.789 04:05:06 04:05 040506 04:05 AM 04:05 PM allballs Beschreibung ISO 8601 ISO 8601 ISO 8601 ISO 8601 identisch mit 04:05. 1. Tag ISO-8601. alles wahlweise gefolgt von einer Zeitzonenangabe. Januar im US-Modus. Januar in jedem Modus ISO-8601. August im europäischen Modus) US-Schreibweise.12: Zeiteingabe mit Zeitzone Mehr Beispiele für Zeitzonen finden Sie in Tabelle 8. timestamp-Werte Gültige Eingabewerte für die Typen timestamp und timestamp with time zone bestehen aus einem Datum gefolgt von einer Zeitangabe und wahlweise einem AD (englisch für unsere Zeitrechnung) oder BC (vor unserer Zeitrechnung). Beispiel 04:05:06.) Beschreibung zweideutig (8. Jahr. Stunde muss <= 12 sein identisch mit 00:00:00 Tabelle 8. Beispiel 04:05:06.11 zeigt gü (Forts.10: Datumseingabe (Forts. 99 BC Tabelle 8.789-8 04:05:06-08:00 04:05-08:00 040506-08 Beschreibung ISO 8601 ISO 8601 ISO 8601 ISO 8601 Tabelle 8. wie in Tabelle 8.13.Datentypen Beispiel 1/8/1999 1/18/1999 19990108 990108 1999. Monat.)ltige Eingabewerte für den Typ time. gefolgt von einer gültigen Zeitzonenangabe. Jahr. die für time gültig sind.008 99008 J2451187 January 8.) Also sind 1999-01-08 04:05:06 119 .13.

und Zeitangaben der entsprechenden Datentypen verwendet werden: CURRENT_DATE (aktuelles Datum). Minuten und Sekunden können ohne ausdrückliche Einheiten angegeben werden. millennium ( Jahrtausend). wird angenommen. Um die Zeit in einer anderen Zeitzone zu sehen. CURRENT_TIME (aktuelle Zeit). minute (Minute).3). 120 . auch bekannt als Greenwich Mean Time/GMT) abgespeichert.. Die Werte in den unterschiedlichen Einheiten werden automatisch unter Beachtung der Vorzeichen zusammengezählt. Ein Eingabewert. einheit eines der Folgenden ist: second (Sekunde). richtung kann ago oder leer sein. dass der Wert in der aktuellen Systemzeitzone ist (welche durch den Parameter timezone festgelegt ist) und wird dementsprechend nach UTC umgewandelt. der Ergebniswert wird nur aus den Datums. ändern Sie entweder den Parameter timezone oder verwenden die Klausel AT TIME ZONE (siehe Abschnitt 9. hour (Stunde). oder eine Abkürzung oder die Mehrzahl von einer dieser Einheiten. Eine andere Zeitzone kann für die Umwandlungen mit der Klausel AT TIME ZONE angegeben werden. Stunden. week (Woche). Das heißt.] [richtung] Wobei: zahl eine Zahl (möglicherweise mit Vorzeichen) ist.Kapitel 8 und 1999-01-08 04:05:06 -8:00 gültige Werte. Werte für Tage. month (Monat). Darüber hinaus wird das weit verbreitete Format January 8 04:05:06 1999 PST unterstützt. dass der Wert für timestamp without time zone in der aktuellen Systemzeitzone stehen soll. wobei ago für eine negative Zeitspanne steht. century ( Jahrhundert).13: Zeitzoneneingabe interval-Werte Werte vom Typ interval können mit der folgenden Syntax geschrieben werden: [@] zahl einheit [zahl einheit. welche dem ISO-8601-Standard folgen. Umwandlungen zwischen timestamp without time zone und timestamp with time zone gehen normalerweise davon aus. Zum Beispiel: '1 12:59:10' entspricht '1 day 12 hours 59 min 10 sec'. Bei timestamp [without time zone] werden ausdrückliche Zeitzonenangaben still ignoriert. dann wird der Wert wiederum von UTC in die aktuelle Systemzeitzone umgewandelt und als lokale Zeit in dieser Zone ausgegeben. Das At-Zeichen (@) ist optional und hat keine Bedeutung. day (Tag). wird entsprechend der Zeitzone in UTC umgewandelt. Besondere Werte Die folgenden SQL-kompatiblen Funktionen können als Datums. Beispiel MEZ +1:00 +100 +1 Beschreibung Mitteleuropäische Zeit Zeitunterschied für MEZ nach ISO 8601 Zeitunterschied für MEZ nach ISO 8601 Zeitunterschied für MEZ nach ISO 8601 Tabelle 8. decade ( Jahrzehnt). Wenn keine Zeitzone angegeben ist. der eine Zeitzonenangabe enthält. Wenn ein Wert des Typs timestamp with time zone ausgegeben werden soll.8. Bei timestamp with time zone wird der Wert intern immer in UTC (Universal Coordinated Time. year ( Jahr)..und Zeitfeldern im Eingabewert ermittelt und nicht der Zeitzone wegen angepasst.

time.00 PST Wed Dec 17 07:37:16 1997 PST 17.14 gezeigt.und Zeiteingabewerte 8. Alle diese Werte werden wie normale Konstanten behandelt und müssen in halbe Anführungszeichen gesetzt werden. Dazu wird der Befehl SET datestyle verwendet.00 PST Tabelle 8. Der Name des Formats “SQL” ist ein Fehler der Geschichte.4. 121 . Die Ausgabe der Typen date und time ist natürlich immer nur der jeweilige Datums.8.1997 07:37:16.12.und Zeittypen kann auf vier Stile gesetzt werden: ISO 8601.16 zeigt ein Beispiel.15: Ausgabestile für Datum und Zei Der Stil SQL hat eine europäische und eine nicht-europäische (US) Variante.) Tabelle 8. Die Vorgabe ist das ISO-Format. die der Bequemlichkeit dienen können.5. timestamp date.und Zeiteingabewerte. SQL (Ingres). später als alle anderen Zeiten negativ unendlich.15 zeigt Beispiele für jeden Stil. traditioneller POSTGRES-Stil und Deutsch (German). ob der Monat vor oder nach dem Tag steht.oder Zeitteil der Beispiele. timestamp timestamp timestamp date. früher als alle anderen Zeiten Zeit der aktuellen Transaktion heute um Mitternacht morgen um Mitternacht gestern um Mitternacht 00:00:00. timestamp date.5.Datentypen CURRENT_TIMESTAMP (aktuelle Zeit mit Datum). die bei der Eingabe in normale Daten und Zeiten umgewandelt werden. (Der SQL-Standard verlangt die Verwendung des ISO-8601Formats. Die letzteren beiden akzeptieren auch eine optionale Genauigkeitsangabe.) PostgreSQL unterstützt auch mehrere besondere Datums. Sie werden in Tabelle 8. z Gültige Typen date. allballs. Die Werte infinity und -infinity werden im System gesondert gespeichert und auch genauso wieder ausgegeben. wie diese Einstellung die Interpretation der Eingabewerte beeinflusst. timestamp date.14: Besondere Datums. timestamp time Beschreibung 1970-01-01 00:00:00+00 (Unix-Systemzeit null) unendlich. Stilangabe ISO SQL POSTGRES German Beschreibung ISO-8601-/SQL-Standard traditioneller Stil ursprünglicher Stil deutscher Stil Beispiel 1997-12-17 07:37:16-08 17/12/1997 07:37:16. Eingabe epoch infinity -infinity now today tomorrow yesterday zulu. (Lesen Sie auch in Abschnitt 8.2 Ausgabeformate für Datum und Zeit Das Ausgabeformat der Datums. welche bestimmt. wogegen die anderen einfach Abkürzungen sind. (Siehe auch Abschnitt 9.1.) Tabelle 8.00 UTC Tabelle 8.

❏ Der Parameter timezone kann in der Konfigurationsdatei postgresql. 122 . Die Zeitzonen wurden rund um die Welt während des 20. wenn sich arithmetische Berechnungen über die Umstellungsdaten erstrecken.00 CET 12/17/1997 07:37:16.Kapitel 8 Stilangabe European US Tabelle 8. weil die Zeitzonenunterschiede sich während des Jahres ändern können (Sommerzeit). PostgreSQLstrebt an. Da PostgreSQL die Zeitzonenunterstützung aus dem Betriebssystem verwendet. die nur ein Datum oder nur die Zeit enthalten. ] ] [ tage ] [ stunden:minuten:sekunden ] Die Ausgabestile können vom Benutzer mit dem Befehl SET datestyle. PostgreSQL verwendet die Funktionen des Betriebssystems. Zwei offensichtliche Probleme sind: ❏ Obwohl der Typ date keine Zeitzone hat. können dadurch aber Sommerzeit und andere Besonderheiten unterstützt werden. in der lokalen Zeitzone sind. wenn sie nicht sowohl zu einem Datum als auch zu einer Zeit gehört.3 Zeitzonen Zeitzonen und ihr Gebrauch werden von politischen Entscheidungen beeinflusst. Im ISO-Modus sieht die Ausgabe so aus: [ zahl einheit [ .16: Datumsformate Beschreibung tag/monat/jahr monat/tag/jahr Beispiel 17/12/1997 15:37:16.conf gesetzt werden. timestamp with time zone und time with time zone verwenden Zeitzoneninformationen nur in diesem Bereich und nehmen an. kann der Typ time eine haben. zu entsprechen. die für normale Anwendungen von Belang sind. und sind folglich. dass Typen. Es gibt mehrere Wege. In der Realität ist eine Zeitzone aber wertlos. die vom Server verwendete Zeitzone festzulegen: ❏ Wenn nichts anderes angegeben ist. Alle Daten und Zeiten werden intern in UTC abgespeichert.und Zeittypen und -fähigkeiten. empfehlen wir. dass. dem Parameter datestyle in der Konfigurationsdatei postgresql. außer dass Einheiten wie week (Woche) oder century ( Jahrhundert) in Jahre und Tage umgewandelt werden. wenn keine Clientzeitzone definiert ist. dass die Zeiten außerhalb dieses Bereichs in UTC sind. Um diesen Problemen aus dem Weg zu gehen.conf und der Umgebungsvariable PGDATESTYLE auf dem Server oder Client gesetzt werden. in der Zeitzone des Servers. Der SQL-Standard hat allerdings eine eigenartige Mischung aus Datums. PostgreSQL geht davon aus. Jahrhunderts einigermaßen standardisiert.00 PST Das Ausgabeformat des Typs interval sieht aus wie das Eingabeformat. und nicht nur durch die Geometrie der Erde. sind aber immer noch für willkürliche Änderungen anfällig. Sie dann Typen mit Datum und Zeit verwenden.und Zeitangaben zu formatieren.. um Zeitzonenunterstützung anzubieten. dem SQL-Standard in Bereichen. wenn Sie Zeitzonen verarbeiten müssen. bevor Sie an den Client geschickt werden.5.. dass Sie den Typ time with time zone nicht verwenden (obwohl er in PostgreSQL zur Unterstützung bestehender Anwendungen und zur Kompatibilität mit anderen SQL-Implementierungen vorhanden ist). Dadurch wird die Anpassung an die Sommerzeit erschwert.7) ein flexiblerer Weg. wird die Umgebungsvariable TZ auf der Servermaschine als Vorgabe verwendet. 8. ❏ Die Standardzeitzone wir als Zahlenkonstante als Unterschied zu UTC angegeben. Die Zeiten werden vom Datenbankserver in die lokale Zeitzone umgewandelt. Wir empfehlen. und diese Systeme haben in der Regel nur Informationen für die Zeit von 1902 bis 2038 (was der unterstützten Spanne der herkömmlichen Unix-Systemzeit entspricht). Datums. Außerdem ist die Formatierungsfunktion to_char (siehe Abschnitt 9.

Die Kalender. Ein dritter Zustand. nach der Verbindung einen SET TIME ZONE-Befehl an den Server zu schicken. wird sie von libpq-Anwendungen dazu verwendet. INSERT INTO test1 VALUES (TRUE. b text). ❏ Der SQL-Befehl SET TIME ZONE setzt die Zeitzone für die aktuelle Sitzung. 'sic est'). Jahrhundert in Gebrauch waren.4 Interna PostgreSQL verwendet das Julianische Datum für alle Datums. unter der Annahme. 123 .6 Der Typ boolean PostgreSQL verfügt über den standardisierten SQL-Typ boolean. dass alle Daten von 4713 v. 8. wird UTC angenommen (jedenfalls auf den meisten Systemen). geben eine interessante Lektüre ab. sind aber nicht beständig genug. boolean hat immer einen von nur zwei Zuständen: “wahr” oder “falsch”. wird in SQL durch den NULL-Wert ausgedrückt. Anmerkung Wenn eine ungültige Zeitzone angegeben wurde. die vor dem 19.u.2: Verwendung des Typs boolean CREATE TABLE test1 (a boolean.5. “unbekannt”.Datentypen ❏ Wenn die Umgebungsvariable PGTZ beim Client gesetzt ist. In Anhang A finden Sie eine vollständige Liste aller verfügbaren Zeitzonen. dass ein Jahr 365.Z. 8. bis in die ferne Zukunft korrekt vorhergesagt und berechnet werden können.und Zeitberechnungen. Das hat die praktische Eigenschaft. Beispiel 8. Gültige Konstanten für den Zustand “wahr” (englisch true) sind: TRUE 't' 'true' 'y' 'yes' '1' Für den Zustand “falsch” (englisch false) können die folgenden Werte verwendet werden: FALSE 'f' 'false' 'n' 'no' '0' Die Verwendung der Schlüsselwörter TRUE und FALSE wird bevorzugt (und entspricht dem SQL-Standard).2425 Tage lang ist. um Sie in eine moderne Datenbank einzubauen.

.) [(x1. dass Werte vom Typ boolean mit den Buchstaben t und f ausgegeben werden.y1).r> (Mittelpunkt und Radius) Tabelle 8. durchzuführen.(x2. der Punkt (point)..y1)..y1). Sie werden in Abschnitt 9. Drehung und die Ermittlung von Schnittpunkten. Siehe auch Abschnitt 9.17: Geometrische Typen Eine große Zahl Funktionen und Operatoren sind verfügbar.17 zeigt die in PostgreSQL verfügbaren geometrischen Typen. Geometrische Typen stellen zweidimensionale räumliche Objekte dar. Tipp Werte vom Typ boolean können nicht unmittelbar in andere Typen umgewandelt werden (zum Beispiel CAST (boolwert AS integer) funktioniert nicht).2: zeigt. Der elementarste Typ.(x2. a | b ---+--------t | sic est Beispiel 8. SELECT * FROM test1. Name point line lseg box path path polygon circle Speichergröße 16 Bytes 32 Bytes 32 Bytes 32 Bytes 16+16n Bytes 16+16n Bytes 40+16n Bytes 24 Bytes Beschreibung Punkt auf der Ebene Gerade (nicht voll implementiert) endliche Strecke Rechteck geschlossener Pfad (ähnlich Polygon) offener Pfad Polygon (ähnlich geschlossener Pfad) Kreis Darstellung (x. 8. a | b ---+--------t | sic est f | non est SELECT * FROM test1 WHERE a.9 beschrieben.y2)) ((x1. bildet die Grundlage für alle anderen Typen..y1).y2)) ((x1. um diverse geometrische Operationen..] ((x1. Tabelle 8..y2)) ((x1.y). Verschiebung..y1).y1). 'non est').7 Geometrische Typen boolean benötigt 1 Byte Speicherplatz... wie Dehnung.y) ((x1.12. 124 .(x2. Man kann dies aber durch den CASE-Ausdruck erreichen: CASE WHEN boolwert THEN 'Wert wenn wahr' ELSE 'Wert wenn falsch' END.Kapitel 8 INSERT INTO test1 VALUES (FALSE.) <(x.

3 Rechtecke Der Typ box speichert ein Rechteck.. Andere Ecken können auch eingegeben werden. y2 ) x1 . Die Ecken werden sortiert. wenn der erste und der letzte Punkt nicht verbunden sind. . . x2 . . Eckige Klammern ([]) ergeben einen offenen und runde Klammern (()) einen geschlossenen Pfad. Rechtecke werden durch ein Paar gegenüberliegende Ecken dargestellt. ( xn ..y1) und (x2. ( x2 . Die Syntax ist folgende: ( ( x1 . y1 ) . 8. . y ) x . ( xn . 8.7.. y2 ) ) ( x1 . ( x2 . aber die obere rechte und die untere linke Ecke werden aus den eingegebenen und gespeicherten Ecken berechnet. .7. . damit zuerst die obere rechte Ecke und dann die untere linke Ecke steht. ( x2 . . y1 ) . y1 . oder geschlossen. um festzulegen.7.y1) und (x2... y2 ) x1 . .7. Werte vom Typ path werden mit der folgenden Syntax angegeben: ( ( ( ( ( x1 x1 x1 x1 x1 . x2 .. ( xn . Das Ausgabeformat entspricht der ersten Syntax.y2) die Endpunkte der Strecke sind. aus denen sich der Pfad zusammensetzt. y1 .4 Pfade Der Typ path speichert einen Pfad.2 Strecken Der Typ lseg speichert eine Strecke (englisch line segment). . . .. . xn . Das Ausgabeformat entspricht der ersten Syntax. ( x2 . y1 ) .Datentypen 8. 125 . Strecken werden durch ein Paar Punkte dargestellt. y1 ) . yn y1 ) . 8. y1 ) . wenn der erste und der letzte Punkt verbunden sind. y2 wobei (x1. y wo x und y die entsprechenden Koordinaten als Fließkommazahlen sind. . . y2 ) ) ( x1 . xn . Ein Pfad kann offen sein.y2) die gegenüberliegenden Ecken des Rechtecks sind.. yn y1 ) .1 Punkte Der Typ point speichert einen Punkt. und die Funktionen isopen(p) und isclosed(p) stehen zur Verfügung um die Art in einem Ausdruck zu prüfen. ob ein Pfad offen oder geschlossen sein soll. Die Syntax ist folgende: ( ( x1 .. y2 wobei (x1. Punkte sind auch die grundlegenden Bausteine aller anderen geometrischen Typen. Werte vom Typ point werden mit der folgenden Syntax angegeben: ( x . Die Funktionen popen(p) und pclose(p) stehen zur Verfügung. yn y1 . yn ) ) [ ) ] ) ) wobei die Punkte die Endpunkte der Strecken sind. yn y1 ..

Wenn Sie nur Netzwerke speichern wollen. Name cidr inet macaddr Speichergröße 12 Bytes 12 Bytes 6 Bytes Beschreibung IP-Netzwerke IP-Hosts und -Netzwerke MAC-Adressen Tabelle 8.7. y1 . werden aber anders gespeichert und haben einen getrennten Satz Funktionen verfügbar. gibt der Wert kein Subnetz an. 8. Das Ausgabeformat entspricht der ersten Syntax.1 inet Der Typ inet speichert eine IP-Hostadresse und wahlweise die Identität des Subnetzes. r ) y ) .8..8 Typen für Netzwerkadressen PostgreSQL bietet Datentypen. wie viele Bits der Hostadresse die Netzwerkadresse darstellen (die “Netzmaske”).Kapitel 8 8. . Die Subnetzidentität wird ausgedrückt. xn ..und MAC-Adressen zu speichern.. in dem der Host ist. y1 . 8. . ( xn . 8. welche in Tabelle 8. .18 gezeigt werden.18: Typen für Netzwerkadressen IPv6 wird noch nicht unterstützt. x1 .. r y .. . . r > y ) . ( x1 . y1 ) . . yn ) ) yn ) yn ) yn wobei die Punkte die Endpunkte der Strecken sind. Werte vom Typ polygon werden mit der folgenden Syntax angegeben: ( ( x1 . . . ( xn . y1 ) . xn . .. Polygone entsprechen in gewisser Weise geschlossenen Pfaden. indem angegeben wird. Das Ausgabeformat entspricht der ersten Syntax.. da diese Typen die Eingabewerte prüfen und es spezialisierte Operatoren und Funktionen für sie gibt. y ) . diese Typen statt normaler Texttypen zu verwenden. Die Syntax ist folgende: < ( x ( ( x ( x x wobei (x. beides in einem Wert.y) der Mittelpunkt und r der Radius des Kreises sind. ..6 Kreise .7. ( x1 . Kreise werden durch den Mittelpunkt und den Radius dargestellt. die das Polygon begrenzen. . sollten Sie den Typ cidr statt inet verwenden. 126 . sondern nur einen einzelnen Host. r Der Typ circle speichert einen Kreis.5 Polygone Der Typ polygon speichert ein Polygon (Vieleck). um IP. Es ist empfehlenswert. Wenn die Netzmaske 32 ist.

0.1 128 128. dann ist die Netzmaske 32 und der Wert steht für einen einzelnen Host.0/24 128.2 10.8.x. Es ist ein Fehler. Das Format.Datentypen Das Eingabeformat für diesen Typ ist x.x. cidr Der Hauptunterschied zwischen den Datentypen inet und cidr ist.0/24 128. Als Eingabe werden verschiedene gebräuchliche Formate akzeptiert.128/25 192.2/24 10.2/24 10.1.x.1.0/8 abbrev(cidr) 192.128/25 192.0.168/24 192.100.0.168.x. einschließlich 127 .0/24 10. um ein Netzwerk anzugeben. Eingabe.0/25 192. wobei x.0/25 192.x.168.8. eine Netzwerkadresse anzugeben.0/24 192.0/24 10. dass inet gesetzte Bits rechts von der Netzmaske zulässt und cidr nicht.1/16 10/8 Tabelle 8. cidr-Eingabe 192. dass die Bitmaske mindestens groß genug sein muss.100.x. Tipp Wenn Sie die Ausgabeformate von inet oder cidr nicht mögen.168. das heißt die Hardwareadressen von Ethernetkarten (obwohl MAC-Adressen auch für andere Zwecke verwendet werden).168 128.x/ y.0/16 128.1.168.168. mit der Ausnahme.168. dann wird es aus den Annahmen des alten klassen-orientierten Netzwerknummerierungssystems errechnet.0.8.168/25 192.1.x eine IP-Adresse ist und y die Anzahl der Bits in der Netzmaske. Bei der Ausgabe wird der /y-Teil weggelassen. Wenn /y ausgelassen wird. wobei x.2 cidr Der Typ cidr speichert die Identität eines IP-Netzwerks.und Ausgabeformate folgen den Vorgaben des Classless Internet Domain Routing Systems.168. 8.0.1.0/16 128.1.1 10 cidr-Ausgabe 192.19: Eingabebeispiele für den Typ cidr 8.19 zeigt einige Beispiele.168. die Bits rechts von der angegebenen Netzmaske gesetzt hat. Wenn y ausgelassen wird.1/16 128.0.1.x ein Netzwerk und y die Anzahl von Bits in der Netzmaske ist.100.1 192.168.0. dann versuchen Sie die Funktionen host.0.0/24 192.0.168. text und abbrev.x/y. 8.x.0/16 10.4 macaddr Der Typ macaddr speichert MAC-Adressen. Tabelle 8.2.2.1/24 192.0/16 128.1.0.168.1. ist x.2 10. um alle Oktetts im Eingabewert einzuschließen.0/24 192.128/25 192. wenn die Netzmaske 32 ist.3 inet vs.168.x.

Daten vom Typ bit varying sind variabel in der Länge bis zur Höchstlänge n. B'101'). 8. Für die Ziffern a bis f werden Groß. es ist ein Fehler zu versuchen.und Kleinbuchstaben akzeptiert. egal in welchem Anmerkung Wenn man einen Bitkettenwert ausdrücklich in bit(n) umwandelt (Cast). Beispiel 8. die verwendet werden können. dann wird er rechts abgeschnitten. Das wurde geändert. Anmerkung Vor PostgreSQL 7. um aus MAC-Adressen die Namen der Hardwarehersteller zu ermitteln. a | b -----+----101 | 00 100 | 101 128 . siehe Kapitel 9. wogegen bit varying ohne Längenangabe eine unbegrenzte Länge zult Nullen erweitert. b BIT VARYING(5)).Kapitel 8 '08002b:010203' '08002b-010203' '0800. wenn er länger als n Bits ist. INSERT INTO test VALUES (B'10'. INSERT INTO test VALUES (B'101'. SELECT * FROM test. B'00'). Bitlogische Operatoren sowie Funktionen zur Bitkettenmanipulation sind auch verfügbar. ERROR: Bit string length 2 does not match type BIT(3) INSERT INTO test VALUES (B'10'::bit(3). Das Verzeichnis contrib/mac in der PostgreSQL-Quelltext-Distribution enthält einige Werkzeuge. einen kürzeren oder längeren Wert zu speichern.0203' '08-00-2b-01-02-03' '08:00:2b:01:02:03' welche alle die gleiche Adresse angeben würden. Ebenso gilt. wird er rechts gekürzt oder mit Nullen erweitert. Sie können verwendet werden. um Bitmasken zu speichern oder darzustellen. egal in welchem Zusammenhang die Zuweisung oder Umwandlung erfolgte. Es gibt zwei SQL-Typen für Bitketten: bit(n) und bit varying(n). damit er genau n Bits lang wird. Schauen Sie in Kapitel 4 Abschnitt Bitkettenkonstanten für Informationen über die Syntax von Bitkettenkonstanten.9 Bitkettentypen Bitketten sind Ketten von Einsen und Nullen. B'101').2 wurden Bitwerte immer still abgeschnitten oder mit Nullen erweitert.3: Verwendung der Bitkettentypens CREATE TABLE test (a BIT(3). Eine Typangabe bit ist gleichbedeutend mit bit(1). wo n eine positive ganze Zahl ist. längere Werte werden nicht akzeptiert. um dem SQLStandard zu entsprechen. wenn ein Bitkettenwert ausdrücklich in bit varying(n) umgewandelt wird.2b01. Das Ausgabeformat entspricht immer der letzten gezeigten Form. Daten vom Typ bit müssen genau der Länge n entsprechen.

der vom System verwendet wird. (Wenn Sie das tun.) Name oid regproc regprocedure regoper regoperator regclass regtype Verweis beliebig pg_proc pg_proc pg_operator pg_operator pg_class pg_type Beschreibung numerischer Objekt-Identifikator Funktionsname Funktion mit Argumenttypen Operatorname Operator mit Argumenttypen Relationsname Datentypname Wertbeispiel 564182 sum sum(int4) + *(integer. Daher ist er nicht groß genug. der vom System verwendet wird. Am besten sollten OIDs nur für Verweise auf die Systemtabellen verwendet werden. um die richtige OID zu finden.20: Objekt-Identifikator-Typen Alle OID-Aliastypen akzeptieren schemaqualifizierte Namen und geben diese aus. der Transaktions-Identifikator. Eine ctid ist ein Paar (Blocknummer. Ein dritter Identifikator-Typ. indem man NONE für den nicht benutzten Operand schreibt. wenn das Objekt im aktuellen Suchpfad nicht ohne ausdrückliche Schemaangabe gefunden würde. das die physikalische Stelle der Zeilenversion innerhalb seiner Tabelle angibt. wenn es mehrere Tabellen namens meinetabelle in verschiedenen Schemas gibt. Daher ist es nicht empfehlenswert. Der Typ oid hat selbst kaum Operationen außer Vergleichsoperationen. regoper. Der Typ oid ist gegenwärtig ein 4-Byte-Ganzzahlentyp ohne Vorzeichen. wenn die Tabelle erzeugt wird). ist xid. Bei regoperator kann man unäre Operatoren angeben.) Die OID-Aliastypen haben keine eigenen Operationen außer den spezialisierten Eingabe. regprocedure. Transaktionsnummern sind 32 Bit groß. Das ist der Datentyp der Systemspalten xmin und xmax. (In Wirklichkeit müsste man eine viel kompliziertere Anfrage verwenden. ist tid (tuple identifier). Der Typ oid speichert einen Objekt-Identifikator.und Ausgaberoutinen. meistens sind regprocedure bzw. die OID-Spalte einer benutzerdefinierten Tabelle als Primärschlüssel zu verwenden. Es gibt auch mehrere Aliastypen für oid: regproc.) 129 .2 erläutert.20 zeigt einen Überblick.integer) pg_type integer Tabelle 8. ist cid (command identifier). die eindeutig (nicht überladen) sind. um die OID der Tabelle meinetabelle zu erfahren. sind also von begrenztem Nutzen. Index im Block). regoperator sinnvoller. regoperator. Das ist der Datentyp der Systemspalte ctid. achten Sie aber auf mögliche Verwirrungen über die Vorzeichen. Ein weiterer Identifikator-Typ. Die Aliastypen gestatten eine vereinfachte Suche nach der OID von Systemobjekten: Zum Beispiel kann man schreiben 'meinetabelle'::regclass. (Die Systemspalten werden im Einzelnen in Abschnitt 5. cid-Werte sind auch 32 Bit groß.10 Objekt-Identifikator-Typen Objekt-Identifikatoren (OIDs) werden von PostgreSQL intern als Primärschlüssel in diversen Systemtabellen verwendet. Man kann ihn aber in integer umwandeln und ihn mit den normalen numerischen Operationen bearbeiten. Die Typen regproc und regoper akzeptieren nur Namen als Eingabe. Das ist der Datentyp der Systemspalten cmin und cmax.integer) oder (NONE. um in der ganzen Datenbank oder sogar in einzelnen großen Tabellen eindeutig sein zu können. der vom System verwendet wird.Datentypen 8. Ein letzter Identifikator-Typ. Eine OID-Systemspalte wird auch jeder benutzerdefinierten Tabelle hinzugefügt (außer wenn WITHOUT OIDS angegeben wird. regclass und regtype. anstatt SELECT oid FROM pg_class WHERE relname = 'meinetabelle' schreiben zu müssen. Tabelle 8.

name -------Carola (1 row) 130 . 25000. Zuerst zeigen wir. 8.2 Eingabe von Arraywerten Jetzt können wir einige Daten einfügen. 8. quartal_gehalt integer[]. "Mittag"}. 25000}'. 10000}'. wie man auf ein einzelnes Element im Array zugreifen kann.Kapitel 8 8. Arrayelemente werden von geschweiften Klammern eingeschlossen und durch Kommas voneinander getrennt. werden Arraytypen bezeichnet. dann werden Sie diese Syntax vielleicht wiedererkennen.11. '{20000.3 Verweise auf Arraywerte Jetzt können wir einige Anfragen durchführen. '{{"Präsentation". "Beratung"}. {}}'). Das ganze Array kann auf den NULL-Wert gesetzt werden. '{10000. wo einzelne Werte NULL sind und andere nicht. plan text[][] ). Die folgende Anfrage ergibt zum Beispiel die Namen der Angestellten. 25000. erzeugen wir diese Tabelle: CREATE TABLE angestellte ( name text.11. dies irgendwann zu verbessern.11. Der obige Befehl erzeugt eine Tabelle namens angestellte mit einer Spalte vom Typ text (name). (Weiter Einzelheiten folgen unten. INSERT INTO angestellte VALUES ('Carola'. Anmerkung Gegenwärtig können einzelne Arrayelemente nicht den SQL-NULL-Wert enthalten. Wenn Sie C kennen. einem eindimensionalen Array vom Typ integer (quartal_gehalt). 10000. Arrays können aus eingebauten oder benutzerdefinierten Typen erzeugt werden. und einem zweidimensionalen Array vom Typ text (plan). welches den Wochenplan des Angestellten darstellt. Wie gezeigt. '{{"Meeting". Es ist vorgesehen. 8.) INSERT INTO angestellte VALUES ('Wilhelm'. indem eckige Klammern ([]) an den Typnamen der Arrayelemente angehängt werden. deren Gehalt sich im zweiten Quartal verändert hat: SELECT name FROM angestellte WHERE quartal_gehalt[1] <> quartal_gehalt[2].11 Arrays PostgreSQL erlaubt die Definition von Spalten als mehrdimensionalen Arraytyp mit variabler Länge. {"Meeting"}}'). aber Sie können kein Array haben.1 Deklaration von Arraytypen Um die Verwendung von Arrays zu erläutern. 10000. welches das Gehalt pro Quartal des Angestellten speichert.

Oder Teilarrays können aktualisiert werden: UPDATE angestellte SET quartal_gehalt[1:2] = '{27000. wenn ein Index nur einen Wert angibt. jeweils für eine oder mehrere Arraydimensionen. schreibt. und hätte das gleiche Ergebnis erhalten. Die Untergrenze 1 wird angenommen. Diese Anfrage ermittelt zum Beispiel den ersten Eintrag auf Wilhelms Wochenplan für die ersten zwei Tage der Woche: SELECT plan[1:2][1:1] FROM angestellte WHERE name = 'Wilhelm'. Oder einzelne Elemente können aktualisiert werden: UPDATE angestellte SET quartal_gehalt[4] = 15000 WHERE name = 'Wilhelm'. das heißt. in einem Array von Größe n fangen die Elemente bei array[1] an und enden bei array[n].Datentypen Die Arrayindexzahlen werden in eckige Klammern gesetzt. wenn mindestens ein Indexwert die Form untergrenze:obergrenze hat.27000.25000. Ein Array kann vergrößert werden.27000}' WHERE name = 'Carola'. indem man einen Wert einem Element zuweist. Ein Teilarray wird mit der folgenden Schreibweise bestimmt: untergrenze:obergrenze.{""}} (1 row) Man hätte auch schreiben können SELECT plan[1:2][1] FROM angestellte WHERE name = 'Wilhelm'. plan -------------------{{Meeting}. Die folgende Anfrage ermittelt das Gehalt von allen Angestellten im dritten Quartal: SELECT quartal_gehalt[3] FROM angestellte. oder indem man in ein Teilarray. Eine Arrayindizierung ergibt immer ein Teilarray.27000}' WHERE name = 'Carola'. quartal_gehalt ---------------10000 25000 (2 rows) Man kann auch auf beliebige Teilarrays eines Arrays zugreifen. das an vorhandene Daten angrenzt oder sich mit ihnen überschneidet. PostgreSQL zählt die Arrayelemente normalerweise von eins an. das an ein bereits vorhandenes angrenzt. wird es fünf Ele- 131 . Ein Arraywert kann komplett ersetzt werden: UPDATE angestellte SET quartal_gehalt = '{25000. Wenn zum Beispiel ein Array vorher vier Elemente hat.

um ein Array zu erzeugen. die dafür verwendet werden kann. Indem man Teilarrays Daten zuweist. die neue Funktionen und Operatoren definiert. Um das ganze Array zu durchsuchen (und nicht nur Teilarrays). Damit könnte man die obige Anfrage so schreiben: SELECT * FROM angestellte WHERE quartal_gehalt[1:4] *= 10000. Die aktuellen Dimensionen eines Arraywerts können mit der Funktion array_dims ermittelt werden: SELECT array_dims(plan) FROM angestellte WHERE name = 'Carola'. So kann man zum Beispiel Daten in array[-2:7] schreiben. Die Angabe der Dimensionen oder Größen in CREATE TABLE dient also einfach nur der Dokumentation und beeinflusst das Laufzeitverhalten nicht.[ 1:2][1:1] (1 row) array_dims erzeugt ein Ergebnis vom Typ text. ungeachtet der Zahl oder der Größe der Dimensionen.11. was für Leute gut zu lesen. die aber nicht in PostgreSQL eingebaut ist. müssen Sie jeden Wert des Arrays prüfen. Zum Beispiel: SELECT * FROM angestellte WHERE quartal_gehalt[1] quartal_gehalt[2] quartal_gehalt[3] quartal_gehalt[4] = = = = 10000 OR 10000 OR 10000 OR 10000.4 In Arrays suchen Um einen Wert in einem Array zu finden. Gegenwärtig können auf diese Art nur eindimensionale Arrays vergrößert werden. kann man Arrays erzeugen. Arrays mit einem bestimmten Elementtyp werden alle als derselbe Typ betrachtet. könnten Sie Folgendes machen: SELECT * FROM angestellte WHERE quartal_gehalt *= 10000. wo die Elemente nicht von eins an zählen.Kapitel 8 mente haben. Außerdem könnten Sie alle Zeilen finden. Das kann von Hand gemacht werden (wenn Sie die Größe des Arrays kennen). aber vielleicht nicht so prak- tisch für Programme ist. array_dims -----------. Die angegebene Zahl der Dimensionen wird im Übrigen auch nicht durchgesetzt. wenn die Arrays sehr groß sind. Es gibt eine Erweiterung. wo die Arrayelemente alle gleich 10000 sind: 132 . Das kann aber sehr umständlich sein. nicht aber mehrdimensionale. funktioniert das gar nicht. 8. Gegenwärtig werden diese Arraygrößengrenzen aber nicht durchgesetzt. das Indexwerte von -2 bis 7 hat. Das Verhalten ist genauso wie bei Arrays ohne Größenangabe. nachdem eine Aktualisierung in array[5] schreibt. und wenn die Größe des Arrays nicht bekannt ist. Die Syntax von CREATE TABLE erlaubt auch die Erzeugung von Arrays mit fester Größe: CREATE TABLE tictactoe ( kästchen integer[3][3] ).

die Sie verwenden müssen. Die Arrayausgabefunktion setzt Anführungszeichen um Elementwerte. Dadurch verdoppelt sich die Anzahl der Backslashes. dass die Datenbank falsch entworfen wurde. was Sie in einem SQL-Befehl schreiben. VALUES ('{"\\\\". Backslashes oder Whitespace am Anfang in Anführungszeichen gesetzt werden. Das Arrayfeld sollte normalerweise als eigene belle abgetrennt werden.. Leerzeichen nach Elementen werden allerdings nicht ignoriert: Nachdem die vorangehenden Leerzeichen übersprungen wurden. 8. dass sie auftreten können oder auch nicht. können Sie in einen Arraywert Anführungszeichen um die einzelnen Elemente schreiben.). die sonst Teil der Arraysyntaxdekoration oder ignorierte Leerzeichen sind. aber alle anderen Typen verwenden das Komma. Das Trennzeichen ist normalerweise das Komma (. der aus einem Backslash und einem Anführungszeichen besteht. Anmerkung Beachten Sie. Die externe Darstellung eines Arrays besteht aus den Elementen. Trennzeichen. Die Verwendung von Arrays in der beschriebenen Art und Weise ist oft ein Zeichen.11. (Das ist eine Veränderung im Verhalten gegenüber PostgreSQL-Versionen vor 7.11.. und Trennzeichen müssen zwischen den eingeklammerten Einheiten stehen. Anführungszeichen. kann aber auch ein anderes sein: Es wird durch den typdelim-Wert des Arrayelementtyps festgelegt. 8. So müssen zum Beispiel Elemente mit geschweiften Klammern. die die Struktur des Arrays angibt. Um ein Anführungszeichen oder einen Backslash in ein Arrayelement zu schreiben. (Unter den Standarddatentypen in der PostgreSQL-Distribution verwendet der Typ box das Semikolon (.) INSERT . Tabellen können Sie logischerweise ganz einfach durchsuchen.5 Array-Eingabe. dass das. Anführungszeichen. dass Anführungszeichen niemals verwendet werden. schauen Sie in das Verzeichnis conArtrib/array in der PostgreSQL-Quelltext-Distribution.). und der Dekoration. Vor Anführungszeichen und Backslashes in Elementwerten wird ein Backslash gestellt.und Ausgabesyntax Tipp Arrays sind keine Mengen. aber bei Textdatentypen sollte man darauf vorbereitet sein. Backslashes oder Whitespace enthalten. die durch die Eingabe.6 Sonderzeichen in Arrayelementen Wie oben gezeigt. Um zum Beispiel einen Arraywert einzufügen. Um dieses optionale Modul zu installieren.2.Datentypen SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000.) In mehrdimensionalen Arrays muss um jede Dimension ein Paar geschweifte Klammern stehen. Als Alternative können Sie auch einen Backslash vor alle anderen Zeichen setzen. Bei Zahlentypen kann man mit Sicherheit davon ausgehen. wenn diese leere Zeichenketten sind oder geschweifte Klammern. setzen Sie einen Backslash davor. Das ist erforderlich. wenn der Elementwert den Arrayparser verwirren könnte. müssten Sie schreiben: 133 . zuerst als Zeichenkettenkonstante verarbeitet wird und dann als Array. Diese Dekoration besteht aus geschweiften Klammern ({ und }) um den Arraywert sowie den Trennzeichen zwischen den Elementen.und Ausgaberoutinen des entsprechenden Datentyps interpretiert werden."\\""}'). Leerzeichen können vor den linken oder rechten Klammern oder vor den einzelnen Elementen stehen. Kommas (oder was das Trennzeichen sein mag). zählt alles bis zum nächsten Trennzeichen oder der rechten Klammer als zum Wert gehörend.

sind \ bzw.Kapitel 8 Bei der Verarbeitung der Zeichenkettenkonstante wird ein Satz Backslashes entfernt. wo das Verhalten der Funktion nicht einfach durch einen normalen SQL-Datentyp als Eingabe oder Ausgabe ausgedrückt werden kann. Ein obsoleter Typname. deren Eingaberoutine Backslashes besonders behandelt. dass sie trigger zurückgibt. die einen nicht näher definierten Zeilentyp zurückgibt. die in prozeduralen Sprachen geschrieben wurden. Tabelle 8."\""} aussieht. dass die Funktion sich ordnungsgemäß verhält. die wiederum bei der Eingabefunktion vom Typ text ankommen. dann kann es von SQL aus nicht aufgerufen werden. die in C geschrieben wurden (egal ob eingebaut oder dynamisch geladen). wie zum Beispiel bytea. Gibt an. sodass der Wert. Die Werte.21: Pseudotypen Beschreibung Identifiziert eine Funktion. dass die Funktion keinen Wert zurückgibt.12 Pseudotypen Das Typensystem in PostgreSQL enthält einige Typen mit besonderen Aufgaben. dass die Funktion einen internen Datentyp akzeptiert oder zurückgibt. Funktionen.) 8. folgende Regel zu beachten: Deklarieren Sie keine Funktion mit einen Rückgabetyp internal. dass sie einen dieser Pseudodatentypen als Argument oder Rückgabewert verwenden. Ein Handler für eine prozedurale Sprache wird so deklariert. ". wie {"\\". Gibt an. aber er kann als Argument. dass die Funktion jeden beliebigen Arraydatentyp akzeptiert. Der Autor der Funktion muss selbst sicherstellen. Wenn eine Funktion mindestens ein Argument vom Typ internal hat. um am Ende einen im Arrayelementwert zu speichern. Name record any anyarray void trigger language_handler cstring internal opaque Tabelle 8. dass die Funktion jeden Datentyp akzeptiert. wenn die Funktion nicht mindestens ein Argument vom Typ internal hat. wenn die Funktion als Trigger verwendet werden soll). der bei der Arrayeingabefunktion ankommt. Gibt an. Ein Pseudotyp kann nicht als Spaltentyp verwendet werden. können Pseudotypen nur verwenden. wenn es die Sprachen gestatten. dass die Funktion eine C-Zeichenkette (mit Null-Byte abgeschlossen) akzeptiert oder zurückgibt. Funktionen. (Wenn man Datentypen verwendet. die zusammenfassend Pseudotypen genannt werden. wenn einer dieser Pseudotypen als Argument verwendet wird. dann muss man mithin bis zu acht Backslashes verwenden. die nur intern vom Datenbanksystem aufgerufen werden sollen und nicht von einem SQL-Befehl aus.oder Ergebnistyp einer Funktion angegeben werden. Um in die Typensicherheit dieser Beschränkung zu erhalten. Eine Triggerfunktion wird so deklariert. Gibt an. der früher alle oben genannten Funktionen ausfüllte. 134 . Jeder der vorhandenen Pseudotypen ist in einer Situation von Nutzen. ist es wichtig. dass er language_handler zurückgibt. Gibt an. Gegenwärtig verbieten die prozeduralen Sprachen alle die Verwendung von Pseudotypen als Argument und gestatten nur void als Ergebnistyp (sowie trigger. Der Pseudotyp internal wird zur Deklaration von Funktionen verwendet.21 listet die bestehenden Pseudotypen. können so deklariert werden.

nicht im SQL-Standard definiert sind. Die Befehle \df und \do in psql können verwendet werden. wobei der NULL-Wert den Zustand “unbekannt” darstellt.1 Logische Operatoren Die gebräuchlichen logischen Operatoren sind vorhanden: AND (Konjunktion) OR (Disjunktion) NOT (Negation) SQL verwendet eine Boole'sche Logik mit drei Wertigkeiten. Beachten Sie die folgenden Wahrheitstabellen: a wahr wahr wahr falsch falsch unbekannt b wahr falsch unbekannt falsch unbekannt unbekannt a AND b wahr falsch unbekannt falsch falsch unbekannt a OR b wahr wahr wahr falsch unbekannt unbekannt 135 . dass die meisten hier beschriebenen Funktionen und Operatoren. sollten Sie beachten. Einige der Erweiterungen sind auch in anderen SQL-Datenbanken vorhanden und in vielen Fällen ist die Funktionalität zwischen den Produkten einheitlich und kompatibel. mit Ausnahme der einfachsten arithmetischen und Vergleichsoperatoren und einiger ausdrücklich markierter Funktionen. Wenn Sie auf Portierbarkeit Wert legen. Benutzer können auch eigene Funktionen und Operatoren definieren. um alle tatsächlich vorhandenen Funktionen bzw. wie in Teil V beschrieben wird. 9.9 9 Funktionen und Operatoren PostgreSQL bietet eine große Zahl Funktionen und Operatoren für die eingebauten Datentypen. Operatoren anzuzeigen.

1: Vergleichsoperatoren Anmerkung Der Operator != wird vom Parser in <> umgewandelt. Vergleichsoperatoren gibt es für alle Datentypen. So ist a BETWEEN x AND y gleichbedeutend mit a >= x AND a <= y Ebenso ist a NOT BETWEEN x AND y gleichbedeutend mit a < x OR a > y Es gibt keinen Unterschied zwischen den beiden Formen.1 gelistet. Ausdrükke wie 1 < 2 < 3 sind ungültig (weil es keinen Operator < zum Vergleichen eines Werts vom Typ boolean mit 3 gibt). die aufgewendet werden muss. Alle Vergleichsoperatoren sind binäre Operatoren (mit zwei Operanden) und haben ein Ergebnis vom Typ boolean. Es ist nicht möglich.2 Vergleichsoperatoren Die gewöhnlichen Vergleichsoperatoren sind vorhanden und werden in Tabelle 9. außer der CPU-Leistung. Operatoren mit den Namen != und <> zu erzeugen. wo dies sinnvoll ist. Um zu prüfen. ob ein Wert NULL ist. verwenden Sie die Klauseln 136 . Operator < > <= >= = <> oder != Beschreibung kleiner als größer als kleiner als oder gleich größer als oder gleich gleich ungleich Tabelle 9.Kapitel 9 a wahr falsch unbekannt NOT a falsch wahr unbekannt 9. die sich verschieden verhalten. um die erste Form intern in die zweite Form umzuschreiben. Neben den Vergleichsoperatoren gibt es die spezielle Klausel BETWEEN.

aber nicht standardisierten Formen ausdruck ISNULL ausdruck NOTNULL Verwenden Sie nicht ausdruck = NULL. 9. wenn ausdruck den NULL-Wert ergibt.5 bis 7. SET transform_null_equals TO ON.0 |/ 25.B. Ein NULL-Wert wird als der logische Wert “unbekannt” (unknown) behandelt.2 zeigt die vorhandenen mathematischen Operatoren. Werte vom Typ boolean können mit folgenden Ausdrücken getestet werden: expression expression expression expression expression expression IS IS IS IS IS IS TRUE NOT TRUE FALSE NOT FALSE UNKNOWN NOT UNKNOWN Diese sind ähnlich IS NULL in dem Sinne.2: Mathematische Operatoren 137 .Funktionen und Operatoren ausdruck IS NULL ausdruck IS NOT NULL oder die gleichbedeutenden.B.) Einige Anwendungen gehen (fälschlicherweise) davon aus. dass ausdruck = NULL wahr ist. In dem Fall wird PostgreSQL Ausdrücke der Form x = NULL in x IS NULL umwandeln.0 ^ 3. Für Typen ohne weithin bekannte mathematische Definitionen für alle Varianten (z.3 Mathematische Funktionen und Operatoren Mathematische Operatoren stehen für viele PostgreSQLPostgreSQL-Typen zur Verfügung. Datum und Zeit) beschreiben wir das Verhalten in den folgenden Abschnitten. dass sie immer wahr oder falsch ergeben und niemals den NULL-Wert. weil NULL nicht “gleich” NULL ist. kann man den Konfigurationsparameter transform_null_equals anstellen (z. Um diese Anwendungen zu unterstützen. Das war das voreingestellte Verhalten in PostgreSQL 6. Tabelle 9. Operator + * / % ^ |/ Beschreibung Addition Subtraktion Multiplikation Division (Ganzzahldivision schneidet Ergebnis ab) Rest nach Division Potenzierung Quadratwurzel Beispiel 2+3 2-3 2*3 4/2 5%4 2.1. ob zwei unbekannte Werte gleich sind.).0 Ergebnis 5 -1 6 2 1 8 5 Tabelle 9. selbst wenn ein Operand NULL ist. (Der NULL-Wert stellt einen unbekannten Wert dar und man kann nicht bestimmen.

4 3 -42 dp dp degrees(0. Beispiel B'10001' & B'01101' B'10001' | B'01101' B'10001' # B'01101' ~ B'10001' B'10001' << 3 B'10001' >> 2 Ergebnis 00001 11101 11110 01110 01000 00100 Tabelle 9.Kapitel 9 Operator ||/ ! !! @ & | # ~ << >> Beschreibung Kubikwurzel Fakultät Fakultät (Präfixoperator) Betrag bitweise Konjunktion (“und”) bitweise Disjunktion (“oder”) bitweise Alternative (“exklusiv-oder”) bitweise Negation (“nicht”) bitweises Linksschieben bitweises Rechtsschieben Beispiel ||/ 27. Funktion abs(x) cbrt(dp) ceil(dp oder numeric) degrees(dp) exp(dp oder numeric) Ergebnistyp (gleicher wie x) dp numeric Beschreibung Betrag Kubikwurzel kleinste ganze Zahl.5) exp(1.71828182845905 Tabelle 9. Wenn nichts anderes angegeben wurde. die mit dem Datentyp double precision umgehen.8) Ergebnis 17. Die Funktionen. Viele dieser Funktionen gibt es in mehreren Formen mit unterschiedlichen Argumentdatentypen. wie in der Tabelle gezeigt. sind meistens mit den Funktionen der C-Bibliothek des Betriebssystems implementiert. Die Bitkettenoperanden von &.3 gezeigt.0 91 & 15 32 | 3 17 # 5 ~1 1 << 4 8 >> 2 Ergebnis 3 120 120 5 11 35 20 -2 16 2 Tabelle 9.0) 28. Beim Bitschieben wird die ursprüngliche Länge der Bitkette erhalten. die nicht kleiner als das Argument ist Radiant in Grad umwandeln Potenzierung Beispiel abs(-17.3: Bitweise Operatoren für Bitketten Tabelle 9.4) cbrt(27. In der Tabelle steht dp für double precision. wie in Tabelle 9.) Die bitweisen Operatoren gibt es auch für die Bitkettentypen bit und bit varying.0) ceil(-42.4: Mathematische Funktionen 138 .2: Mathematische Operatoren (Forts. | und # müssen jeweils die gleiche Länge haben.6478897565412 2.0 5! !! 5 @ -5. ist der Rückgabewert von jeder Variante dieser Funktionen derselbe wie der Argumentdatentyp. die Genauigkeit und das Verhalten in Grenzfällen kann daher vom System abhängen.4 zeigt die verfügbaren mathematischen Funktionen.

0) log(100. s integer) sign(dp oder numeric) sqrt(dp) trunc(dp) trunc(numeric.14159265358979 729 729 0.4382.0) radians(45.5 die verfügbaren trigonometrischen Funktionen. 2) sign(-8.0 (wie Argument) zur nächsten ganzen Zahl runden numeric 42 42.0) random() round(42.0 und 1.und Ergebnistypen double precision. b dp) pow(a numeric.Funktionen und Operatoren Funktion floor(dp oder numeric) ln(dp oder numeric) log(dp oder numeric) log(b numeric.0.4) sqrt(2. Alle trigonometrischen Funktionen haben Argument. 2) 3.4) round(42. 3. y) cos(x) cot(x) sin(x) tan(x) Beschreibung Arkuskosinus Arkussinus Arkustangens Arkustangens von x/y Kosinus Kotangens Sinus Tangens Tabelle 9.) Schließlich zeigt Tabelle 9.785398163397448 Grad in Radiant umwandeln zufälliger Wert zwischen 0. r integer) Konstante π” a hoch b a hoch b pi() pow(9.0.5: Trigonometrische Funktionen 139 . Funktion acos(x) asin(x) atan(x) atan2(x. x numeric) mod(y.693147180559945 2 6. b numeric) radians(dp) random() round(dp or numeric) round(v numeric. 3. die nicht größer als das Argument ist natürlicher Logarithmus Logarithmus zur Basis 10 Logarithmus zur Basis b Beispiel floor(-42.8) trunc(42.0000000000 1 (gleicher wie Rest von y/x Argumenttypen ) dp dp numeric dp dp pi() pow(a dp. 64. +1) dp dp numeric Quadratwurzel Richtung null runden (abschneiden) auf r Dezimalstellen abschneiden Tabelle 9.0) pow(9.44 -1 1.8) Ergebnis -43 dp dp numeric ln(2. x) Ergebnistyp numeric Beschreibung größte ganze Zahl.0) trunc(42.4142135623731 42 42.4) 0. 0.0.0) mod(9.4382.43 auf s Dezimalstellen runden (wie Argument) Vorzeichen des Arguments (-1.4: Mathematische Funktionen (Forts.0) log(2.

8.$') substring('Thomas' from '%#"o_a#"_' for '#') trim(both 'x' from 'xTomxx') Thomas integer text Position der angegebenen Teilzeichenkette Teilzeichenkette ermitteln 3 hom text text Teilzeichenkette nach POSIX regulärem Ausdruck ermitteln Teilzeichenkette nach SQL regulärem Ausdruck ermitteln Entfernt die längste Zeichenkette.Kapitel 9 9. wobei die Werte dann automatisch in eine Zeichenkettendarstellung umgewandelt werden. Einzelheiten sehen Sie in Tabelle 9.7. aber achten Sie auf die möglichen Auswirkungen der automatischen Auffüllung mit Leerzeichen beim Typ character. Damit sind in diesem Zusammenhang die Typen character.. Konversionen können mit CREATE CONVERSION erzeugt werden. siehe Tabelle 9. Diese Funktionen gibt es auch mit der normalen Syntax für Funktionsaufrufe. SQL definiert einige Funktionen mit spezieller Syntax. von Anfang/Ende/beiden Enden von string mas oma text Tom upper(string) text in Großbuchstaben umwandeln upper('tom') TOM Tabelle 9. sind alle gelisteten Funktionen für alle Typen verfügbar. character varying und text gemeint.6: SQL-Zeichenkettenfunktionen und -operatoren 140 . um die Argumente zu trennen.) Funktion string || string bit_length(string ) Ergebnistyp text integer Beschreibung Beispiel Ergebnis PostgreSQL 32 4 Zeichenketten aneinander hängen 'Post' || 'greSQL' Anzahl Bits in Zeichenkette Anzahl Zeichen in Zeichenkette bit_length('jose') char_length('jose ') char_length(strin integer g) or character_length( string) convert(string using konversionsname) text Ändert die Kodierung mit der angegebenen Konversion.6. wo bestimmte Schlüsselwörter anstatt Kommas verwendet werden. Im Allgemeinen kann man die hier beschriebenen Funktionen auch mit anderen Datentypen verwenden. Wenn nicht anders angegeben. Einige Funktionen gibt es auch direkt für die Bitkettentypen. Es gibt auch vordefinierte Konversionen.. in Kleinbuchstaben umwandeln Anzahl Bytes in Zeichenkette Teilzeichenkette ersetzen convert('PostgreSQ L' using iso_8859_1_to_utf _8) 'PostgreSQL ' in Unicode- Kodierung (UTF-8) lower(string) octet_length(stri ng) overlay(string placing string from integer [for integer]) position(substrin g in string) substring(string [from integer] [for integer]) substring(string from pattern) substring(string from pattern for escape) trim([leading | trailing | both] [zeichen] from string) text integer text lower('TOM') tom octet_length('jose' 4 ) overlay('Txxxxas' placing 'hom' from 2 for 4) position('om' in 'Thomas') substring('Thomas' from 2 for 3) substring('Thomas' from '. (Siehe Tabelle 9. die nur aus zeichen (als Vorgabe ein Leerzeichen) besteht.4 Zeichenkettenfunktionen und -operatoren Dieser Abschnitt beschreibt Funktionen und Operatoren zur Auswertung und Manipulation von Zeichenketten.

7: Andere Zeichenkettenfunktionen 141 . füllung text]) integer text 4 xyxhi ltrim(string text.7 aufgeführt. die Zeichenkette enthält Sonderzeichen oder Großbuchstaben). dann wird es rechts abgeschnitten. Gibt die Zeichenkette so zurück. Beispiel ascii('x') btrim('xyxtrim yyx'.'xyz') pg_client_enco ding() quote_ident('F oo') trim name text SQL_ASCII "Foo" quote_literal( string text) text quote_literal( 'O\'Reilly') 'O''Reill y' repeat(text. Anführungszeichen werden hinzugefügt. die nur aus Zeichen in zeichen steht. zeichen text) chr(integer) convert(string text. Parametertyp ist genauso wie bei encode. die nur aus Zeichen in zeichen besteht. um die SQL-Standard-Funktionen aus Tabelle 9. vom Anfang der Zeichenkette. 'UNICODE'. Vorhandene Apostrophe und Backslashes werden korrekt verdoppelt. text Wandelt ersten Buchstaben jedes Worts (durch Whitespace getrennt) in Großbuchstaben um. typ text) initcap(text) Ergebnistyp integer text Beschreibung ASCII-Code des ersten Arguments Entfernt die längste Zeichenkette. aktuelle Clientkodierung Gibt die Zeichenkette so zurück. dann wird die Datenbankkodierung angenommen. 'LATIN1') Ergebnis 120 trim text text A text_in_u nicode in der Kodierung ISO 8859-1 123\000\0 01 MTIzAAE= bytea decode('MTIzAA E='. typ text) encode(data bytea.6 zu implementieren. Unterstützte Typen 00\\001'.Funktionen und Operatoren Weitere Funktionen zur Zeichenkettenmanipulation sind in Tabelle 9. Wenn string schon länger als länge ist. Wenn quellkodierung ausgelassen wird. Dekodiert binäre Daten von string. 'base64') sind: base64. wenn nötig (d. Einige davon werden intern verwendet. 'base64') text encode('123\\0 Kodiert binäre Daten in eine Darstellung nur aus ASCII-Zeichen. Vorhandene Anführungszeichen werden korrekt verdoppelt. zeichen text) pg_client_enco ding() quote_ident(st ring text) text ltrim('zzzytri m'. initcap('hi thomas') length('jose') lpad('hi'. [quellkodierun g name.h. dass sie als Name in einem SQL-Befehl verwendet werden kann. Funktion ascii(text) btrim(string text. hex. die zuvor mit encode kodiert wurden.] zielkodierung name) decode(string text. escape. Entfernt die längste Zeichenkette. 4) PgPgPgPg Tabelle 9. indem Zeichen füllung (ein Leerzeichen als Vorgabe) vorangestellt werden. 'xy') Hi Thomas length(string) lpad(string text. integer) text repeat('Pg'. 5. dass sie als Zeichenkettenkonstante in einem SQLBefehl verwendet werden kann. Anzahl Zeichen in Zeichenkette Füllt string bis zur Länge länge. länge integer [. vom Anfang und Ende von string Zeichen mit dem angegebenen ASCIICode Wandelt Zeichenkette von quellkodierung nach zielkodierung um. Wiederholt den Text so oft wie angegeben.'xy') chr(65) convert('text_ in_unicode'.

rtrim('trimxxx Entfernt die längste Zeichenkette.'~@~'. from [. Position der angegebenen Teilzeichenkette (das Gleiche wie position(substring in string).2) def text strpos('high'. 'xy') Zeichen füllung (ein Leerzeichen als Vorgabe) angehängt werden. die nur aus Zeichen in zeichen besteht. count]) to_ascii(text [.8: Eingebaute Konversionen 142 . Wenn string schon länger als länge ist. zeichen text) split_part(str ing text. von text. Tabelle 9. kodierung]) to_hex(zahl integer or bigint) translate(stri ng text.'x') der Zeichenkette. 'XX') Ergebnis abXXefabX Xef text Füllt string bis zur Länge länge. wird durch das 'ax') entsprechende Zeichen in nach ersetzt. 3. Karel 7ffffffff fffffff a23x5 text Jedes Zeichen in string. aber andere Reihenfolge der Argumente). Konversionsname a ascii_to_mic ascii_to_utf_8 big5_to_euc_tw big5_to_mic big5_to_utf_8 euc_cn_to_mic euc_cn_to_utf_8 euc_jp_to_mic euc_jp_to_sjis euc_jp_to_utf_8 Quellkodierung SQL_ASCII SQL_ASCII BIG5 BIG5 BIG5 EUC_CN EUC_CN EUC_JP EUC_JP EUC_JP Zielkodierung MULE_INTERNAL UNICODE EUC_TW MULE_INTERNAL UNICODE MULE_INTERNAL UNICODE MULE_INTERNAL SJIS UNICODE Tabelle 9. feld integer) strpos(string. Die Funktion to_ascii unterstützt nur die Konversion von LATIN1. nach text) text substr('alphab et'. dass gleich einem translate('123 45'. trennzeichen text. länge integer [. dann wird es rechts abgeschnitten. 'ig') 2 substr(string. Beispiel replace('abcde fabcdef'. '14'. Wandelt zahl in hexadezimale Darstellung um.Kapitel 9 Funktion replace(string text. vorher text. füllung text]) Ergebnistyp text Beschreibung Ersetzt alle Vorkommen von Teilzeichenkette vorher in string mit nachher . 'cd'. indem rpad('hi'. nachher text) rpad(string text. Teilzeichenkette ermitteln (das Gleiche wie substring(string from from for count)) split_part('ab c~@~def~@~ghi' . 5. vom Ende x'.) a.7: Andere Zeichenkettenfunktionen (Forts. 2) to_ascii('Kare l') to_hex(9223372 036854775807) ph text text Text von anderer Kodierung in ASCII umwandeln a . substring) text trim text Teilt string an den trennzeichen auf und ergibt das angegebene Feld (von eins an zählend). hixyx rtrim(string text. LATIN2 und WIN1250. Zeichen in von ist.

) 143 .8: Eingebaute Konversionen (Forts.Funktionen und Operatoren Konversionsname a euc_kr_to_mic euc_kr_to_utf_8 euc_tw_to_big5 euc_tw_to_mic euc_tw_to_utf_8 gb18030_to_utf_8 gbk_to_utf_8 iso_8859_10_to_utf_8 iso_8859_13_to_utf_8 iso_8859_14_to_utf_8 iso_8859_15_to_utf_8 iso_8859_16_to_utf_8 iso_8859_1_to_mic iso_8859_1_to_utf_8 iso_8859_2_to_mic iso_8859_2_to_utf_8 iso_8859_2_to_windows_1250 iso_8859_3_to_mic iso_8859_3_to_utf_8 iso_8859_4_to_mic iso_8859_4_to_utf_8 iso_8859_5_to_koi8_r iso_8859_5_to_mic iso_8859_5_to_utf_8 iso_8859_5_to_windows_1251 iso_8859_5_to_windows_866 iso_8859_6_to_utf_8 iso_8859_7_to_utf_8 iso_8859_8_to_utf_8 iso_8859_9_to_utf_8 johab_to_utf_8 koi8_r_to_iso_8859_5 koi8_r_to_mic koi8_r_to_utf_8 koi8_r_to_windows_1251 koi8_r_to_windows_866 mic_to_ascii mic_to_big5 Quellkodierung EUC_KR EUC_KR EUC_TW EUC_TW EUC_TW GB18030 GBK LATIN6 LATIN7 LATIN8 LATIN9 LATIN10 LATIN1 LATIN1 LATIN2 LATIN2 LATIN2 LATIN3 LATIN3 LATIN4 LATIN4 ISO_8859_5 ISO_8859_5 ISO_8859_5 ISO_8859_5 ISO_8859_5 ISO_8859_6 ISO_8859_7 ISO_8859_8 LATIN5 JOHAB KOI8 KOI8 KOI8 KOI8 KOI8 MULE_INTERNAL MULE_INTERNAL Zielkodierung MULE_INTERNAL UNICODE BIG5 MULE_INTERNAL UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE MULE_INTERNAL UNICODE MULE_INTERNAL UNICODE WIN1250 MULE_INTERNAL UNICODE MULE_INTERNAL UNICODE KOI8 MULE_INTERNAL UNICODE WIN ALT UNICODE UNICODE UNICODE UNICODE UNICODE ISO_8859_5 MULE_INTERNAL UNICODE WIN ALT SQL_ASCII BIG5 Tabelle 9.

Kapitel 9 Konversionsname a mic_to_euc_cn mic_to_euc_jp mic_to_euc_kr mic_to_euc_tw mic_to_iso_8859_1 mic_to_iso_8859_2 mic_to_iso_8859_3 mic_to_iso_8859_4 mic_to_iso_8859_5 mic_to_koi8_r mic_to_sjis mic_to_windows_1250 mic_to_windows_1251 mic_to_windows_866 sjis_to_euc_jp sjis_to_mic sjis_to_utf_8 tcvn_to_utf_8 uhc_to_utf_8 utf_8_to_ascii utf_8_to_big5 utf_8_to_euc_cn utf_8_to_euc_jp utf_8_to_euc_kr utf_8_to_euc_tw utf_8_to_gb18030 utf_8_to_gbk utf_8_to_iso_8859_1 utf_8_to_iso_8859_10 utf_8_to_iso_8859_13 utf_8_to_iso_8859_14 utf_8_to_iso_8859_15 utf_8_to_iso_8859_16 utf_8_to_iso_8859_2 utf_8_to_iso_8859_3 utf_8_to_iso_8859_4 utf_8_to_iso_8859_5 utf_8_to_iso_8859_6 utf_8_to_iso_8859_7 Quellkodierung MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL MULE_INTERNAL SJIS SJIS SJIS TCVN UHC UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE Zielkodierung EUC_CN EUC_JP EUC_KR EUC_TW LATIN1 LATIN2 LATIN3 LATIN4 ISO_8859_5 KOI8 SJIS WIN1250 WIN ALT EUC_JP MULE_INTERNAL UNICODE UNICODE UNICODE SQL_ASCII BIG5 EUC_CN EUC_JP EUC_KR EUC_TW GB18030 GBK LATIN1 LATIN6 LATIN7 LATIN8 LATIN9 LATIN10 LATIN2 LATIN3 LATIN4 ISO_8859_5 ISO_8859_6 ISO_8859_7 Tabelle 9.) 144 .8: Eingebaute Konversionen (Forts.

10. Einzelheiten sehen Sie in Tabelle 9.) 145 . wo bestimmte Schlüsselwörter anstatt Kommas verwendet werden. Diese Funktionen gibt es auch mit der normalen Syntax für Funktionsaufrufe. (Siehe Tabelle 9.Funktionen und Operatoren Konversionsname a utf_8_to_iso_8859_8 utf_8_to_iso_8859_9 utf_8_to_johab utf_8_to_koi8_r utf_8_to_sjis utf_8_to_tcvn utf_8_to_uhc utf_8_to_windows_1250 utf_8_to_windows_1251 utf_8_to_windows_1256 utf_8_to_windows_866 utf_8_to_windows_874 windows_1250_to_iso_8859_2 windows_1250_to_mic windows_1250_to_utf_8 windows_1251_to_iso_8859_5 windows_1251_to_koi8_r windows_1251_to_mic windows_1251_to_utf_8 windows_1251_to_windows_866 windows_1256_to_utf_8 windows_866_to_iso_8859_5 windows_866_to_koi8_r windows_866_to_mic windows_866_to_utf_8 windows_866_to_windows_1251 windows_874_to_utf_8 Quellkodierung UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE UNICODE WIN1250 WIN1250 WIN1250 WIN WIN WIN WIN WIN WIN1256 ALT ALT ALT ALT ALT WIN874 Zielkodierung ISO_8859_8 LATIN5 JOHAB KOI8 SJIS TCVN UHC WIN1250 WIN WIN1256 ALT WIN874 LATIN2 MULE_INTERNAL UNICODE ISO_8859_5 KOI8 MULE_INTERNAL UNICODE ALT UNICODE ISO_8859_5 KOI8 MULE_INTERNAL UNICODE WIN UNICODE Tabelle 9.5 Funktionen und Operatoren für binäre Daten Dieser Abschnitt beschreibt Funktionen und Operatoren zur Bearbeitung von Werten des Typs bytea. Daher könnten die Namen von den gebräuchlichen Kodierungsnamen abweichen. SQL definiert einige Funktionen mit spezieller Syntax. um die Argumente zu trennen. Die Konversionsnamen folgen einem einheitlichen Schema: Der offizielle Name der Quellkodierung mit allen nicht alphanumerischen Zeichen durch Unterstriche ersetzt.8: Eingebaute Konversionen (Forts. gefolgt vom auf gleiche Weise umgewandelten Zielkodierungsnamen. gefolgt von _to_.9. 9.) a.

Unterstützte Typen sind: base64. vom Anfang und Ende von daten. die 00456'. 146 . Außerdem gibt es die Funktion substring. escape.9: SQL-Funktionen und -Operatoren für binäre Daten Weitere Funktionen zur Zeichenkettenmanipulation sind in Tabelle 9. hex. in PostgreSQL Mustervergleiche durchzuführen: der herkömmliche SQL-Operator LIKE. encode('123\\0 00456'::bytea. die nur aus Bytes in bytes steht. Anzahl Bytes in Daten Beispiel btrim('\\000tr im\\000'::byte a.9 zu implementieren. Funktion btrim(daten bytea bytes bytea) length(daten) decode(daten text. um die SQL-Standard-Funktionen aus Tabelle 9.10: Andere Funktionen für binäre Daten 9. sollten Sie das Schreiben einer benutzerdefinierten Funktion in Perl oder Tcl in Betracht ziehen. Parametertyp ist genauso wie bei encode. die diese Fähigkeiten überschreiten. Tom Tabelle 9. vom Anfang und Ende von daten .6 Mustervergleiche Es gibt drei verschiedene Möglichkeiten. 'escape') 123\000456 Tabelle 9. typ text) encode(daten bytea.Kapitel 9 Funktion daten || daten Ergebnistyp Beschreibung bytea Beispiel '\\\\Post'::bytea || '\\047greSQL\\000':: bytea octet_length('jo\\00 0se'::bytea) position('\\000om':: bytea in 'Th\\000omas'::bytea ) substring('Th\\000om as'::bytea from 2 for 3) trim('\\000'::bytea from '\\000Tom\\000'::byt ea) Ergebnis \\Post'greSQL\ 000 5 3 Datenketten aneinander hängen Anzahl Bytes in Daten Position der angegebenen Teildatenkette Teildatenkette ermitteln octet_length(date integer n) position(subdaten integer in daten) substring(daten [from integer] [for integer]) trim([both] bytes from daten) bytea h\000o bytea Entfernt die längste Datenkette. zuvor mit encode kodiert wurden.10 aufgeführt. der neuere SQL99-Operator SIMILAR TO und reguläre Ausdrücke nach POSIX. Tipp Wenn sie Anforderungen für Mustervergleiche haben. Einige davon werden intern verwendet. 'escape') text Kodiert binäre Daten in eine Darstellung nur aus ASCII-Zeichen. die Mustervergleiche mit regulären Ausdrücken entweder nach SQL99 oder POSIX durchführen kann. typ text) Ergebnistyp bytea Beschränkung Entfernt die längste Datenkette.'\\000'::byt ea) length('jo\\00 0se'::bytea) Ergebnis trim integer bytea 5 123\000456 decode('123\\0 Dekodiert binäre Daten in daten. die nur aus Bytes in bytes besteht.

9.6. muss das Muster also am Anfang und Ende ein Prozentzeichen haben.und Kleinschreibung zu machen (entsprechend der aktuellen Locale-Einstellung). NOT ILIKE stehen. Alle diese Operatoren gibt es so nur in PostgreSQL. also brauchen Sie immer noch zwei. Dadurch wird der Fluchtzeichenmechanismus im Prinzip ausgeschaltet. Um einen Unterstrich oder ein Prozentzeichen.2 SIMILAR TO und reguläre Ausdrücke nach SQL99 zeichenkette SIMILAR TO muster [ESCAPE fluchtzeichen] zeichenkette NOT SIMILAR TO muster [ESCAPE fluchtzeichen] Der Operator SIMILAR TO ergibt wahr oder falsch abhängig davon. aber keine anderen Zeichen. schreiben Sie es zweimal hintereinander in das Muster. müssen Sie in dem Befehl vier eingeben. sondern ist eine Erweiterung von PostgreSQL. Der LIKE-Ausdruck ergibt logisch wahr. 147 . wenn die zeichenkette in der von muster bestimmten Sammlung ist. Reguläre Ausdrücke nach SQL99 sind eine merkwürdige Kombination aus der von LIKE bekannten Schreibweise und der allgemein gebräuchlichen Schreibweise von regulären Ausdrücken. dass einen Backslash findet. Ein Unterstrich (_) in muster steht für ein einzelnes beliebiges Zeichen.1 LIKE zeichenkette LIKE muster [ESCAPE fluchtzeichen] zeichenkette NOT LIKE muster [ESCAPE fluchtzeichen] Jedes muster definiert eine Sammlung von Zeichenketten. ein Prozentzeichen (%) steht für null oder mehr Zeichen. dann hat der Backslash keine besondere Bedeutung für LIKE mehr. Einige Beispiele: 'abc' 'abc' 'abc' 'abc' LIKE LIKE LIKE LIKE 'abc' 'a%' '_b_' 'c' wahr wahr wahr falsch Mustervergleiche mit LIKE gehen immer über die gesamte Zeichenkette. außer dass es das Muster als regulären Ausdruck nach SQL99 interpretiert. aber ein anderes Zeichen kann mit der ESCAPE-Klausel gewählt werden. zu finden. Das können Sie vermeiden. Das normale Fluchtzeichen ist der Backslash. Es ist ähnlich LIKE. Wenn Sie folglich ein Muster schreiben wollen. wenn LIKE wahr ergibt.) Wenn muster kein Prozentzeichen oder Unterstrich enthält. müssen Sie in einem SQL-Befehl zwei Backslashes schreiben. Der Operator ~~ ist gleichbedeutend mit LIKE und ~~* entspricht ILIKE. Um das Fluchtzeichen selbst zu finden. dass der Backslash in Zeichenkettenkonstanten eine besondere Bedeutung hat. Beachten Sie. wodurch es unmöglich wird.) Es ist möglich. gar kein Fluchtzeichen auszuwählen. Es gibt auch die Operatoren !~~ und !~~* die für NOT LIKE bzw. Das Schlüsselwort ILIKE kann anstelle von LIKE verwendet werden. muss vor die entsprechenden Zeichen in muster das Fluchtzeichen geschrieben werden. indem Sie mit ESCAPE ein anderes Fluchtzeichen bestimmen. um die Mustersuche unabhängig von Groß. indem man ESCAPE '' schreibt. Um also eine Musterkonstante mit einem Backslash zu schreiben. Um ein Muster irgendwo in einer Zeichenkette zu finden. und umgekehrt. ob das Muster mit der angegebenen Zeichenkette übereinstimmt. Ein gleichbedeutender Ausdruck ist NOT (zeichenkette LIKE muster). die besondere Bedeutung des Unterstrichs und des Prozentzeichens im Muster zu umgehen.6. Das steht nicht im SQL-Standard. dann steht das Muster nur für die Zeichenkette selbst. (Aber er hat immer noch eine besondere Bedeutung in Zeichenkettenkonstanten.Funktionen und Operatoren 9. (Wie zu erwarten ist. in dem Fall verhält sich LIKE wie die Vergleichsoperation. ergibt der Ausdruck NOT LIKE falsch.

Operator ~ ~* Beschreibung Vergleich mit regulärem Ausdruck. ist SIMILAR TO nur erfolgreich. Klammern () können verwendet werden. die mit dem regulären Ausdruck nach SQL99 übereinstimmt.] ist eine Zeichenklasse. ansonsten schlägt die Funktion fehl und gibt den NULL-Wert zurück. achtet auf Groß-/ Kleinschreibung Beispiel 'thomas' ~ '. ignoriert Groß-/Kleinschreibung 'thomas' ~* '. dass begrenzte Wiederholung (? und {. substring(zeichenkette from muster for fluchtzeichen)...*Thomas. wie bei POSIX. + steht für die Wiederholung des vorangegangenen Ausdrucks ein oder mehrere Male. Der Text. jede beliebige Zeichenkette.6. Einige Beispiele: substring('foobar' from '%#"o_b#"%' for '#') oob substring('foobar' from '#"o_b#"%' for '#') NULL 9. Wie bei SIMILAR TO muss das Muster auf die gesamte Zeichenkette passen. Ebenso wie LIKE verwendet SIMILAR TO _ und % als Wildcard-Zeichen für ein beliebiges einzelnes Zeichen bzw.}) nicht zur Verfügung steht. wird zurückgegeben.*' Tabelle 9. Beachten Sie.) kein Sonderzeichen. * steht für die Wiederholung des vorangegangenen Ausdrucks null oder mehrere Male. um Ausdrücke zu einem einzigen logischen Ausdruck zu- sammenzufassen.. Außerdem ist der Punkt (. (Diese sind vergleichbar mit . obwohl sie in POSIX vorhanden sind. wenn das Muster auf die gesamte Zeichenkette passt.*thomas.*' Vergleich mit regulärem Ausdruck.* in regulären Ausdrücken in der POSIX-Schreibweise.Kapitel 9 Wie LIKE.11 listet die verfügbaren Operatoren für Mustervergleiche mit regulären Ausdrücken nach POSIX. und . der bei erfolgreicher Übereinstimmung zurückgegeben werden soll. muss das Muster zweimal das Fluchtzeichen jeweils gefolgt von einem Anführungszeichen (") enthalten. Einige Beispiele: 'abc' 'abc' 'abc' 'abc' SIMILAR SIMILAR SIMILAR SIMILAR TO TO TO TO 'abc' 'a' '%(b|d)%' '(b|c)%' wahr falsch wahr falsch Die Funktion substring mit drei Parametern. der mit dem Teil des Musters zwischen diesen Markierungen übereinstimmt. wo das Muster auch auf nur einen Teil der Zeichenkette passen kann. Um den Teil des Musters zu markieren. erlaubt das Auswählen einer Teilzeichenkette.11: Operatoren für reguläre Ausdrücke 148 .3 Reguläre Ausdrücke nach POSIX Tabelle 9.. ❏ Ein Ausdruck in eckigen Klammern [. oder ein anderes Fluchtzeichen kann mit ESCAPE bestimmt werden. Das steht im Gegensatz zur gebräuchlichen Praxis bei regulären Ausdrücken.) Neben diesen von LIKE übernommenen Möglichkeiten unterstützt SIMILAR TO auch folgende von POSIX übernommene Sonderzeichen zur Mustersuche: ❏ ❏ ❏ ❏ | steht für eine Alternative (entweder die eine oder die andere). Genauso wie bei LIKE kann der Backslash die besondere Bedeutung dieser Sonderzeichen abschalten.

Ein Atom gefolgt von ? passt auf eine Folge von 0 oder 1 Übereinstimmungen mit dem Atom. der mit dem ersten eingeklammerten Teilausdruck (der. ignoriert Groß-/ Kleinschreibung Beispiel 'thomas' !~ '. Einige Beispiele: 'abc' 'abc' 'abc' 'abc' ~ ~ ~ ~ 'abc' '^a' '(b|d)' '^(b|c)' wahr wahr wahr falsch Die Funktion substring mit zwei Parametern. die der hier beschriebenen ähnlich ist. PostgreSQL bietet die moderne Form an. erlaubt das Auswählen einer Teilzeichenkette. in 1003. Wenn Sie Klammern verwenden wollen. können Sie um den ganzen Ausdruck ein Klammernpaar setzen. Wie mit LIKE passen Zeichen im Muster genau auf Zeichen in der angegebenen Zeichenkette. die in abgekürzter Schreibweise eine Menge von Zeichenketten definiert (eine reguläre Menge).)b') o Reguläre Ausdrücke (RAs). die mit dem regulären Ausdruck nach POSIX übereinstimmt. dass die Übereinstimmung vom Anfang oder bis zum Ende bestehen muss. gibt es in zwei Formen: moderne RAs (etwa die von egrep bekannten.*' 'thomas' !~* '. wenn der Text auf alle Teile hintereinander passt. Ein Teil besteht aus einem Atom.*vadim. wenn sie ein Element der von dem regulären Ausdruck beschriebenen regulären Menge ist. in 1003.Funktionen und Operatoren Operator !~ !~* Beschreibung negierter Vergleich mit regulärem Ausdruck. sed oder awk. getrennt durch |.2 “einfache” RAs). passt auf eine Folge von 1 oder mehr Übereinstimmungen mit dem Atom. Im Gegensatz zu LIKE-Mustern können reguläre Ausdrücke auch auf Teilzeichenketten mitten in der zu durchsuchenden passen.2 werden diese “erweiterte” RAs genannt) und obsolete RAs (etwa die aus ed. wird der Teil des Texts zurückgegeben. nach der Definition in POSIX 1003. Wenn das Muster Klammern enthält. 149 . Wenn es keine Übereinstimmung gibt. Ein Atom. Aber reguläre Ausdrücke verwenden andere Sonderzeichen als LIKE.b') oob substring('foobar' from 'o(. ansonsten ergibt sie den Teil des Textes der übereingestimmt hat.11: Operatoren für reguläre Ausdrücke (Forts. wahlweise gefolgt von einem einzelnen Zeichen *. passt auf eine Folge von 0 oder mehr Übereinstimmungen mit dem Atom. Er passt auf alles. Ein regulärer Ausdruck ist eine Zeichenfolge.*Thomas. Einige Beispiele: substring('foobar' from 'o. Eine Zeichenkette stimmt mit einem regulären Ausdruck überein. dann ergibt sie den NULL-Wert. Ein (moderner) RA besteht aus einem oder mehreren nicht leeren Zweigen. was auf einen der Zweige passt. Ein Atom. +. ? oder einer Begrenzung. Viele Unix-Werkzeuge. verwenden eine Schreibweise für reguläre Ausdrücke. substring(zeichenkette from muster). das von einem + gefolgt wird.2. außer wenn es im regulären Ausdruck explizit angegeben wurde. von dem die linke Klammer zuerst kam) übereingestimmt hat. Er passt. außer wenn sie Sonderzeichen von regulären Ausdrücken sind. ohne diesen Mechanismus auszulösen.*' Tabelle 9. achtet auf Groß-/ Kleinschreibung negierter Vergleich mit regulärem Ausdruck. wie egrep.) Die regulären Ausdrücke nach dem POSIX-Standard bieten eine mächtigere Schnittstelle für Mustervergleiche als die Operatoren LIKE und SIMILAR TO. Ein Zweig besteht aus einem oder mehreren aneinander gehängten Teilen. das von einem * gefolgt wird.

Die Zahlen müssen zwischen einschließlich 0 und RE_DUP_MAX (255) liegen. am Ende eines RA ein \ stehen zu haben. dann wären [[=o=]]. ^ (passt auf den Anfang der angegebenen Zeichenkette). müssen Sie in dem Befehl zwei Backslashes schreiben. wahlweise gefolgt von . ist es eine Äquivalenzklasse. Wenn zwei Zeichen in der Liste durch – getrennt sind. die einen Backslash enthält. Diese Folge ist ein einzelnes Element in der eingeklammerten Liste. dass zwei Bereiche einen gemeinsamen Endpunkt haben. die mit demjenigen äquivalent sind. die für die Zeichenfolgen aller Sortierelemente. Es ist nicht erlaubt. ein \ gefolgt von einem anderen Zeichen (passt auf dieses Zeichen. *.B. und . ihre besondere Bedeutung innerhalb von eckigen Klammern. um es in ein Sortierelement umzuwandeln (siehe unten).) Wenn zum Beispiel o und ^ Elemente einer Äquivalenzklassen wären.ch. als wenn er stattdessen zwischen [. (Wenn es keine äquivalenten Sortierelemente gibt. [[=^=]] und [o^] alle gleichbedeutend. was mit dem eingeschlossenen Ausdruck übereinstimmt). Wenn zum Beispiel die Sortierreihenfolge ein ch als Sortierelement enthält. zählt als normales Zeichen und nicht als Anfang einer Begrenzungsangabe.[$()|*+?{\ (passt auf das Zeichen ungeachtet seiner Stellung als Sonderzeichen). ein leeres Paar () (passt auf eine leere Zeichenkette). Ein Ausdruck in eckigen Klammern kann also auf mehr als ein Zeichen passen. steht. Normalerweise passt er auf ein beliebiges Zeichen aus der Liste (siehe aber unten). und . und am Ende immer }. Um ein – in die Liste zu setzen. Wenn die Liste mit ^ beginnt.] stehen würde.]. a-c-e. Beachten Sie. Um also eine Musterkonstante zu schreiben.Kapitel 9 Eine Begrenzung besteht aus { gefolgt von einer ganzen Zahl ohne Vorzeichen (in Dezimalschreibweise). Anmerkung Ein Wiederholungsoperator (?. passt der RA [[. passt er auf ein beliebiges Zeichen (siehe aber unten). Mit Ausnahme dieser Konstruktion und einigen Kombinationen mit [ (siehe nächster Absatz) verlieren alle anderen Sonderzeichen. und . oder ein besonderer Name für eins der beiden) zwischen [. dann ist das eine Kurzschreibweise für den gesamten Bereich von Zeichen zwischen diesen beiden (einschließend) in der Sortierreihenfolge. die wie ein einzelnes Zeichen sortiert wird. dass ein Backslash (\) schon eine besondere Bedeutung in Zeichenkettenkonstanten hat. z. Um ein ] in die Liste zu setzen. verhält sich der Ausdruck. als ob der \ nicht da gewesen wäre) oder ein anderes Zeichen ohne besondere Bedeutung (passt auf dieses Zeichen). Ein Atom gefolgt von einer Begrenzung mit einer Zahl i und einem Komma passt auf eine Folge von i oder mehr Übereinstimmungen mit dem Atom. ein Ausdruck in ekkigen Klammern (siehe unten). einschließlich demjenigen selbst. Um ein – als Anfangspunkt eines Bereichs zu verwenden. passt [0-9] in ASCII auf eine beliebige dezimale Ziffer. Es ist nicht erlaubt. Ein Wiederholungsoperator kann nicht am Anfang eines Ausdrucks oder eines Teilausdrucks oder nach ^ oder | stehen. Ein Atom gefolgt von einer Begrenzung mit einer Zahl i und keinem Komma passt auf eine Folge von genau i Übereinstimmungen mit dem Atom. eine Folge aus mehreren Zeichen. die von [] eingeschlossen wird. das nicht in der Liste ist. schreiben Sie es als erstes Zeichen (nach einem etwaigen ^). das keine Ziffer ist. Eine Äquivalenzklasse darf nicht der Endpunkt eines Bereichs sein. Ein Atom gefolgt von einer Begrenzung mit zwei Zahlen i und j passt auf eine Folge von einschließlich i bis j Übereinstimmungen mit dem Atom. darf die erste nicht größer als die zweite sein. schreiben Sie es als erstes oder letztes Zeichen oder als zweiter Endpunkt eines Bereichs. schreiben Sie es zwischen [. + oder eine Begrenzung) kann nicht auf einen anderen Wiederholungsoperator folgen. (passt auf ein einzelnes Zeichen). Ein Ausdruck in eckigen Klammern ist eine Liste von Zeichen.B. ein . und wahlweise noch einer ganze Zahl ohne Vorzeichen.] steht. Wenn innerhalb eines Ausdrucks in eckigen Klammern ein Sortierelement zwischen [= und =] steht. ein \ gefolgt von eines der Zeichen ^.]]*c auf die ersten fünf Zeichen von chchcc. 150 . z. Ein { gefolgt von einem Zeichen. Ein Atom ist ein regulärer Ausdruck in () (passt auf alles. Die Bereiche hängen stark von Locale-Einstellungen ab und sollten von portierbaren Programmen vermieden werden. einschließlich \. $ (passt auf das Ende der eingegebenen Zeichenkette). und wenn zwei Zahlen angegeben wurden. dann steht es für die Zeichenfolge dieses Sortierelements. Wenn innerhalb eines Ausdrucks in eckigen Klammern ein Sortierelement (ein Zeichen.

cntrl. Diese stehen für die Zeichenklassen. 151 .12 sind sie gelistet.100}){1. lower. aber das Problem bleibt bestehen. um verschiedene Datentypen (Datum/Zeit. wo weder davor noch danach ein weiteres Wortzeichen steht. dass ein RA mit mehr als einer Teilzeichenkette übereinstimmt. so wird aus x zum Beispiel [xX]. dann wird es im Endeffekt in einen Ausdruck in eckigen Klammern umgewandelt. In bestimmten LocaleEinstellungen können weitere vorhanden sein. 1 9. als ob alle Unterschiede zwischen Groß.100} wird (letztendlich) den Speicher fast jeder bestehenden Maschine aufbrauchen. die zwar kompatibel mit POSIX 1003. Ein RA wie zum Beispiel ((((a{1. dass äußere Teilausdrücke Vorrang vor den tiefer in ihnen geschachtelten haben.* mit abc verglichen wird.und als Kleinbuchstabe gibt. Es gibt keine bestimmte Höchstgrenze für die Länge eines RA.100}){1. Zum Beispiel: bb* passt auf die drei mittleren Zeichen von abbbc. dann ergeben der ganze RA wie auch der Teilausdruck in Klammern eine Übereinstimmung mit der leeren Zeichenkette. Wenn es innerhalb einer Liste in eckigen Klammern auftritt.und Kleinschreibung ignoriert. upper. Teilausdrücke suchen auch eine Übereinstimmung mit den längstmöglichen Teilzeichenketten. (wee|week)(knights|nights) passt auf alle zehn Zeichen von weeknights. Daraus ergibt sich. Bedenken Sie. Diese Funktionen werden alle nach 1. dann steht das für die Liste aller Zeichen. digit.und Kleinbuchstaben aus dem Alphabet verschwunden wären. Eine Zeichenklasse darf nicht als Endpunkt eines Bereichs verwendet werden. Das ist eine Erweiterung. Wenn der RA mit mehr als einer Teilzeichenkette an dieser Stelle übereinstimmen kann. Wenn es sich ergibt.2 ist. der Groß. dann passt der Teilausdruck in Klammern auf alle drei Zeichen. was viel Zeit und Platz kostet. wenn (. die eher in dem RA anfangen. der beide Buchstabenformen enthält. außer was den Hauptspeicher betrifft. Vorrang vor den später Anfangenden haben. dort aber nicht angegeben wird. print. die zuerst in der Zeichenkette anfängt. dass die gesamte Übereinstimmung so lang wie möglich sein soll und dass Teilausdrücke. außer bei begrenzten Wiederholungen. die zu dieser Klasse gehören. graph. als normales Zeichen außerhalb von eckigen Klammern auftritt. ergibt der RA eine Übereinstimmung mit der. Der Speicherverbrauch ist in etwa direkt proportional zur Länge des RA und im Großen und Ganzen unabhängig von dessen Komplexität. space. wenn die Software auf andere Systeme portierbar sein soll. Eine leere Zeichenkette wird als länger als gar keine Übereinstimmung erachtet.*). Die Länge einer Übereinstimmung wird in Zeichen. daher sollte sie mit Vorsicht verwendet werden. und wenn (a*)* mit bc verglichen wird. Es gibt zwei besondere Fälle von Ausdrücken in eckigen Klammern: [[:<:]] und [[:>:]] erzeugen eine Übereinstimmung am Anfang bzw. nimmt er die längste. werden alle übrigen Formen des Buchstabens zu der Liste hinzugefügt.100}){1. punct.100}){1. das es als Groß. Ein Wort ist definiert als eine Folge von Wortzeichen. blank. die in ctype (3) definiert sind. Begrenzte Wiederholungen sind als Makroerweiterung implementiert. dass das 1994 geschrieben wurde. so wird zum Beispiel [x] in [xX] und [^x] in [^xX] verwandelt.Funktionen und Operatoren Wenn innerhalb eines Ausdrucks in eckigen Klammern der Name einer Zeichenklasse zwischen [: und :] steht. mit der Einschränkung. diverse Zahlentypen) in formatierte Zeichenketten oder formatierte Zeichenketten in bestimmte Datentypen umzuwandeln. Standardisierte Namen von Zeichenklassen sind: alnum. Ein Wortzeichen ist ein “alnum”Zeichen (definiert in ctype (3)) oder ein Unterstrich. Die Zahlen haben sich wahrscheinlich verändert. Ende eines Worts. In Tabelle 9. nicht Sortierelementen gezählt. dann ist die Auswirkung. wenn die Zahlen groß oder die begrenzten Wiederholungen geschachtelt sind. Wenn ein alphabetisches Zeichen.7 Datentyp-Formatierungsfunktionen Die PostgreSQL-Formatierungsfunktionen bieten vielfältige Möglichkeiten. xdigit. alpha. Wenn ein Mustervergleich gewünscht wird.

oder PM oder P.13 zeigt die Muster. text) to_char(numeric. text) text to_char(double precision. '999D99S') to_date('05 Dec 2000'. 4 Ziffern) die letzten 3 Ziffern des Jahres die letzten 2 Ziffern des Jahres Tabelle 9. '99G999D9S') to_char(int.M. wird unverändert übernommen. '999D9') to_char(-125. Gleichermaßen bestimmen die Muster in einer Eingabemustervorlage (für alles außer to_char).M.m. Funktion to_char(timestamp .Kapitel 9 dem gleichen Schema aufgerufen: Das erste Argument ist der zu formatierende Wert und das zweite Argument ist eine Mustervorlage.8-'. text) to_number(text. text) to_char(interval. text) text text date timestamp numeric integer in Zeichenkette umwandeln real/double precision in Zeichenkette umwandeln numeric in Zeichenkette umwandeln Zeichenkette in date umwandeln Zeichenkette in timestamp umwandeln Zeichenkette in numeric umwandeln Tabelle 9. Beschreibung Stunde (01-12) Stunde (01-12) Stunde (00-23) Minute (00-59) Sekunde (00-59) Millisekunde (000-999) Mikrosekunde (000000-999999) Sekunden nach Mitternacht (0-86399) Vormittags-/Nachmittagsangabe (Großbuchstaben) am oder a.12: Formatierungsfunktionen In einer Ausgabemustervorlage (für to_char) werden bestimmte Muster erkannt und durch entsprechend formatierte Daten vom zu formatierenden Wert ersetzt.13: Mustervorlagen für die Formatierung von Datum/Zeit 152 .8. 'HH24:MI:SS') to_char(125. Tabelle 9. die das Ausgabe.454.und Zeitangaben zur Verfügung stehen. Vormittags-/Nachmittagsangabe (Kleinbuchstaben) Y.oder Eingabeformat bestimmt. text) to_date(text. Muster HH HH12 HH24 MI SS MS US SSSS AM oder A. 'HH12:MI:SS') to_char(interval '15h 2m 12s'.m. die zur Formatierung von Datums. 4 Ziffern) mit Komma zur Zifferngruppierung Jahr (mind. text) Ergebnistyp text text Beschreibung timestamp in Zeichenkette umwandeln interval in Zeichenkette umwandeln Beispiel to_char(current_timesta mp. welche Teile der angegebenen Zeichenkette zu betrachten sind und welche Werte dort zu finden sind. text) to_timestamp(text . oder pm oder p. der kein solches Muster ist. 'DD Mon YYYY') to_number('12.8::real. 'DD Mon YYYY') to_timestamp('05 Dec 20 00'. Jeglicher Text. '999') to_char(125.YYY YYYY YYY YY Jahr (mind.

I=Januar) (Großbuchstaben) Monat in römischen Zahlen (i-xii.) Quartal Monat in römischen Zahlen (I-XII. oder ad oder a.u.d. englische Angabe der Zeitrechnung (Kleinbuchstaben) MONTH Month month MON Mon mon MM DAY Day day DY Dy dy DDD DD D W WW IW CC J Q RM rm TZ tz voller englischer Monatsname in Großbuchstaben (mit Leerzeichen auf 9 Zeichen aufgefüllt) voller englischer Monatsname in gemischten Buchstaben (mit Leerzeichen auf 9 Zeichen aufgefüllt) voller englischer Monatsname in Kleinbuchstaben (mit Leerzeichen auf 9 Zeichen aufgefüllt) abgekürzter englischer Monatsname in Großbuchstaben (3 Zeichen) abgekürzter englischer Monatsname in gemischten Buchstaben (3 Zeichen) abgekürzter englischer Monatsname in Kleinbuchstaben (3 Zeichen) Nummer des Monats (01-12) voller englischer Wochentag in Großbuchstaben (mit Leerzeichen auf 9 Zeichen aufgefüllt) voller englischer Wochentag in gemischten Buchstaben (mit Leerzeichen auf 9 Zeichen aufgefüllt) voller englischer Wochentag in Kleinbuchstaben (mit Leerzeichen auf 9 Zeichen aufgefüllt) abgekürzter englischer Wochentag in Großbuchstaben (3 Zeichen) abgekürzter englischer Wochentag in gemischten Buchstaben(3 Zeichen) abgekürzter englischer Wochentag in Kleinbuchstaben (3 Zeichen) Tag im Jahr (001-366) Tag im Monat (01-31) Wochentag (1-7.13: Mustervorlagen für die Formatierung von Datum/Zeit (Forts. Zum Beispiel wäre FMMonth das Muster Month mit der Abänderung FM.Z.) Woche im Jahr (1-53) (Die erste Woche fängt am ersten Tag des Jahres an.) ISO-Wochennummer (Der erste Donnerstag des neuen Jahres ist in Woche Nummer 1.C. um ihr Verhalten zu verändern.c.D. Tabelle 9.Funktionen und Operatoren Muster Y Beschreibung die letzte Ziffer des Jahres BC oder B.) Jahrhundert (2 Ziffern) Julianischer Tag (Tage seit 1. i=Januar) (Kleinbuchstaben) Zeitzonenname (Großbuchstaben) Zeitzonenname (Kleinbuchstaben) Tabelle 9. Januar 4712 v.) Auf alle Muster können bestimmte Abänderungen angewendet werden. englische Angabe der Zeitrechnung (Großbuchstaben) bc oder b. oder AD oder A.14 zeigt die Abänderungsmuster für die Formatierung von Datum und Zeit. Sonntag ist 1) Woche im Monat (1-5) (Die erste Woche fängt am ersten Tag des Monats an. 153 .

FX muss das erste Element in der Mustervorlage sein. sondern 300. 12:30 und 12:300 alle die gleiche Anzahl Millisekunden ergeben.15: Mustervorlagen für die Formatierung von numerischen Werten 154 . Zum Beispiel ergibt to_timestamp('12:3'. ❏ to_timestamp und to_date ignorieren Folgen von mehreren Leerzeichen im Eingabetext. 'YYYYMonDD'). (Komma) Beschreibung Wert mit der angegebenen Anzahl von Ziffern Wert mit führenden Nullen Punkt zur Trennung von Nachkommastellen Komma als Tausendergruppierung Tabelle 9.3 Sekunden zählt.US') ergibt 15 Stunden. 'YYYYMMDD') wird als 4-ziffriges Jahr interpretiert. Sie können eine Teilzeichenkette in Anführungszeichen setzen. um zu verhindern. 'YYYY MON') ist korrekt. Zum Beispiel (mit dem Jahr 20000): to_date('200001131'. 'YYYY-MMDD') oder to_date('20000Nov31'.003 Sekunden gezählt wird.MS. müssen Sie einen Backslash davor stellen. wie to_date('20000-1131'. weil der Backslash schon eine besondere Bedeutung in Zeichenkettenkonstanten hat. Nach dem YYYY muss ein nichtnumerisches Zeichen oder Muster stehen. muss man 12:003 schreiben. die zur Formatierung von numerischen Werten zur Verfügung stehen. 'SS:MS') nicht 3 Millisekunden.Kapitel 9 Abänderung FM Präfix TH Suffix th Suffix FX Präfix SP Suffix Beschreibung Füllmodus (unterbindet Auffüllen mit Leerzeichen und Nullen) englische Ordnungszahlendung (Großbuchstaben) englische Ordnungszahlendung (Kleinbuchstaben) globale Option Fixformat (siehe Verwendungshinweise) (noch nicht implementiert) Beispiel FMMonth DDTH DDth FX Month DD Day DDSP Tabelle 9. dass bei der Mustervorlage SS:MS die Eingabewerte 12:3. zum Beispiel '\\"YYYY Month\\"'.001230'. Zum Beito_timestamp('2000 JUN'. So wird zum Beispiel in '"Hello Year "YYYY' das YYYY durch das Jahr ersetzt. wenn Sie Jahreszahlen mit mehr als vier Ziffern verwenden.15 zeigt die Muster. nicht aber das einzelne Y in Year. Um drei Millisekunden zu erhalten.021230 Sekunden. (Sie müssen zwei Backslashes eingeben. weil to_timestamp nur ein Leerzeichen erwartet. dass Zeichen als eins der Muster verwendet werden. 12 Minuten und 2 Sekunden + 20 Millisekunden + 1230 Mikrosekunden = 2. Das bedeutet. Hier ist ein komplexeres Beispiel: to_timestamp('15:12:02.020. weil die Umwandlung 12 + 0. um dem Ergebnis eines Musters eine feste Länge zu geben. was ansonsten verwendet wird. ❏ Wenn Sie ein Anführungszeichen im Ergebnis haben wollen. wenn die Option FX nicht verwendet wird. Muster 9 0 . ❏ Die Formatwerte für Millisekunden (MS) und Mikrosekunden (US) in einer Umwandlung von Text in timestamp werden als Teil der Sekunden nach dem Komma verwendet. ❏ Normaler Text kann in Mustervorlagen für to_char stehen und wird unverändert übernommen.14: Abänderungsmuster für die Formatierung von Datum/Zeit Verwendungshinweise zur Formatierung von Datum und Zeit: ❏ FM unterbindet das Füllen mit Nullen links und mit Leerzeichen rechts. setzen Sie stattdessen ein nichtnumerisches Trennzeichen nach das Jahr.) ❏ Die Umwandlungen mit YYYY von Text in timestamp oder date hat eine Einschränkung.003 = 12. (Punkt) . was als 12 + 0. 'FXYYYY MON') ergibt einen Fehler. ansonsten werden immer vier Ziffern als das Jahr genommen. 'HH:MI:SS. aber spiel: to_timestamp('2000 JUN'. Tabelle 9.

PL oder MI formatiertes Vorzeichen steht nicht direkt neben der Zahl.1. 6 ' -. '9990999. DD to_char(current_timestamp.5.0' '0012' ' 485' '-485' ' 4 8 5' ' 1. Wenn keine Ziffer verfügbar ist.99') to_char(0.16 zeigt einige Beispiele. zum Beispiel.16: Beispiele für to_char 155 . 'S9999') ergibt ' -12'. dann wird ein Leerzeichen ausgegeben.99') to_char(-0.485' ' 1 485' ' 148.) ❏ Verwendungshinweise zur Formatierung von numerischen Werten: ❏ Ein mit SG. '99.Funktionen und Operatoren Muster PR S L D G MI PL SG RN TH oder th V EEEE Beschreibung negativer Wert in spitzen Klammern Vorzeichen direkt neben der Zahl (verwendet Locale) Währungssymbol (verwendet Locale) Trennzeichen für Nachkommastellen nach Locale (also Komma auf Deutsch) Zeichen zur Tausendergruppierung nach Locale (Punkt auf Deutsch) Minuszeichen auf angegebener Position (wenn Zahl < 0) Pluszeichen auf angegebener Position (wenn Zahl > 0) Plus-/Minuszeichen auf angegebener Position römische Zahl (Eingabe zwischen 1 und 3999) englische Ordnungszahlendung um angegebene Anzahl Ziffern verschieben (siehe Hinweise) wissenschaftliche Schreibweise (noch nicht implementiert) Tabelle 9.999') to_char(1485.9') to_char(12.1.999') HH12:MI:SS') Ergebnis 'Tuesday . 'FMDay.9V99 nicht erlaubt. '0. aber to_char(-12. '9. ❏ V multipliziert den Eingabewert mit 10^n. dass 9 vor MI steht. '999') to_char(485. 'FM9. '9G999') to_char(148.500' 05:39:18' Tabelle 9. Ausdruck to_char(current_timestamp. SG und TH sind PostgreSQL-Erweiterungen. Die Oracle-Implementierung erlaubt nicht die Verwendung von MI vor 9.9') to_char(12.1' ' 0.) Tabelle 9. '9 9 9') to_char(1485.1' ' 0012. (Zum Beispiel ist 99. 'MI9999') ergibt '. wobei n die Anzahl der Ziffern nach V ist. '999') to_char(-485. wie die Funktion to_char verwendet werden kann. ❏ 9 ergibt einen Wert mit der gleichen Zahl von Ziffern.9') to_char(485. to_char unterstützt nicht die Verwendung von V mit einen Dezimalpunkt. FMDD HH12:MI:SS') to_char(-0. sondern erfordert.10' '-. '999. 06 05:39:18' 'Tuesday. 'Day. to_char(-12. ❏ PL.15: Mustervorlagen für die Formatierung von numerischen Werten (Forts. wie 9en vorhanden sind. ❏ TH funktioniert nicht mit Werten unter null oder mit Zahlen mit Bruchteilen.12'. 'FM9990999.1.

'FMRN') to_char(482. '9SG99') to_char(-485. bei denen unten steht. 'SG999') to_char(-485. '"Good number:"999') to_char(485.und Zeittypen aus Abschnitt 8. '9G999D999') to_char(-485. 'PL999') to_char(485. dass sie Werte vom Typ time oder timestamp verwenden. '999D999') to_char(3148. '"Pre:"999" Post:" . '99V9') Ergebnis ' 148. Des Platzes halber sind diese Varianten nicht getrennt aufgeführt.Kapitel 9 Ausdruck to_char(148.interval '23 hours' timestamp '2001-09-28' Tabelle 9.2. 'RN') to_char(485. timestamp without time zone.17 zeigt das Verhalten der grundlegenden arithmetischen Operatoren (+.5. '999PR') to_char(485.18 listet die verfügbaren Operatoren zur Verarbeitung von Datums.45.und Zeitangaben. timestamp with time zone und eine verwendet time without time zone bzw.8 Funktionen und Operatoren für Datum und Zeit Tabelle 9.4. 'SG999') to_char(-485.16: Beispiele für to_char (Forts. 'FMRN') to_char(5. Sie sollten mit den Hintergrundinformationen über die Datums.17: Operatoren für Datum/Zeit 156 . * usw. Alle Funktionen.) 9. '99V999') to_char(12. '999MI') to_char(485. '999S') to_char(-485. '999MI') to_char(485.500' ' 3 148.8. 'L999') to_char(485. gibt es in Wirklichkeit in zwei Varianten: Eine verwendet time with time zone bzw. Operator + + + - Beispiel timestamp '2001-09-28 01:00' + interval '23 hours' date '2001-09-28' + interval '1 hour' time '01:00' + interval '3 hours' date '2001-09-28' .800' ' 12000' ' 12400' ' 125' CDLXXXV' Tabelle 9. Formatierungsfunktionen finden Sie in Abschnitt 9.time '05:00' Ergebnis timestamp '2001-09-29 00:00' timestamp '2001-09-28 01:00' time '04:00' timestamp '2001-09-27 23:00' time '03:00' time '03:00:00' timestamp '2001-09-28 23:00' .5 vertraut sein.999') to_char(12.7.interval '2 hours' interval '2 hours' .interval '1 hour' time '05:00' .500' '485-' '485-' '485' '+485' '+485' '-485' '4-85' '<485>' 'DM 485 ' 'CDLXXXV' 'V' ' 482nd' 'Good number: 485' 'Pre: 485 Post: . '999th') to_char(485.5.). Einzelheiten finden Sie in den folgenden Unterabschnitten. '99V999') to_char(12. Tabelle 9.

2 Teilfeld ermitteln.8. siehe Abschnitt 16 20:38:40') 9.4 aktuelle Zeit mit Datum. siehe Abschnitt 9.0 00126 2001 EST Tabelle 9. siehe Abschnitt 9. siehe Abschnitt 9.8. interval '2 years 3 mit extract). siehe Abschnitt 9.8. siehe auch Abschnitt 9.4 timeofday() date_trunc('hour'.4 Beispiel Ergebnis age(timestamp '1957.Funktionen und Operatoren Operator * / Beispiel interval '1 hour' * int '3' interval '1 hour' / int '3' Ergebnis interval '03:00' interval '00:20' Tabelle 9.1 Teilfeld ermitteln.) Funktion age(timestamp) Ergebnistyp interval Beschreibung Subtraktion vom heutigen Datum Subtraktion heutiges Datum.4 aktuelle Zeit mit Datum.4 aktuelle Zeit. siehe auch Abschnitt 9.17: Operatoren für Datum/Zeit (Forts.8. timestamp) extract(feld from timestamp) extract(feld from interval) isfinite(times tamp) isfinite(inter val) localtime localtimestamp now() interval date time with time zone timestamp with time zone double precision double precision timestamp Teilfeld ermitteln (gleichbedeutend date_part('hour'. siehe Abschnitt 9.8.8.4 aktuelle Zeit mit Datum (gleichbedeutend mit current_timestamp).1 auf angegebene Genauigkeit abschneiden.4 aktuelle Zeit mit Datum.8.8. siehe auch Abschnitt 9.8.8.43 years 8 06-13') mons 3 days age('2001-04-10'.18: Funktionen für Datum/Zeit 157 . siehe Abschnitt 9. timestamp '1957-0613') 43 years 9 mons 27 days age(timestamp. timestamp) current_date current_time current_timest amp date_part(text .1 Teilfeld ermitteln (gleichbedeutend date_part('month'. timestamp) date_part(text . interval) date_trunc(tex t. timestamp '2001-02mit extract).8.8. siehe Abschnitt months') 9.1 auf endlichen Wert prüfen (ungleich infinity) auf endlichen Wert prüfen (ungleich infinity) aktuelle Zeit. siehe Abschnitt 9. timestamp '2001-0216 20:38:40') extract(hour from timestamp '2001-0216 20:38:40') extract(month from interval '2 years 3 months') isfinite(timestamp '2001-02-16 21:28:30') isfinite(interval '4 hours') 20 3 2001-02-16 20:00:00+0 0 20 double precision double precision boolean 3 true boolean time timestamp timestamp with time zone text true timeofday() Wed Feb 21 17:01:13.

dass das Ergebnis einfach das Jahr geteilt durch 100 ist und nicht die gebräuchliche Definition eines Jahrhunderts.und Zeitangaben Teilfelder. Sonntag ist 0) (nur für timestamp-Werte) SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 16 decade Das Jahr geteilt durch 10 SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 47 epoch Bei date. Ergebnis: 5 doy Die Nummer des Tages im Jahr (1-365/366) (nur für timestamp-Werte) SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40'). nach der mindestens die Jahre 1900 bis 1999 ins 20. Der Ergebnistyp der Funktion extract ist double precision. wie zum Beispiel das Jahr oder die Stunde.1 EXTRACT. Jahrhundert gehören. Ergebnis: 982352320 158 .Kapitel 9 9. (Ausdrücke mit Ergebnistyp date oder time werden automatisch in timestamp umgewandelt und können daher auch verwendet werden. Ergebnis: 20 Beachten Sie. die angibt. Gültige Feldnamen sind folgende: century Das Jahr geteilt durch 100 SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'). quelle ist ein Wertausdruck vom Typ timestamp oder interval. welches Feld aus dem Eingabewert ermittelt werden soll.8.) feld ist ein Name oder eine Zeichenkette. bei interval-Werten die Gesamtzahl der Sekunden in der Zeitspanne SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40').und timestamp-Werten die Anzahl der Sekunden seit 1970-01-01 00:00:00-00 (möglicherweise negativ). date_part EXTRACT (feld FROM quelle) Die Funktion extract ermittelt aus Datums. day Die Nummer des Tages im Monat (1-31) SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 200 dow Der Wochentag (0-6.

nach der zum Beispiel die Jahre 1900 bis 1999 ins zweite Jahrtausend gehören. Ergebnis: 28500 minute Das Minutenfeld (0-59) SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40'). einschließlich Bruchteile. multipliziert mit 1 000 000. milliseconds Das Sekundenfeld. Ergebnis: 38 month Bei timestamp-Werten die Nummer des Monats im Jahr (1-12). Ergebnis: 2 SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'). wenn man die Anzahl der Monate durch 12 teilt (0-11) SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 28500000 millennium Das Jahr geteilt durch 1000 SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 2 Beachten Sie. SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28. bei interval-Werten der Rest. Beinhaltet also auch ganze Sekunden.5'). SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28. dass das Ergebnis einfach das Jahr geteilt durch 1000 ist und nicht die gebräuchliche Definition eines Jahrtausends. einschließlich Bruchteile. multipliziert mit 1000.5').Funktionen und Operatoren SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'). Ergebnis: 3 SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'). Ergebnis: 20 microseconds Das Sekundenfeld. Ergebnis: 442800 hour Das Stundenfeld (0-23) SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40'). Beinhaltet also auch ganze Sekunden. Ergebnis: 1 159 .

Die Funktion date_part ist der alten Funktion aus Ingres nachempfunden. Ergebnis: 28. Die gültigen Feldnamen für date_part sind dieselben wie bei extract. entspricht aber der Funktion extract aus dem SQL-Standard: date_part('feld'. einschließlich Bruchteile (0-59 2) SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 16 2. in der sich der Tag befindet. SELECT date_part('day'. ist der erste Donnerstag eines Jahres in der Woche Nummer 1 dieses Jahres (nur für timestamp-Werte). Ergebnis: 40 SELECT EXTRACT(SECOND FROM TIME '17:12:28. SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'). quelle) Beachten Sie.Kapitel 9 quarter Das Quartal (1-4) in dem sich der Tag innerhalb des Jahres befindet (nur für timestamp-Werte) SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 7 year Das Jahr SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40').5'). Januar dieses Jahres. Laut Definition (ISO 8601) enthält die erste Woche eines Jahres den 4.) Anders ausgedrückt. 60 wenn das Betriebssystem Schaltsekunden unterstützt 160 . schauen Sie in Abschnitt 9. Um Datums. innerhalb des Jahres. (Nach ISO 8601 fängt eine Woche am Montag an.7.5 timezone_hour Der Stundenteil des Zeitzonenunterschieds timezone_minute Der Minutenteil des Zeitzonenunterschieds week Die Nummer der Woche. dass der Parameter feld ein Zeichenkettenwert sein muss. Ergebnis: 2001 Die Funktion extract ist vornehmlich für Berechnungen gedacht.und Zeitangaben für die Ausgabe zu formatieren. TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 1 second Das Sekundenfeld. kein Name.

8. Tabelle 9. Der Rückgabewert ist vom Typ timestamp. die kleiner als das angegebene sind. Ergebnis: 2001-02-16 20:00:00+00 SELECT date_trunc('year'. quelle) quelle ist ein Wertausdruck vom Typ timestamp. INTERVAL '4 hours 3 minutes').19 zeigt ihre Varianten.8. bei Tag und Monat). wobei alle Felder. date_trunc('feld'. (Werte vom Typ date und time werden automatisch umgewandelt.2 date_trunc Die Funktion date_trunc entspricht in etwa der Funktion trunc für Zahlen.3 AT TIME ZONE Die Klausel AT TIME ZONE ermöglicht die Umrechnung von Zeitangaben in andere Zeitzonen. TIMESTAMP '2001-02-16 20:38:40').Funktionen und Operatoren SELECT date_part('hour'. auf welche Genauigkeit der Wert abgeschnitten werden soll. Ergebnis: 2001-01-01 00:00:00+00 9. TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 4 9. Ausdruck timestamp without time zone AT TIME ZONE zone timestamp with time zone AT TIME ZONE zone time with time zone AT TIME ZONE zone Ergebnistyp timestamp with time zone timestamp without time zone time with time zone Beschreibung Ortszeit in angegebener Zeitzone in UTC umwandeln UTC in Ortszeit in angegebener Zeitzone umwandeln Ortszeit in andere Zeitzone übertragen Tabelle 9. auf null gesetzt sind (oder eins.19: Varianten von AT TIME ZONE 161 .) feld bestimmt. Gültige Werte für feld sind: microseconds milliseconds second minute hour day month year decade century millennium Beispiele: SELECT date_trunc('hour'.

Letztere entspricht dem SQL-Standard. Nach CURRENT_TIME. Ergebnis: 2001-02-16 18:38:40 Das erste Beispiel nimmt eine Zeit ohne Zeitzone.662522-05 SELECT CURRENT_DATE. Einige Beispiele: SELECT CURRENT_TIME.2 gab es die Präzisionsparameter nicht und das Ergebnis hatte immer nur ganzzahlige Sekunden. INTERVAL '-08:00') angegeben werden. Das zweite Beispiel nimmt eine Zeit in der Zone EST (UTC-5) und wandelt sie in eine Ortszeit in der Zone MST (UTC-7) um. Beispiele (mit aktueller Zeitzone PST8PDT): SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'MST'.4 Aktuelle Zeit Die folgenden Funktionen stehen zur Verfügung. timestamp) ist gleichbedeutend mit der Konstruktion timestamp AT TIME ZONE zone. Ergebnis: 14:39:53. LOCALTIME und LOCALTIMESTAMP kann wahlweise ein Parameter stehen. Ergebnis: 2001-02-16 19:38:40-08 SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST'. Ohne den Präzisionsparameter enthält das Ergebnis die volle mögliche Präzision. 'PST') oder als interval-Wert (z. 9.Kapitel 9 In diesen Ausdrücken kann die gewünschte Zeitzone zone als Zeichenkettenkonstante (z.B. nimmt die Zeitzone MST (UTC-7) an. wodurch das Ergebnis auf die angegebene Zahl von Nachkommastellen im Sekundenfeld gerundet wird. die von LOCALTIME und LOCALTIMESTAMP sind ohne Zeitzone. CURRENT_TIMESTAMP.B.8. um die aktuelle Zeit und/oder das aktuelle Datum abzufragen: CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_TIME ( präzision ) CURRENT_TIMESTAMP ( präzision ) LOCALTIME LOCALTIMESTAMP LOCALTIME ( präzision ) LOCALTIMESTAMP ( präzision ) Die Ergebnisse von CURRENT_TIME und CURRENT_TIMESTAMP sind mit Zeitzone. der die Präzision angibt. 162 . berechnet die Zeit in UTC und rechnet sie dann in PST (UTC-8) zur Ausgabe um. Anmerkung Vor PostgreSQL 7. Die Funktion timezone(zone.

163 . sodass. ihre Ergebnisse ändern sich während einer Transaktion nicht.66-05 SELECT LOCALTIMESTAMP. Ergebnis: 2001-12-23 14:39:53. Das Ergebnis von timeofday() ist allerdings die tatsächliche Zeit. wenn Sie eine Tabelle erstellen. Ergebnis: 2001-12-23 14:39:53. SELECT now(). wenn der Vorgabewert benötigt wird. die Zeit der Erzeugung der Tabelle herauskommen würde! Die ersten beiden Formen werden erst ausgewertet.Funktionen und Operatoren Ergebnis: 2001-12-23 SELECT CURRENT_TIMESTAMP. welche aus historischen Gründen einen Wert vom Typ text anstatt timestamp zurückgibt: SELECT timeofday().662522-05 SELECT CURRENT_TIMESTAMP(2). um die aktuelle Zeit anzugeben.und Zeittypen akzeptieren außerdem die spezielle Konstante now als Eingabe. Anmerkung Die dritte Form sollten Sie höchstwahrscheinlich nicht in einer DEFAULT-Klausel verwenden.000126 2001 EST Es ist wichtig zu wissen. SELECT TIMESTAMP 'now'. wenn der Vorgabewert verwendet wird. weil sie als Funktionsaufrufe zählen. Ferner gibt es die Funktion timeofday(). Anmerkung In anderen Datenbanksystemen könnte es sein. PostgreSQLspezifische Variante. dass CURRENT_TIMESTAMP und die verwandten Funktionen die Startzeit der aktuellen Transaktion ergeben. dass diese Werte sich auch während einer Transaktion ändern. Ergebnis: 2001-12-23 14:39:53. sobald die Konstante gelesen wird. Sie ist eine traditionelle. die sich auch während einer Transaktion ändert. Folglich haben alle drei dieser Befehle das gleiche Ergebnis: SELECT CURRENT_TIMESTAMP. Das System wandelt now in timestamp um. dass der Vorgabewert die Zeit des Einfügens der Zeile ergibt. Ergebnis: Sat Feb 17 19:07:32. Alle Datums. Daher bieten sie das gewünschte Verhalten.662522 Die Funktion now() ist gleichbedeutend mit CURRENT_TIMESTAMP.

0).9 Geometrische Funktionen und Operatoren Die geometrischen Typen point.1)' @ circle '((0.(-1.0)' ?.1)' >^ circle '((0.(-1.0).0).0).0).(-1.5).2))' point '(1.-1))' # '((1.1)' >> circle '((0.0).(1.0))' ?# box '((-2.(3.0).(2.0))' point '(0.0.1). line.2))' / point '(2.0).-1).0).(2.(0. lseg.0)' box '((0.1))' .(1.21 und Tabelle 9.0).2).(2.1)' << circle '((5.0.2))' box '((0.0).1))' + point '(2. box.0).20: Geometrische Operatoren 164 .1)' <^ circle '((0.3))' &> box '((0.1)' circle '((0.point '(0.0).0)' box '((0.1))' && box '((0.0).20.(0.0)' '((1. Tabelle 9.(1.0).0).1))' ?-| lseg '((0.(1.0)' lseg '((-1.22 gezeigt werden.0))' ?|| lseg '((1.0)' lseg '((0.(0.5).0))' point '(0.0)' box '((0.1))' &< box '((0.10)' polygon '((0.0))' Tabelle 9.0))' @-@ path '((0. polygon und circle haben eine große Zahl zugehöriger Funktionen und Operatoren.(1.(1.2))' box '((0.0).(1.(2.0).2))' point '(1.1)' lseg '((-1.2))' box '((0.1)' <-> circle '((5.point '(2.(1.(1.0).(0.(1.0).0.1).0).1)' ?| point '(0.(1.2))' circle '((0.2).1)' circle '((0.1)' circle '((5.0).0).0).2)' @@ circle '((0.0).1))' * point '(2.0)' ## lseg '((2.1))' ~= polygon '((1.0.1)' circle '((0.0).0).1))' # '((1.(2. welche in Tabelle 9.Kapitel 9 9.0).1). Operator + * / # # ## && &< &> <-> << <^ >> >^ ?# ??-| @-@ ?| ?|| @ @@ ~= Beschreibung Verschiebung Verschiebung Dehnung/Drehung Dehnung/Drehung Schnittpunkt oder -rechteck Anzahl der Punkte in Pfad oder Polygon zu erstem Operanden nächstliegender Punkt auf zweitem Operanden liegt Überschneidung vor? liegt Überschneidung links vor? liegt Überschneidung rechts vor? Abstand liegt links von? liegt unterhalb von? liegt rechts von? liegt oberhalb von? schneidet? ist horizontal? steht senkrecht auf? Länge oder Umfang ist vertikal? sind parallel? liegt innerhalb oder darauf? Mittelpunkt identisch? Beispiel box '((0. path.

22: Geometrische Typumwandlungsfunktionen 165 .0).0).1))') Pfad in geschlossenen umwandeln popen(path Pfad in offenen umwandeln Radius des Kreises Breite des Rechtecks Tabelle 9.1).0)') height(box '((0.0).0))') npoints(path '[(0.1).0)') width(box '((0.0))') isopen(path '[(0.1).0))') circle(box '((0.(1. point) box(polygon) circle(box) circle(point.0).(1.(1.(1.(0.0))') Tabelle 9.(2.1).0)') box(point '(0.(1.21: Geometrische Funktionen Funktion box(circle) box(point.(2.0)]') popen(path '((0.0).0).(1.0).(1.-2).(1. double precision) lseg(box) lseg(point. lseg) point(polygon) Ergebnistyp box box box circle circle lseg lseg point point point point Beschreibung Kreis in Rechteck Punkte in Rechteck Polygon in Rechteck Rechteck in Kreis Punkt und Radius in Kreis Rechteckdiagonale in Strecke Punkte in Strecke Polygon in Pfad Mittelpunkt des Kreises Schnittpunkt Mittelpunkt des Polygons Beispiel box(circle '((0.(1.5).0.0).1))') circle(point '(0.box '((0.0).(2.(1.0))') radius(circle '((0.2.0).(1.1).0)'.0)') path(polygon '((0.1).2.(1.1).0)'.1)') box(polygon '((0.0).2))') diameter(circle '((0. lseg '((-2.0).Funktionen und Operatoren Funktion area(objekt) box(box.1))') isclosed(path '((0.(2.(1. point '(1.0))') point(circle '((0.(1.(2.0).(1.2.0). point '(1.(2. 2.1))') box(box '((0.0)'.1))'.0).0).(2.0))'.1).0))') lseg(point '(-1.(2.2))') point(polygon '((0.0).2))') center(box '((0.0)') point(lseg '((-1.0).0)]') length(path '((1.(2.2.0). box) center(objekt) diameter(circle ) height(box) isclosed(path) isopen(path) length(objekt) npoints(path) npoints(polygon ) pclose(path) popen(path) radius(circle) width(box) Ergebnistyp double precision box point double precision double precision boolean boolean double precision integer integer path path double precision double precision Beschreibung Flächeninhalt Schnittrechteck Mittelpunkt Durchmesser des Kreises Höhe des Rechtecks geschlossener Pfad? offener Pfad? Länge Anzahl der Punkte Anzahl der Punkte Beispiele area(box '((0.0).0))') '[(0.(1.1).0)]') npoints(polygon '((1.0) lseg(box '((-1.(2. point) path(polygon) point(circle) point(lseg.0).(1.5.

168.168.168.5' = inet '192.0).) Es ist möglich. als ob point ein Array mit Indizes 0 und 1 wäre.168.1.168.168.2.5' inet '192.1.1.1. Sie betrachten dafür nur den Netzwerkteil der beiden Adressen und ignorieren einen möglichen Host-Teil. Funktion broadcast(inet) host(inet) Ergebnistyp Beschreibung inet text Beispiel Ergebnis Broadcast-Adresse des Netzwerks IP-Adresse als Text auslesen broadcast('192.1. auf die beiden Zahlen in einem Wert des Typs point zuzugreifen. Sie können einen Textwert mit der normalen Umwandlungssyntax in inet umwandeln: inet(ausdruck) oder spaltennamen::inet.(1.1. Die Operatoren <<.1/24' >>= inet '192.23 zeigt die Operatoren.168.1/24' inet'192.168.1. Operator < <= = >= > <> << <<= >> >>= Beschreibung ist kleiner als ist kleiner als oder gleich ist gleich ist größer als oder gleich ist größer als ist ungleich ist enthalten in ist enthalten in oder ist gleich enthält enthält oder ist gleich Beispiel inet '192.5' <> inet '192.p eine Spalte vom Typ point ist.Kapitel 9 Funktion polygon(box) polygon(circle) polygon(npkte.24: Funktionen für cidr und inet 166 .5' > inet '192.1/24' >> inet '192. die für die Typen cidr und inet zur Verfügung stehen.(2.1. 9. Die Funktionen host. circle Pfad in Polygon polygon(path '((0.168.10 Funktionen für Netzwerkadresstypen Tabelle 9.23: Operatoren für cidr und inet Tabelle 9.2.168.1).168.168.168. ob ein Subnetz in einem anderen Netz enthalten ist.1 192.255 .168.(1.5' inet '192.4' inet '192.22: Geometrische Typumwandlungsfunktionen (Forts. Ebenso können Werte vom Typ box und lseg als Array zweier Werte vom Typ point behandelt werden.168.1))') Kreis in 12-Punkte Polygon polygon(circle '((0. dann ergibt SELECT p[0] FROM t die X-Koordinate und UPDATE t SET p[1] = .168.0).168.0)..1.1/24' <<= inet '192. >> und >>= überprüfen.1.168.5 Tabelle 9.168.1.1.5' << inet '192.6' inet '192.5' < inet '192.1. ändert die Y-Koordinate.24 zeigt die Funktionen.168.1.4' inet '192.168.0). circle) polygon(path) Ergebnistyp polygon polygon polygon polygon Beschreibung Beispiel Rechteck in 4-Punkte-Polygon polygon(box '((0.1/24' Tabelle 9. die für die Typen cidr und inet zur Verfügung stehen. Wenn zum Beispiel t.5' <= inet '192.168.0))') Tabelle 9.5' inet '192.5/ 24') 192. text und abbrev bieten in der Hauptsache alternative Ausgabeformate für Werte dieser Typen.0)') '((0.0)') Kreis in npkte-Punkte-Polygon polygon(12.1.5' >= inet '192.5/24') /24 host('192.1. <<=.168.168..5' inet '192.1/24' inet '192.1.

die mit dem Befehl CREATE SEQUENCE erzeugt werden. bigint) setval(text.255.1.25 zeigt die Funktionen. <= usw.1. bieten einfache und für den Mehrbenutzerbetrieb geeignete Methoden.1.5/ 32 10.0/16') Tabelle 9.5/24'.1.168.11 Funktionen zur Bearbeitung von Sequenzen Dieser Abschnitt beschreibt die Funktion von PostgreSQL zur Verwendung mit Sequenzobjekten.1.0 /24') ermitteln Netzwerkteil der Adresse auslesen network('192. der zuletzt durch nextval erzeugt wurde aktuellen Wert der Sequenz setzen aktuellen Wert der Sequenz und den Parameter is_called setzen Tabelle 9.) zur lexikographischen Sortierung.1/16 text(inet IP-Adresse und Netzmaskenlänge als Text '192.5 255.168.0/ /24') 24 192.168. Damit kann der übrig gebliebene Präfix mit einem Hersteller in Verbindung gebracht werden.5 24 /24') set_masklen('192.i nteger) netmask(inet) network(inet) text(inet) Ergebnistyp Beschreibung integer inet inet cidr text Beispiel Ergebnis Netzmaskenlänge auslesen Netzmaskenlänge für inet-Wert setzen masklen('192. 9.255.168 192.1.26 gelistet sind.5 192. Ein Sequenzobjekt wird normalerweise verwendet. um laufende Werte aus Sequenzobjekten zu erhalten. Die Funktion trunc(macaddr) ergibt die MAC-Adresse mit den letzten 3 Bytes auf null gesetzt.24: Funktionen für cidr und inet (Forts. bigint.16) 16 Netzmaske des Netzwerks netmask('192. Die Sequenzfunktionen.168. boolean) Ergebnistyp bigint bigint bigint bigint Beschreibung Sequenz erhöhen und neuen Wert zurückgeben Wert.1.1.25: Funktionen für macaddr Der Typ macaddr hat auch die normalen Vergleichsoperatoren (>. Das Verzeichnis contrib/mac in der Quelltext-Distribution enthält einige Hilfsmittel. welche in Tabelle 9.168.0.Funktionen und Operatoren Funktion masklen(inet) set_masklen(inet. die für den Typ macaddr zur Verfügung stehen.5') auslesen abbrev(inet) text abgekürztes Ausgabeformat als Text abbrev(cidr '10.26: Sequenzfunktionen 167 .1. um eine solche Assoziierungstabelle zu erstellen und zu pflegen.168. Funktion nextval(text) currval(text) setval(text. um für die Zeilen einer Tabelle laufende Nummern zur eindeutigen Identifikation zu erzeugen.) Tabelle 9.168.5/ . Sequenzobjekte (auch Sequenzgeneratoren oder einfach Sequenzen genannt) sind besondere Tabellen mit einer einzigen Zeile. Funktion trunc(macaddr) Ergebnistyp Beschreibung macaddr Beispiel trunc(macaddr '12:34:56:78:90:ab') Ergebnis 12:34:56:00:00:00 letzte 3 Bytes auf null setzen Tabelle 9.

sich gegenseitig blockieren. 42). Nächster nextval ergibt 43 ebenso Nächster nextval ergibt 42 Das Ergebnis von setval ist einfach der Wert des zweiten Arguments. Also gilt: nextval('foo') betrifft die Sequenz foo nextval('FOO') betrifft die Sequenz foo nextval('"Foo"') betrifft die Sequenz Foo Der Sequenzname kann. was heißt. werden nextval-Operationen nicht zurückgerollt. true). später abgebrochen wird. dann ergibt der nächste Aufruf von nextval genau den angegebenen Wert und die Erhöhung der Sequenz beginnt erst mit den folgenden Aufruf von nextval. der zuletzt in der aktuellen Sitzung von nextval für diese Sequenz zurückgegeben wurde.foo nextval('"meinschema".foo') betrifft meinschema. Das heißt. Die Form mit zwei Argumenten setzt das Feld last_value (letzter Wert) der Sequenz auf den angegebenen Wert und setzt das Feld is_called auf logisch wahr. In der Form mit drei Argumenten kann is_called auf wahr oder falsch gesetzt werden.) Beachten Sie. false). wenn notwendig. 42. bevor ein Wert zurückgegeben wird. die gleichzeitig Zahlen von einer Sequenz erhalten wollen. Zum Beispiel: SELECT setval('foo'. 42. wandeln die Sequenzfunktionen ihre Argumente in Kleinbuchstaben um. außer wenn die Zeichenkette in Anführungszeichen steht. SELECT setval('foo'. wenn zur selben Zeit in anderen Sitzungen nextval ausgerufen wird. Das bedeutet. 168 . wenn ein Wert einmal abgegeben wurde. Wenn es auf falsch gesetzt wird. dass der nächste Aufruf von nextval den Sequenzwert erst erhöht. Das kann gelegentlich nützlich sein. durch ein Textargument angegeben. (Ein Fehler wird ausgegeben. um einen Schemanamen ergänzt werden: nextval('meinschema.foo') ebenso nextval('foo') sucht im Pfad nach foo Natürlich kann das Textargument ein Ausdruck sein und nicht nur eine einfach Konstante. dass das Ergebnis speziell für diese Sitzung gilt und auch noch gültig bleibt. erhält jede Sitzung einen unterschiedlichen Sequenzwert. Die verfügbaren Sequenzfunktionen sind: nextval Erhöhe die Sequenz zum nächsten Wert und gib diesen Wert zurück. setval-Operationen werden auch nicht zurückgerollt. dass abgebrochene Transaktionen unbenutzte “Löcher” in der Reihe der erzeugten Werte verursachen können. Wichtig Um zu verhindern. dass Transaktionen. wenn nextval für diese Sequenz in dieser Sitzung noch nie aufgerufen wurde. SELECT setval('foo'. selbst wenn die Transaktion. dann wird er als verwendet betrachtet. Das geschieht atomar: Selbst wenn mehrere Sitzungen nextval gleichzeitig aufrufen. die durch eine Sequenzfunktion bearbeitet wird. currval Gib den Wert zurück. die nextval aufgerufen hatte.Kapitel 9 Aus im Großen und Ganzen historischen Gründen wird die Sequenz. Um eine gewisse Kompatibilität mit der Behandlung von normalen SQL-Namen zu erreichen. setval Stellt den Zähler für diese Sequenz zurück.

ergeben Aufrufe von nextval aufeinander folgende Werte bei 1 beginnend.1 CASE Der CASE-Ausdruck ist ein allgemeiner konditionaler Ausdruck. dann ist das Ergebnis des CASE-Ausdrucks das nach der Bedingung stehende ergebnis. ähnlich if/else-Anweisungen in anderen Sprachen: CASE WHEN bedingung THEN ergebnis [WHEN . Ein Beispiel: SELECT * FROM test. bedingung ist ein Ausdruck. der ein Ergebnis vom Typ boolean liefert.12 Konditionale Ausdrücke Dieser Abschnitt beschreibt die in PostgreSQL verfügbaren konditionalen Ausdrücke. eine serverseitige Prozedur in einer ausdrucksfähigeren Sprache zu schreiben. CASE WHEN a=1 THEN 'one' WHEN a=2 THEN 'two' ELSE 'other' 169 . 9... Tipp Wenn Ihre Anforderungen die von diesen konditionalen Ausdrücken gebotenen Fähigkeiten überschreiten. welche auch dem SQL-Standard entsprechen. Wenn das Ergebnis logisch wahr ist. werden etwaige folgende WHERE-Klauseln auf dieselbe Art durchsucht. Andere Verhalten können mit besonderen Parametern in dem Befehl CREATE SEQUENCE eingestellt werden. a --1 2 3 SELECT a. wo ein Ausdruck gültig ist.Funktionen und Operatoren Wenn ein Sequenzobjekt mit den Vorgabewerten erstellt wurde. siehe die Referenzseite des Befehls für weitere Informationen. ist das Ergebnis der NULL-Wert. 9. sollte Sie in Erwägung ziehen. Wenn das Ergebnis aber falsch ist.12. Wenn die ELSE-Klausel weggelassen wurde und keine Bedingung stimmt.] [ELSE ergebnis] END CASE-Klauseln können überall verwendet werden. Wenn keine der Bedingungen in WHERE wahr ist. dann ist das Ergebnis des CASE-Ausdrucks das ergebnis in der ELSE-Klausel.

Siehe Abschnitt 10. Der folgende “einfache” CASE-Ausdruck ist eine spezialisierte Variante der oben beschriebenen Form: CASE ausdruck WHEN wert THEN ergebnis [WHEN . CASE a WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'other' END FROM test. um bei der Ausgabe für NULL-Werte einen Vorgabewert einzusetzen.] [ELSE ergebnis] END ausdruck wird berechnet und mit allen wert-Angaben in den WHERE-Klauseln verglichen. die gleich ist.2 COALESCE COALESCE(wert [.]) Die Funktion COALESCE gibt das erste ihrer Argumente zurück. a | case ---+------1 | one 2 | two 3 | other Es muss möglich sein. welches nicht NULL ist. Das kann oft nützlich sein.. Diese Konstruktion ist also mit der switch-Anweisung in C vergleichbar...12. Wenn keine Übereinstimmung gefunden wird. bis eine gefunden wird..5 bezüglich Einzelheiten. . 170 . kurzbeschreibung. '(keine)') . dann wird das ergebnis in der ELSEKlausel (bzw. zum Beispiel: SELECT COALESCE(beschreibung. a | case ---+------1 | one 2 | two 3 | other 9. der NULL-Wert) zurückgegeben.Kapitel 9 END FROM test. Das obige Beispiel kann mit der einfachen CASE-Syntax geschrieben werden: SELECT a. die Datentypen aller ergebnis-Ausdrücke in einen einzigen Ergebnistyp umzuwandeln...

wahlweise einschließlich der impliziten Schemas Benutzername der aktuellen Ausführungsumgebung Benutzername der Sitzung äquivalent mit current_user PostgreSQL-Versionsinformationen current_schemas(boolean) name[] current_user session_user user version() name name name text Tabelle 9. in dem Tabellen oder andere Objekte angelegt werden. der die Datenbankverbindung eingeleitet hat. Name current_database() current_schema() Ergebnistyp name name Beschreibung Name der aktuellen Datenbank Name des aktuellen Schemas Namen der Schemas in Suchpfad.und Systeminformationen ermitteln. wert2) Die Funktion NULLIF ergibt den NULL-Wert genau dann.13 Diverse Funktionen Tabelle 9. die Sitzungs. Normalerweise sind beide Benutzer gleich. wenn bei deren Erzeugung kein Schema angegeben wird.Funktionen und Operatoren 9. Sie werden beim Parsen früh in CASE-Ausdrücke umgewandelt und in der folgenden Verarbeitung wird dann gedacht.3 NULLIF NULLIF(wert1. Tipp COALESCE und NULLIF sind eigentlich nur Kurzformen von CASE-Ausdrücken. der von der Funktion session_user ermittelt wird. session_user und user haben einen besonderen syntaktischen Status in SQL: Sie müs- sen ohne Klammern aufgerufen werden. die sich auf CASE beziehen. das am Anfang des Suchpfads steht (oder den NULL-Wert.. 9.12. wenn der Suchpfad leer ist). ist der Benutzer.27: Sitzungsinformationsfunktionen Der Benutzer. um die Umkehrung des COALESCEBeispiels von oben durchzuführen: SELECT NULLIF(wert. Ansonsten wird wert1 zurückgegeben. der für die Prüfung von Zugriffsrechten verwendet wird. Im Unix-Jargon wäre session_user der “reale Benutzer” und current_user der “effektive Benutzer”. Anmerkung current_user. der von der Funktion current_user zurückgegeben wird. Das ist das Schema. current_schemas(boolean) ergibt ein 171 . '(keine)') . wenn wert1 und wert2 gleich sind. Eine fehlerhafte Verwendung von COALESCE oder NULLIF kann daher zu Fehlermeldungen führen. man hat es mit wirklichen CASE-Ausdrücken zu tun. ist der Benutzer. Diese Funktion kann verwendet werden. er ändert sich während der gesamten Verbindung nicht..27 zeigt einige Funktionen. aber current_user ändert sich während der Ausführung von Funktionen mit dem Attribut SECURITY DEFINER. current_schema gibt das Schema zurück. Der Benutzer.

29: Funktionen zur Abfrage von Zugriffsprivilegien 172 . Die Funktion entspricht dem SQL-Befehl SET.29 listet Funktionen. lokal) text Tabelle 9. Ein Beispiel: SELECT current_setting('datestyle'). Wenn lokal logisch wahr ist. wie zum Beispiel pg_catalog. neuer_wert. dann gilt der neue Wert nur für die aktuelle Transaktion. die gegenwärtig im Suchpfad sind.Kapitel 9 Array mit den Namen aller Schemas. Der Befehl lautet: SET search_path TO schema [. privileg) Ergebnistyp boolean boolean Beschreibung Benutzer hat Privileg für Tabelle aktueller Benutzer hat Privileg für Tabelle Tabelle 9.28 zeigt die Funktionen zur Abfrage und Veränderung von Konfigurationsparametern. die es dem Benutzer ermöglichen. die die Version des PostgreSQL-Servers beschreibt. 'off'. Sie entspricht dem SQL-Befehl SHOW. Name has_table_privilege(benutzer. false).. set_config -----------off (1 row) Tabelle 9.. Die boolean-Option bestimmt. . privileg) has_table_privilege(tabelle. dann geben Sie logisch falsch an. current_setting --------------------------------------ISO with US (NonEuropean) conventions (1 row) set_config setzt den Konfigurationsparameter parametername auf neuer_wert. Ein Beispiel: SELECT set_config('show_statement_stats'. Wenn der neue Wert für die aktuelle Sitzung gelten soll. ob implizite Systemschemas.6. tabelle. Weitere Informationen über Privilegien finden Sie in Abschnitt 5. Name current_setting(parametername) Ergebnistyp Beschreibung text aktueller Wert des Parameters setzt Parameter und gibt neuen Wert zurück set_config(parametername. Anmerkung Der Suchpfad kann zur Laufzeit geändert werden. Tabelle 9.schema .] Die Funktion version() ergibt eine Zeichenkette. im Ergebnis mit auftauchen.28: Funktionen zur Kontrolle von Konfigurationsparametern Die Funktion current_setting ergibt den aktuellen Wert des Konfigurationsparameters parametername als Teil eines Anfrageergebnisses. die Zugriffsprivilegien für Objekte programmatisch zu untersuchen.

die feststellen. has_schema_privilege prüft. has_language_privilege prüft. Wenn die Funktion als Zeichen- kette statt als OID angegeben wird. Gleichbedeutend heißt. wenn das Argument ausgelassen wird. REFERENCES oder TRIGGER. INSERT. wenn nötig. Die möglichen Argumente sind analog zu has_table_privilege.usesysid) angegeben werden. Tabelle 9. Eine Tabelle wird als sichtbar bezeichnet. welche sich durch die Zahl und die Typen der Argumente unterscheiden. RULE. dass auf die Tabelle verwiesen werden kann. (Es gibt also eigentlich sechs Varianten von has_table_privilege. Das gewünschte Zugriffsprivileg muss gegenwärtig immer gleich EXECUTE sein.) Ein Beispiel ist: SELECT has_table_privilege('meinschema. privileg) has_language_privilege(sprache. im Suchpfad steht und keine Tabelle mit dem gleichen Namen vorher im Suchpfads steht.) has_table_privilege prüft. (Groß. welche gleich einem der folgenden Werte sein muss: SELECT. das sie enthält. ob ein Benutzer auf eine Datenbank auf eine bestimmte Art zugreifen darf. ob ein bestimmtes Objekt im aktuellen Schemasuchpfad sichtbar ist. Das gewünschte Zugriffsprivileg wird durch eine Zeichenkette angegeben. privileg) has_language_privilege(benutzer. schema. ohne einen Schemanamen anzugeben.meinetabelle'. um die Namen aller sichtbaren Tabellen anzuzeigen: 173 .Funktionen und Operatoren Name Ergebnistyp Beschreibung Benutzer hat Privileg für Datenbank aktueller Benutzer hat Privileg für Datenbank Benutzer hat Privileg für Funktion aktueller Benutzer hat Privileg für Funktion Benutzer hat Privileg für Sprache aktueller Benutzer hat Privileg für Sprache Benutzer hat Privileg für Schema aktueller Benutzer hat Privileg für Schema has_database_privilege(benutzer. Der Benutzer kann als Name oder als ID (pg_user. UPDATE. funktion. privileg) has_schema_privilege(schema. ob ein Benutzer auf ein Schema auf eine bestimmte Art zugreifen darf. Die möglichen Argumente sind analog zu has_table_privilege. Das gewünschte Zugriffsprivileg muss gleich CREATE. ob ein Benutzer auf eine prozedurale Sprache auf eine bestimmte Art zugreifen darf. sind die erlaubten Eingabewerte die gleichen wie beim Datentyp regprocedure. datenbank. Die möglichen Argumente sind analog zu has_table_privilege. durch ein Schema ergänzt werden. dann wird current_user angenommen. Die möglichen Argumente sind analog zu has_table_privilege. 'select'). has_database_privilege prüft. Die Tabelle kann als Name oder als OID angegeben werden.) Wenn ein Name angegeben wird. privileg) has_schema_privilege(benutzer. privileg) has_function_privilege(funktion. has_function_privilege prüft. ob ein Benutzer auf eine Tabelle auf eine bestimmte Art zugreifen darf. ob ein Benutzer auf eine Funktion auf eine bestimmte Art zugreifen darf. sprache.29: Funktionen zur Abfrage von Zugriffsprivilegien (Forts.oder Kleinschreibung ist unerheblich. privileg) boolean boolean boolean boolean boolean boolean boolean Tabelle 9.30 zeigt Funktionen. privileg) has_function_privilege(benutzer. TEMPORARY oder TEMP (was äquivalent mit TEMPORARY ist) sein. privileg) boolean has_database_privilege(datenbank. wenn das Schema. Das gewünschte Zugriffsprivileg muss gegenwärtig immer gleich USAGE sein. Das gewünschte Zugriffsprivileg muss gleich CREATE oder USAGE sein. Folgende Anfrage kann zum Beispiel verwendet werden. kann er. DELETE.

Operatorklassen aus. Wenn Sie ein Objekt dem Namen nach überprüfen wollen. Name pg_get_viewdef(sicht_name) pg_get_viewdef(sicht_oid) pg_get_ruledef(regel_oid) pg_get_indexdef(index_oid) pg_get_constraintdef(constraint _oid) pg_get_userbyid(benutzer_id) Ergebnistyp text text text text text name Beschreibung ermittle CREATE VIEW-Befehl für Sicht (veraltet) ermittle CREATE VIEW-Befehl für Sicht ermittle CREATE RULE-Befehl für Sicht ermittle CREATE INDEX-Befehl für Index ermittle Definition des Constraints ermittle Benutzername für Benutzernummer Tabelle 9. dass dies eine Wiederzusammensetzung ist und nicht der Originaltext des Befehls.32 gezeigten Funktionen ermitteln Kommentare. (Beachten Sie. pg_type_is_visible. Operatoren bzw. wenn kein passender Kommentar für die angegebenen Parameter gefunden werden konnte. können Sie die OID-Aliastypen (regclass. um das zu überprüfende Objekt zu identifizieren. pg_get_ruledef. regprocedure oder regoperator) verwenden. wenn es kein anderes Objekt mit dem gleichen Namen und den gleichen Argumentdatentypen vorher im Pfad gibt.) pg_get_constraintdef nur mit Fremdschlüssel-Constraints. Bei Funktionen und Operatoren gilt. ein Objekt im Suchpfad ist sichtbar. 174 . einer Regel. Gegenwärtig funktioniert pg_get_userbyid ermittelt den Benutzernamen. der zur angegebenen Benutzernummer gehört.Kapitel 9 SELECT relname FROM pg_class WHERE pg_table_is_visible(oid). zum Beispiel: SELECT pg_type_is_visible('myschema. Tabelle 9. muss er auch sichtbar sein. welche vorher mit dem Befehl COMMENT erzeugt wurden. pg_operator_ is_visible und pg_opclass_is_visible führen die gleiche Art von Sichtbarkeitsprüfung für Daten- typen. die Informationen aus den Systemkatalogen herausholen. pg_get_viewdef. regtype.31: Systemkataloginformationsfunktionen Die in Tabelle 9. der zur Erzeugung einer Sicht.widget'::regtype). Funktionen.31 listet Funktionen. dass es keinen Sinn macht. pg_function_is_visible. Bei Operatorklassen wird sowohl der Name als auch die zugehörige Indexmethode betrachtet. Name pg_table_is_visible(tabellen_oid) pg_type_is_visible(typ_oid) pg_function_is_visible(funktions_oid) pg_operator_is_visible(operator_oid) pg_opclass_is_visible(opklassen_oid) Ergebnistyp boolean boolean boolean boolean boolean Beschreibung ist Tabelle im Suchpfad sichtbar ist Typ im Suchpfad sichtbar ist Funktion im Suchpfad sichtbar ist Operator im Suchpfad sichtbar ist Operatorklasse im Suchpfad sichtbar Tabelle 9. eines Index bzw. einen unqualifizierten Namen auf diese Art zu überprüfen. denn wenn der Name überhaupt erkannt würde. Alle diese Funktionen verlangen die OID. eines Constraints erforderlich ist. Ein NULL-Wert wird zurückgegeben. pg_get_constraintdef rekonstruie- ren den Befehl. Beachten Sie.30: Funktionen zur Überprüfung der Schemasichtbarkeit pg_table_is_visible führt die Überprüfung für Tabellen (oder Sichten oder andere Objekte mit Eintrag in pg_class) aus. pg_get_indexdef bzw.

real.33 zeigt die eingebauten Aggregatfunktionen. der die angegebene OID hat und der im angegebenen Systemkatalog gespeichert ist. Zeichenkette oder Datum/Zeit numerisch. integer. obj_description kann für Tabellenspalten nicht ver- wendet werden. spaltennummer) Ergebnistyp text text text Beschreibung ermittle Kommentar für Datenbankobjekt ermittle Kommentar für Datenbankobjekt (veraltet) ermittle Kommentar für Tabellenspalte Tabelle 9.Funktionen und Operatoren Name obj_description(objekt_oid. da es keine Garantie dafür gibt.2. Funktion avg(ausdruck) Argumenttyp smallint. double precision Beschreibung Durchschnitt (arithmetisches Mittel) aller Eingabewerte für Fließkommaargumente. In Teil I finden Sie weiteres einführendes Material dazu. Zeichenkette oder Datum/Zeit smallint.33: Aggregatfunktionen 175 . integer. da Spalten keine eigenen OIDs haben. ansonsten gleich dem Argumentdatentyp bigint bigint count(*) count(ausdruck) Anzahl der Eingabewerte Anzahl der Eingabewerte. ansonsten numeric Tabelle 9.14 Aggregatfunktionen Aggregatfunktionen berechnen ein einzelnes Ergebnis aus einer Sammlung von Eingabewerten. daher könnte der falsche Kommentar zurückgegeben werden. Die besonderen Syntaxanforderungen für Aggregatfunktionen werden in Abschnitt 4. col_description gibt den Kommentar für eine Tabellenspalte zurück. katalog_name) obj_description(objekt_oid) col_description(tabellen_oid. Die Form von obj_description mit einem Parameter braucht nur die OID des Objekts. bigint. Zum Beispiel würde obj_description(123456. für die ausdruck nicht gleich dem NULL-Wert ist Maximalwert von ausdruck aus allen Eingabewerten Minimalwert von ausdruck aus allen Eingabewerten Standardabweichung der Eingabewerte egal max(ausdruck) min(ausdruck) numerisch.5 erklärt. Diese Form ist jetzt nicht mehr empfohlen. dass OIDs über alle Systemkataloge eindeutig sind. 9. real.'pg_class') den Kommentar für die Tabelle mit der OID 123456 ermitteln. numeric oder interval Ergebnistyp numeric für ganzzahlige Argumente. welche durch die OID ihrer Tabelle und der Spaltennummer angegeben wird. bigint. double precision oder numeric gleich dem Argumenttyp gleich dem Argumenttyp stddev(ausdruck) double precision für Fließkommaargumente. Tabelle 9.32: Funktionen zur Ermittlung von Kommentaren Die Form von obj_description mit zwei Parametern gibt den Kommentar des Datenbankobjekts zurück. double precision.

9. Die Funktion coalesce kann verwendet werden. was man vielleicht erwartet hätte. double precision. integer. Insbesondere ergibt sum ohne Zeilen den NULL-Wert und nicht numerisch null. ansonsten gleich dem Argumenttyp double precision für variance(ausdruck) smallint. ob mindestens eine Zeile zurückgegeben wird. nicht bis zum Ende.15. dass außer count all diese Funktionen den NULL-Wert zurückgeben. Es gibt von dieser Regel jedoch Ausnahmen.B. selbst wenn es mehrere passende Zeilen in tab2 gibt: SELECT col1 FROM tab1 WHERE EXISTS(SELECT 1 FROM tab2 WHERE col2 = tab1. Es ist nicht zu empfehlen.15 Ausdrücke mit Unteranfragen Dieser Abschnitt beschreibt die in PostgreSQL vorhandenen. ob sie irgendwelche Zeilen ergibt. um festzustellen.oder integer-Argumente. double precision oder numeric Fließkommaargumente. real. wenn keine Zeilen ausgewählt sind. wie zum Beispiel bei Unteranfragen. Die Unteranfrage kann auf Variablen aus der übergeordneten Anfrage verweisen.1 EXISTS EXISTS ( unteranfrage ) Das Argument von EXISTS ist ein beliebiger SELECT-Befehl oder eine Unteranfrage. numeric für bigint-Argumente. wenn die Unteranfrage keine Zeilen liefert. Es ist daher gebräuchlich. integer. die Nebeneffekte hat (z. numeric oder interval Ergebnistyp bigint für smallint. SQL-konformen Ausdrücke mit Unteranfragen. Da das Ergebnis nur davon abhängt. was der Inhalt der Zeilen ist. und nicht. 176 . die INTERSECT verwenden. Alle hier beschriebenen Ausdrücke haben einen Rückgabewert vom Typ boolean (wahr/falsch). double precision für Beschreibung Summe von ausdruck für alle Eingabewerte Fließkommaargumente.col2). ansonsten numeric Varianz der Eingabewerte (Quadrat der Standardabweichung) Tabelle 9. ob die Nebeneffekte auftreten. durch andere Werte zu ersetzen. wenn gewünscht. real.) zu schreiben. eine Unteranfrage zu schreiben. ob irgendwelche Zeilen zurückgegeben werden.) Es ist anzumerken. aber es erzeugt höchstens eine Ergebniszeile für jede Zeile in tab1. das Aufrufen von Sequenzfunktionen).. könnte schwer vorherzusagen sein. Die Unteranfrage wird ausgewertet. ist das Ergebnis von EXISTS “falsch”. Dieses einfache Beispiel ist wie ein innerer Verbund über col2. Wenn Sie mindestens eine Zeile liefert. bis festgestellt werden kann.33: Aggregatfunktionen (Forts. alle EXISTS-Prüfungen in der Form EXISTS(SELECT 1 WHERE . ist die Ergebnismenge der Unteranfrage normalerweise uninteressant.. welche sich dann bei jeder einzelnen Auswertung der Unteranfrage als Konstanten verhalten.Kapitel 9 Funktion sum(ausdruck) Argumenttyp smallint. ist das Ergebnis von EXISTS “wahr”. 9. um NULL-Werte. Die Unteranfrage wird im Allgemeinen nur so weit ausgeführt. bigint. bigint.

wenn alle ihre einander entsprechenden Elemente nicht NULL und gleich sind.2 IN (skalare Form) ausdruck IN (wert[. Das Ergebnis ist “falsch”. wenn irgendeine übereinstimmende Zeile gefunden wird. Dies ist eine Abkürzung für ausdruck = wert1 OR ausdruck = wert2 OR . welche genau so viele Zeilen ergeben muss. dass die Unteranfrage keine Zeilen liefert). sondern der NULL-Wert ist. ihn in der Nähe des IN-Ausdrucks für Unteranfragen zu dokumentieren.3 IN (Unteranfrageform) ausdruck IN (unteranfrage) Die rechte Seite dieser Form von IN ist eine Unteranfrage in Klammern. Das Ergebnis von IN ist “wahr”. wenn irgendeine übereinstimmende Zeile gefunden wird. 9.]) IN (unteranfrage) Die rechte Seite dieser Form von IN ist eine Unteranfrage in Klammern. aber es scheint besser. Beachten Sie.. Beachten Sie. . wie es Ausdrücke in der Liste auf der linken Seite gibt..]) Die rechte Seite dieser Form von IN ist eine Liste skalarer Ausdrücke in Klammern.. Der Ausdruck auf der linken Seite wird ausgewertet und mit jeder Zeile des Anfrageergebnisses verglichen. wenn keine übereinstimmende Zeile gefunden wird (einschließlich des Sonderfalls.15. dass. wenn der linke Ausdruck den NULL-Wert ergibt oder wenn es keinen gleichen Ausdruck auf der rechten Seite gibt und mindestens eine Zeile rechts den NULL-Wert ergibt. dass. Das Ergebnis von IN ist “wahr”. Wie bei EXISTS sollte man nicht davon ausgehen. ansonsten ist das Ergebnis des Zeilenvergleichs 177 . wenn der linke Ausdruck den NULL-Wert ergibt oder wenn es keinen gleichen Ausdruck auf der rechten Seite gibt und mindestens ein rechter Ausdruck den NULL-Wert ergibt. wenn keine übereinstimmende Zeile gefunden wird (einschließlich des Sonderfalls.. (ausdruck [.. ausdruck . Das entspricht den normalen Regeln zur Kombinierung logischer Werte in SQL. Das Ergebnis ist “falsch”.Funktionen und Operatoren 9. wenn irgendwelche einander entsprechenden Elemente nicht NULL und ungleich sind. Das Ergebnis ist “wahr”. dass die Unteranfrage keine Zeilen liefert). Zwei Zeilen gelten als gleich. Das entspricht den normalen Regeln zur Kombinierung logischer Werte in SQL. die genau eine Spalte ergeben muss.. werden NULL-Werte in den Ausdrücken und Anfragezeilen gemäß den normalen SQLRegeln für logische Ausdrücke kombiniert. dass die Unteranfrage komplett ausgewertet werden wird.15. wenn das Ergebnis des Ausdrucks auf der linken Seite gleich irgendeinem Ausdruck auf der rechten Seite ist. dass dann das Ergebnis von IN nicht “falsch”. sondern der NULL-Wert ist. Die Ausdrücke links werden ausgewertet und zeilenweise mit jeder Zeile des Anfrageergebnisses verglichen. Anmerkung Diese Form von IN ist eigentlich kein Ausdruck mit Unteranfrage. Wie gewohnt. dass dann das Ergebnis von IN nicht “falsch”. die Zeilen sind ungleich.

wie man naiverweise meinen könnte. Das Ergebnis von NOT IN ist “wahr”. 9. Die Ausdrücke links werden ausgewertet und zeilenweise mit jeder Zeile des Anfrageergebnisses verglichen. dass 178 . dass dann das Ergebnis der NOT IN-Konstruktion der NULL-Wert ist. Das entspricht den normalen Regeln zur Kombinierung logischer Werte in SQL.Kapitel 9 unbekannt (NULL). dass dann das Ergebnis von NOT IN nicht “wahr”. wenn irgendeine übereinstimmende Zeile gefunden wird. positiv aus. dass die Unteranfrage keine Zeilen liefert). wie es Ausdrücke in der Liste auf der linken Seite gibt. Der Ausdruck auf der linken Seite wird ausgewertet und mit jeder Zeile des Anfrageergebnisses verglichen.15. Wie bei EXISTS. (ausdruck [. Das Ergebnis ist “wahr”...4 NOT IN (skalare Form) ausdruck NOT IN (wert[. dann ist das Ergebnis von IN der NULL-Wert. Das Ergebnis ist “falsch”. dass. sollte man nicht davon ausgehen..]) NOT IN (unteranfrage) Die rechte Seite dieser Form von NOT IN ist eine Unteranfrage in Klammern.. wenn das Ergebnis des Ausdrucks auf der linken Seite ungleich aller Ausdrücke auf der rechten Seite ist. welche genau so viele Zeilen ergeben muss. NULL-Werte werden den Anfänger aber bei NOT IN viel wahrscheinlicher verwirren als bei IN. . Wenn die Ergebnisse bei allen Zeilen ungleich oder unbekannt sind.. wenn der linke Ausdruck den NULL-Wert ergibt oder wenn es keinen gleichen Ausdruck auf der rechten Seite gibt und mindestens ein rechter Ausdruck den NULL-Wert ergibt. dass. Dies ist eine Abkürzung für ausdruck <> wert1 AND ausdruck <> wert2 AND ..15.]) Die rechte Seite dieser Form von NOT IN ist eine Liste von skalaren Ausdrücken in Klammern. mit mindestens einem unbekannt.5 NOT IN (Unteranfrageform) ausdruck NOT IN (unteranfrage) Die rechte Seite dieser Form von NOT IN ist eine Unteranfrage in Klammern. wenn nur nicht übereinstimmende Zeilen gefunden werden (einschließlich des Sonderfalls. die genau eine Spalte ergeben muss. dass die Unteranfrage komplett ausgewertet werden wird. wenn möglich. Das Ergebnis von NOT IN ist “wahr”. sondern der NULL-Wert ist. Beachten Sie. und nicht “wahr”. Tipp x NOT IN y ist immer äquivalent mit NOT (x IN y). ausdruck . 9. wenn nur nicht übereinstimmende Zeilen gefunden werden (einschließlich des Sonderfalls. wenn der linke Ausdruck den NULL-Wert ergibt oder wenn es keinen gleichen Ausdruck auf der rechten Seite gibt und mindestens eine Zeile rechts den NULL-Wert ergibt. Das entspricht den normalen Regeln zur Kombinierung logischer Werte in SQL. Beachten Sie. Drücken Sie Bedingungen daher am besten.

Die Ausdrücke links werden ausgewertet. Das Ergebnis von ANY ist “wahr”. Wie bei EXISTS.Funktionen und Operatoren die Unteranfrage keine Zeilen liefert).. Wie gewohnt. Das Ergebnis von ANY ist “wahr”. SOME ist ein Synonym für ANY. Zwei Zeilen gelten als gleich. dass die Unteranfrage komplett ausgewertet werden wird. 9. ausdruck . dass die Unteranfrage keine Zeilen liefert). 9. wenn kein wahres Ergebnis gefunden wird (einschließlich des Sonderfalls. Beachten Sie.. sollte man nicht davon ausgehen. wenn irgendeine gleiche bzw. Wenn die Ergebnisse bei allen Zeilen ungleich oder unbekannt sind. die genau eine Spalte ergeben muss. wenn irgendein wahres Ergebnis zurückgegeben wird.15.. wenn irgendwelche einander entsprechenden Elemente nicht NULL und ungleich sind. mit mindestens einem unbekannt.15. welche genau so viele Zeilen ergeben muss wie es Ausdrücke in der Liste auf der linken Seite gibt..6 ANY/SOME ausdruck operator ANY (unteranfrage) ausdruck operator SOME (unteranfrage) Die rechte Seite dieser Form von ANY ist eine Unteranfrage in Klammern. Das entspricht den normalen Regeln zur Kombinierung logischer Werte in SQL. wenn irgendwelche einander entsprechenden Elemente nicht NULL und ungleich sind. die Zeilen sind ungleich. und zeilenweise mit jeder Zeile des Anfrageergebnisses unter Verwendung von operator verglichen. dass die Unteranfrage keine Zeilen liefert). Zwei Zeilen gelten als gleich. es wird wahr oder der NULL-Wert sein. wenn keine solche Zeile gefunden wird (einschließlich des Sonderfalls. wenn alle ihre einander entsprechenden Elemente nicht NULL und gleich sind. ungleiche Zeile gefunden wird.]) operator ANY (unteranfrage) (ausdruck [. wenn irgendeine übereinstimmende Zeile gefunden wird. dass. Wie gewohnt. werden NULL-Werte in den Ausdrücken und Anfragezeilen gemäß den normalen SQLRegeln für logische Ausdrücke kombiniert. Gegenwärtig sind nur die Operatoren = und <> in zeilenweisen ANY-Konstruktionen erlaubt. (ausdruck [.]) operator SOME (unteranfrage) Die rechte Seite dieser Form von ANY ist eine Unteranfrage in Klammern. ausdruck . dann ist das Ergebnis von NOT IN der NULL-Wert. IN ist äquivalent mit = ANY. Der Ausdruck auf der linken Seite wird ausgewertet und mit jeder Zeile des Anfrageergebnisses unter Verwendung von operator. wenn alle ihre einander entsprechenden Elemente nicht NULL und gleich sind. verglichen. sondern der NULL-Wert ist. ansonsten ist das Ergebnis des Zeilenvergleichs unbekannt (NULL). Wenn das Ergebnis bei mindestens einer Zeile unbekannt ist. dass dann das Ergebnis der ANY-Konstruktion nicht falsch. werden NULL-Werte in den Ausdrücken und Anfragezeilen gemäß den normalen SQLRegeln für logische Ausdrücke kombiniert. ansonsten ist das Ergebnis des Zeilenvergleichs unbekannt (NULL). die Zeilen sind ungleich. Das Ergebnis ist “falsch”. welcher ein Ergebnis des Typs boolean haben muss. Das Ergebnis ist “falsch”.7 ALL ausdruck operator ALL (unteranfrage) 179 . dann kann das Ergebnis von ANY nicht falsch sein. wenn keine wahren Ergebnisse gefunden werden und mindestens eine Zeile auf der rechten Seite für den Operator den NULL-Wert ergibt. Das Ergebnis ist “falsch”.

die ungleich bzw. welche genau so viele Zeilen ergeben muss. werden NULL-Werte in den Ausdrücken und Anfragezeilen gemäß den normalen SQLRegeln für logische Ausdrücke kombiniert. ausdruck . ausdruck . Wie gewohnt.) Die Ausdrücke links werden ausgewertet und zeilenweise mit der einzigen Ergebniszeile der Unteranfrage bzw. wie es Ausdrücke in der Liste auf der linken Seite gibt. verglichen. wie es Ausdrücke in der Liste auf der linken Seite gibt. Das Ergebnis von ALL ist “wahr”. welcher ein Ergebnis des Typs boolean haben muss. NOT IN ist äquivalent mit <> ALL.]) operator (unteranfrage) (ausdruck [. Wenn das Ergebnis bei mindestens einer Zeile unbekannt ist. dass dann das Ergebnis der ALL-Konstruktion nicht wahr. welche genau so viele Zeilen ergeben muss. Das Ergebnis von ALL ist “wahr”. dass die Unteranfrage keine Zeilen liefert). den Ausdrücken auf der rechten Seite verglichen. dass.8 Zeilenweiser Vergleich (ausdruck [.]) Die linke Seite ist eine Liste von skalaren Ausdrücken. Gegenwärtig sind nur die Operatoren = und <> in zeilenweisen Vergleichen erlaubt. wenn irgendwelche einander entsprechenden Elemente nicht NULL und ungleich sind.. Zwei Zeilen gelten als gleich. die Zeilen sind ungleich. Wie bei EXISTS sollte man nicht davon ausgehen. die genau eine Spalte ergeben muss.]) operator (ausdruck [. wenn mindestens eine Zeile. Das Ergebnis ist “wahr”.. Gegenwärtig sind nur die Operatoren = und <> in zeilenweisen ALL-Konstruktionen erlaubt. Zwei Zeilen gelten als gleich. werden NULL-Werte in den Ausdrücken und Anfragezeilen gemäß den normalen SQLRegeln für logische Ausdrücke kombiniert. Außerdem darf die Anfrage nicht mehr als eine Zeile ergeben. gleich ist. gefunden wird. dass die Unteranfrage komplett ausgewertet werden wird.Kapitel 9 Die rechte Seite dieser Form von ALL ist eine Unteranfrage in Klammern. wenn für alle Zeilen ein wahres Ergebnis zurückgegeben wird (einschließlich des Sonderfalls.15. sondern der NULL-Wert ist. Das entspricht den normalen Regeln zur Kombinierung logischer Werte in SQL. ansonsten ist das Ergebnis des Zeilenvergleichs unbekannt (NULL). es wird dann falsch oder der NULL-Wert sein...]) operator ALL (unteranfrage) Die rechte Seite dieser Form von ALL ist eine Unteranfrage in Klammern. Die Ausdrücke links werden ausgewertet und zeilenweise mit jeder Zeile des Anfrageergebnisses unter Verwendung von operator verglichen. Beachten Sie. wenn irgendwelche einander entsprechenden Elemente nicht NULL und ungleich sind. wenn die beiden Zeilen gleich bzw. Die rechte Seite kann entweder eine gleich lange Liste von skalaren Ausdrücken sein oder eine Unteranfrage in Klammern. (ausdruck [. dann wird das Ergebnis als NULL-Wert interpretiert. Das Ergebnis ist “falsch”. ungleich sind (einschließlich des Sonderfalls. wenn alle ihre einander entsprechenden Elemente nicht NULL und gleich sind. dann kann das Ergebnis von ALL nicht wahr sein. ansonsten ist das Ergebnis des Zeilenvergleichs unbekannt (NULL). die Zeilen sind ungleich.. wenn irgendein falsches Ergebnis gefunden wird.. wenn alle ihre einander entsprechenden Elemente nicht NULL und gleich sind. Das Ergebnis ist “falsch”. dass die Unteranfrage keine Zeilen liefert). ausdruck ... 180 . ausdruck . wenn es keine falschen Ergebnisse gibt. 9. wenn alle Zeilen gleich bzw. Der Ausdruck auf der linken Seite wird ausgewertet und mit jeder Zeile des Anfrageergebnisses unter Verwendung von operator. Wie gewohnt. aber mindestens eine Zeile auf der rechten Seite für den Operator den NULL-Wert ergibt. (Wenn sie keine Zeilen ergibt. ungleich sind.

0)' AS "wert". die allgemeingültig sind und nicht aus einer bestimmten Situation heraus aufgestellt wurden. Namen und Schlüsselwörter.1 Überblick SQL ist eine Sprache mit einem starken Typensystem. Die Definition der SQL-Sprache erlaubt. dass allgemeiner und flexibler als in anderen SQL-Implementierungen ist. damit Ausdrücke mit gemischten Datentypen auch mit benutzerdefinierten Typen funktionieren können. Zeichenketten. dass unterschiedliche Datentypen in einem Ausdruck auftreten. Kapitel 9. point '(0. bezeichnung | wert -------------+------Ursprung | (0. Dieses Kapitel gibt eine Einführung in die Typumwandlungsmechanismen und -konventionen in PostgreSQL. dass man bei der Zeichenkette den Typ angeben kann. Die meisten Erweiterungstypen werden am Anfang als Zeichenkette kategorisiert. der das Verhalten und die erlaubte Verwendung bestimmt. und damit kann man in PostgreSQL erreichen. Die impliziten Umwandlungen. dass der Parser gleich den korrekten Typ erfährt. 10. jedes Stück Daten hat einen zugehörigen Datentyp. Daher sollten die meisten Typumwandlungen in PostgreSQL von Regeln bestimmt werden. vorkommen.10vdyfagds 10 Typumwandlung In SQL-Befehlen kann es. PostgreSQL hat ein erweiterbares Typensystem. Das heißt. Fließkommazahlen. können allerdings die Ergebnisse einer Anfrage beeinflussen. Der Parser in PostgreSQL kategorisiert lexikalische Elemente in eine von nur fünf allgemeinen Gruppen: ganze Zahlen. Mehr Informationen über bestimmte Datentypen und die verfügbaren Funktionen und Operatoren finden Sie in Kapitel 8 bzw. PostgreSQL hat diverse Mechanismen. Zum Beispiel hat die Anfrage SELECT text 'Ursprung' AS "bezeichnung".0) (1 row) 181 . kann der Benutzer oder Programmierer diese Ergebnisse mit expliziten Umwandlungen kontrollieren. Wenn es notwendig ist. absichtlich oder nicht. die von PostgreSQL vorgenommen werden. um Ausdrücke mit gemischten Typen auszuwerten. In vielen Fällen müssen Endanwender die Einzelheiten der Typumwandlungsmechanismen nicht kennen.

wie unten beschrieben. Dafür wurden mehrere allgemeine Typenkategorien festgelegt: boolean. das System wählt die richtige Funktion auf Grundlage der Datentypen der angegebenen Funktionsargumente. UNION. mit den Typen text und point. Es gibt grundsätzlich vier SQL-Konstruktionen. welche Umwandlungen (englisch cast) zwischen Datentypen gültig sind und wie diese Umwandlungen durchzuführen sind. Funktionsaufrufe können ein oder mehrere Argumente haben. sowie binären (zwei Operanden) Operatoren. Wertspeicherung Die SQL-Befehle INSERT und UPDATE speichern die Ergebnisse von Ausdrücken in einer Tabelle. In Ausdrücken mit gemischten Typen sollten eingebaute Typen immer in benutzerdefinierte Typen umgewandelt werden (natürlich nur wenn eine Umwandlung nötig ist). Da PostgreSQLPostgreSQL das Überladen von Funktionen erlaubt. numeric.) Außerdem gibt es einige eingebaute Regeln im Parser. Das heißt. damit der gesamte CASE-Ausdruck einen vorhersehbaren Ergebnistyp haben kann. welcher bevorzugt ausgewählt wird. sollten “höher” in der Typenhierarchie stehen. ❏ Benutzerdefinierte Typen stehen in keinem Verhältnis zueinander. müssen die Ergebnistypen eines jeden SELECT angepasst und in einen jeweils einheitlichen Endergebnistyp umgewandelt werden. timespan. geometric. aber bei mehreren möglichen benutzerdefinierten Typen gibt es eine Fehlermeldung. Gegenwärtig verfügt PostgreSQL über keine Informationen über Verhältnisse zwischen Typen. Die Ausdrücke in dem Befehl müssen an die Datentypen der Zielspalten angepasst oder womöglich in diese umgewandelt werden. network und benutzerdefiniert. dann sollte es möglich sein. der in späteren Phasen. (Das wird normalerweise in Verbindung mit der Erzeugung eines neuen Datentyps gemacht. string. hat einen bevorzugten Typ. dann wird erstmal der Platzhaltertyp unknown zugewiesen. aufgelöst wird. wenn eine Anfrage keine implizite Typumwandlung benötigt. wo im PostgreSQL-Parser unterschiedliche Regeln zur Umwandlung von Typen vonnöten sind: Operatoren PostgreSQL erlaubt Ausdrücke mit Präfix. die sich aus vorhandenen Funktionen ergeben. mit Ausnahme der benutzerdefinierten Typen. Auf ähnliche Art müssen die Teilausdrücke eines CASE-Ausdrucks in einen einheitlichen Typ umgewandelt werden. Funktionsaufrufe Ein Großteil des PostgreSQL-Typensystems ist um eine große Zahl Funktionen aufgebaut. die Anfrage zu verarbeiten. von denen der Parser von vornherein keine Kenntnis hat. In der Kategorie der benutzerdefinierten Typen ist jeder Typ sein eigener bevorzugter Typ. wenn die Anfrage gut formuliert wurde und die Typen alle passen. bitstring. Die Systemkatalogtabellen speichern Informationen darüber.und CASE-Konstruktionen Da alle Anfrageergebnisse eines SELECT-Befehls mit Mengenoperationen in den selben Ergebnisspalten erscheinen müssen. Wenn kein Typ für eine Zeichenkettenkonstante angegeben wurde. Zusätzliche Umwandlungen können vom Benutzer mit dem Befehl CREATE CAST bestimmt werden. Jede Kategorie. um das erwartete Verhalten von Typen aus dem SQL-Standard zu ermöglichen. Die Umwandlungsmöglichkeiten zwischen den eingebauten Typen wurden sehr sorgfältig ausgewählt und sollten nicht verändert werden. außer den Regeln für eingebaute Typen und den Beziehungen. ohne zusätzliche Zeit im Parser aufzubringen oder unnötige implizite Umwandlungsfunktionen anzuwenden. 182 . wenn es Unklarheiten gibt. datetime.Kapitel 10 zwei Konstanten. ❏ Benutzerdefinierte Typen. ❏ Parser oder Executor sollten keine zusätzliche Arbeit haben. Zweideutige Ausdrücke (mit mehreren möglichen Parse-Ergebnissen) können daher bei mehreren möglichen eingebauten Typen oft aufgelöst werden. kann die aufzurufende Funktion nicht allein durch den Funktionsnamen identifiziert werden.und Postfix-Operatoren (unär/ein Operand). Alle Regeln zur Typumwandlung wurden aufgrund mehrerer Prinzipien entworfen: ❏ Implizite Umwandlungen sollten niemals überraschende oder unvorhersehbare Ergebnisse haben.

auf den Typumwandlungen erforderlich sein werden. Prüfe alle Kandidaten und behalte die mit den meisten exakten oder binärkompatiblen Übereinstimmungen bei den Operandentypen. Wenn der Suchpfad mehrere Operatoren mitidentischen Operandentypen findet.) Ansonsten. Aber Operatoren mit verschiedenen Operandentypen werden unabhängig von ihrer Suchpfadposition in Betracht gezogen. b. dann wähle diese Kategorie. eine Zeichenkette. ob es einen Operator mit den genauen Typen der Operanden gibt. dann verwende ihn. Wenn kein Kandidat bevorzugte Typen akzeptiert. Wenn ein unqualifizierter Operatorname verwendet wurde (der normale Fall). wenn eine Anfrage normalerweise für eine Funktion eine implizite Umwandlung nötig hat und der Benutzer dann eine neue Funktion mit den passenden Argumenttypen erzeugt. akzeptieren. die den richtigen Namen und die richtige Anzahl Operanden haben und im Suchpfad sichtbar sind (siehe Abschnitt 5. Siehe auch Abschnitt 4. a. verwende ihn. Typauflösung von Operanden 1. ansonsten gehe zum nächsten Schritt. die von den übrig gebliebenen Kandidaten auf diesen Positionen akzeptiert werden. ansonsten gehe zum nächsten Schritt. e. wo die Operandentypen nicht übereinstimmen und nicht entsprechend umgewandelt werden können (mit einer impliziten Umwandlung). Wenn nur ein Kandidat übrig bleibt. wenn ein Kandidat diese Kategorie akzeptiert. Wähle auf jeder Position die Kategorie string. wenn alle übrigen Kandidaten die gleiche Kategorie akzeptieren. weil die richtige Wahl 183 . Wenn nur ein Kandidat übrig bleibt. Wenn es keine Kandidaten mit exakten oder binärkompatiblen Übereinstimmungen gibt. Wenn irgendeiner der angegebenen Operanden vom Typ unknown ist. dann erzeuge einen Fehler. Wähle die zu betrachtenden Operatoren aus der Systemtabelle pg_operator aus. verwende ihn. der als erster im Pfad gefunden wurde. a.Typumwandlung Zusätzlich sollte gelten.7. Verwerfe Kandidaten. Wenn ein Operandentyp eines binären Operatoraufrufs vom Typ unknown ist. dass diese Prozedur indirekt vom Vorrang der betroffenen Operatoren beeinflusst wird. ansonsten gehe zum nächsten Schritt. Wenn es einen gibt (in der Menge der Operatoren. 3. d. dann wird nur der behalten. Wenn nur ein Kandidat übrig bleibt.h.6. aussieht. behalte alle. Beachten Sie. Wenn ein qualifizierter Operatorname verwendet wurde. dann werden nur Operatoren im angegebenen Schema in Betracht gezogen. prüfe die Typenkategorien. 10. dann sollte der Parser diese neue Funktion verwenden und nicht mehr die alte Funktion mit der nötigen impliziten Umwandlung. 2. verwende ihn. Prüfe alle Kandidaten und behalte die. c. verwende ihn.1. dann nimm für diese Prüfung an. Bei Werten vom Typ unknown wird hier angenommen. die bevorzugte Typen auf den meisten Positionen.3). dass sie in alles umgewandelt werden können. Wenn es keine exakten Übereinstimmungen gibt. ansonsten gehe zum nächsten Schritt. Andere Fälle mit dem Typ unknown finden in diesem Schritt nie eine Lösung. Wenn nur ein Kandidat übrig bleibt. Prüfe. kann es nur einen passenden geben). (Die Bevorzugung dieser Kategorie ist sinnvoll. die in Betracht gezogen werden. d. a. weil eine Konstante vom Typ unknown wie ein String. dass er den gleichen Typ wie der andere Operand hat. Prüfe alle Kandidaten und behalte die mit den meisten exakten Übereinstimmungen bei den Operandentypen. Wenn nicht. Suche nach der am besten passenden Lösung. behalte alle Kandidaten. behalte alle. dann werden die Operatoren ausgewählt.2 Operatoren Die Operandentypen eines Operatoraufrufs werden nach der unten beschriebenen Prozedur aufgelöst.

ob es einen Operator gibt. der den Typ text für beide Operanden akzeptiert.Kapitel 10 nicht ohne weitere Hinweise getroffen werden kann. Einige Beispiele folgen. Wenn außerdem irgendein Kandidat einen bevorzugten Typ auf einer gegebenen Operandenposition akzeptiert. verwende ihn. dass der zweite Operand als Typ text interpretiert werden soll. Der Parser weist anfänglich beiden Operanden in dieser Anfrage den Typ integer zu: SELECT 2 ^ 3 AS "exp". verwerfe Kandidaten. Beispiel 10. die nicht den bevorzugten Typ für diesen Operanden akzeptieren.2: Typauflösung beim Zeichenkettenverknüpfungsoperator Eine zeichenkettenähnliche Syntax wird sowohl für Zeichenkettentypen als auch für komplexe Erweiterungstypen verwendet.1: Typauflösung beim Potenzierungsoperator Es gibt nur einen Potenzierungsoperator im Systemkatalog. Zeichenketten ohne angegebenen Typ müssen mit möglichen Operatorkandidaten in Übereinstimmung gebracht werden. text und unknown -----------------abcdef (1 row) In diesem Fall prüft der Parser. Beispiel 10. Da das der Fall ist. die nicht die gewählte Typenkategorie akzeptieren. nimmt er an. Verwerfe jetzt die Kandidaten. und er hat Operanden vom Typ double precision. f. Wenn nur ein Kandidat übrig bleibt. unbekannt ----------abcdef (1 row) 184 . Ein Beispiel mit einem Operanden ohne ausdrücklichen Typ: SELECT text 'abc' || 'def' AS "text und unknown". exp ----8 (1 row) Also führt das System eine Typumwandlung an beiden Operanden durch und die Anfrage wird gleichbedeutend mit SELECT CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "exp". dann erzeuge einen Fehler. Wenn kein oder mehr als ein Kandidat übrig bleibt. Hier ist eine Verknüpfung ohne Typangaben: SELECT 'abc' || 'def' AS "unbekannt".

185 . fakultät --------------------2432902008176640000 (1 row) 10. Daher wird PostgreSQL diesen Eintrag verwenden. Wir können auch überprüfen. da in der Anfrage keine Typen angegeben sind. und der bevorzugte Typ dieser Kategorie. ERROR: Input '-4. Da die Kategorie string bevorzugt wird.5' AS "abs". die alle den Betrag von diversen numerischen Datentypen berechnen.3 Funktionen Die Argumenttypen eines Funktionsaufrufs werden nach der unten beschriebenen Prozedur aufgelöst. wird den Konstanten mit unbekanntem Typ zugewiesen. Einer dieser Einträge ist für den Typ float8.5e500' AS "abs". die Operanden der Kategorie string und der Kategorie bitstring akzeptieren.3: Typauflösung bei den Betrags. dass es Kandidaten gibt. Wenn wir also einen ähnlichen Fall mit ! versuchen. abs ----4.5e500' is out of range for float8 Andererseits gibt es den Postfixoperator ! (Fakultät) nur für Ganzzahltypen. erhalten wir: SELECT '20' ! AS "fakultät". wenn ein nicht-numerischer Wert vorliegt: SELECT @ '-4. welcher der bevorzugte Typ in der Kategorie numeric ist. welcher Typ zu verwenden ist.5 (1 row) Hier hat das System eine implizite Umwandlung von text in float8 vorgenommen. Beispiel 10. text. Wir können mit einer ausdrücklichen Typumwandlung aushelfen: SELECT CAST('20' AS int8) ! AS "fakultät". weil das System nicht entscheiden kann. Also sucht der Parser nach allen Kandidaten und stellt fest. ERROR: Unable to identify a postfix operator '!' for type '"unknown"' You may need to add parentheses or an explicit cast Das passiert. dass wirklich float8 und nicht ein anderer Typ verwendet wurde: SELECT @ '-4. bevor der Operator angewendet wird. nicht für float8.Typumwandlung In diesem Fall gibt es keine Anfangshinweise darüber. welchen der möglichen Operatoren es bevorzugen soll. wird sie ausgewählt.und Fakultätsoperatoren Der PostgreSQL-Operatorkatalog hat mehrere Einträge für den Präfixoperator @.

behalte alle. wo die Argumenttypen nicht übereinstimmen und nicht entsprechend umgewandelt werden können (mit einer impliziten Umwandlung). sein. verwerfe Kandidaten. d. (Fälle mit dem Typ unknown finden in diesem Schritt nie eine Lösung. f. Wenn nur ein Kandidat übrig bleibt. die nicht die gewählte Typenkategorie akzeptieren. Prüfe alle Kandidaten und behalte die. verwende ihn. Wenn außerdem irgendein Kandidat einen bevorzugten Typ auf einer gegebenen Argumentposition akzeptiert. die nicht den bevorzugten Typ für dieses Argument akzeptieren. Wähle die zu betrachtenden Funktionen aus der Systemtabelle pg_proc aus. die als erster im Pfad gefunden wurde.) Ansonsten. werden nur Funktionen im angegebenen Schema in Betracht gezogen. Verwerfe Kandidaten. verwende ihn. c. ansonsten gehe zum nächsten Schritt. wähle diese Kategorie. Wenn nur ein Kandidat übrig bleibt. Wenn kein Kandidat bevorzugte Typen akzeptiert. akzeptieren. (Die Bevorzugung dieser Kategorie ist sinnvoll. b. Wenn ein qualifizierter Funktionsname verwendet wurde. erzeuge einen Fehler. die bevorzugte Typen auf den meisten Positionen. auf denen Typumwandlungen erforderlich sein werden.) 3. Wenn nicht. verwende ihn. ob der Funktionsaufruf eine triviale Typumwandlung darstellt.7. Prüfe. Aber Funktionen mit verschiedenen Argumenttypen werden unabhängig von ihrer Suchpfadposition in Betracht gezogen.h. weil eine Konstante vom Typ unknown wie ein String. a. Wähle auf jeder Position die Kategorie string. Verwerfe jetzt die Kandidaten. Wenn diese Voraussetzungen erfüllt sind. Wenn nur ein Kandidat übrig bleibt. wird nur die behalten. dann wird das Funktionsargument ohne tatsächlichen Funktionsaufruf in den Zieltyp umgewandelt. Wenn nur ein Kandidat übrig bleibt. Wenn es keine exakten Übereinstimmungen gibt. Wenn kein oder mehr als ein Kandidat übrig bleibt. eine Zeichenkette. Wenn ein unqualifizierter Funktionsname verwendet wurde. Prüfe alle Kandidaten und behalte die mit den meisten exakten Übereinstimmungen bei den Argumenttypen. Wenn der Suchpfad mehrere Funktionen mit identischen Argumenttypen findet. wenn der Funktionsaufruf ein Argument hat und der Funktionsname der gleiche ist wie der (interne) Name eines Datentyps. d. e. Wenn es keine Kandidaten mit exakten oder binärkompatiblen Übereinstimmungen gibt. Suche nach der am besten passenden Lösung. dann prüfe. 2. ansonsten gehe zum nächsten Schritt. die von den übrig gebliebenen Kandidaten auf diesen Positionen akzeptiert werden. a. 4. Prüfe alle Kandidaten und behalte die mit den meisten exakten oder binärkompatiblen Übereinstimmungen bei den Argumenttypen. Wenn es eine gibt (in der Menge der Funktionen. ansonsten gehe zum nächsten Schritt. der mit dem ersten binärkompatibel ist. Das ist der Fall. Wenn nur ein Kandidat übrig bleibt. werden die Funktionen ausgewählt. behalte alle Kandidaten. die in Betracht gezogen werden. erzeuge einen Fehler. wenn ein Kandidat diese Kategorie akzeptiert. dass sie in alles umgewandelt werden können. Bei Werten vom Typ unknown wird hier angenommen. ansonsten gehe zum nächsten Schritt. verwende ihn.Kapitel 10 Typauflösung von Funktionsargumenten 1. weil die richtige Wahl nicht ohne weitere Hinweise getroffen werden kann. prüfe die Typenkategorien. Einige Beispiele folgen. Wenn keine exakte Übereinstimmung gefunden wurde. kann es nur eine passende geben). behalte alle. 186 . ob es eine Funktion mit den genauen Typen der Argumente gibt.3). Wenn irgendeiner der angegebenen Argumente vom Typ unknown ist. wenn alle übrigen Kandidaten die gleiche Kategorie akzeptieren. verwende ihn. dann verwende sie. Außerdem muss das Funktionsargument entweder eine Konstante vom Typ unknown oder ein Typ. aussieht. die den richtigen Namen und die richtige Anzahl Argumente haben und im Suchpfad sichtbar sind (siehe Abschnitt 5.

3). round -------4. 4). wählt das System die Kandidatenfunktion. Wenn substr mit einer Zeichenkettenkonstante unbekannten Typs aufgerufen wird. 4). wenn sie aus einer Tabelle stammt. 3). Beispiel 10. benötigt die folgende Anfrage keine Typumwandlung und könnte daher etwas effizienter sein: SELECT round(4. 4). SELECT substr('1234'.) In der folgenden Anfrage wird also das erste Argument vom Typ integer automatisch in den Typ numeric umgewandelt: SELECT round(4. wovon eine Argumente der Typen text und integer hat. 187 . was der Fall sein könnte. das zweite integer. wird der Parser versuchen. die ein Argument der bevorzugten Kategorie string (nämlich Typ text) akzeptiert. substr -------34 (1 row) Wenn die Zeichenkette als Typ varchar ausgewiesen ist.0000 (1 row) Die Anfrage wird vom Parser quasi in folgende Anfrage umgewandelt: SELECT round(CAST (4 AS numeric). Da numerische Konstanten mit Nachkommastellen den Typ numeric zugewiesen bekommen. (Das erste ist numeric.Typumwandlung Beispiel 10.5: Typauflösung bei der Funktion substr Es gibt mehrere Funktionen namens substr.4: Typauflösung bei der Rundungsfunktion Es gibt nur eine Funktion round mit zwei Argumenten.0. substr -------34 (1 row) Das wird vom Parser quasi in folgende Anfrage umgewandelt: SELECT substr(CAST (varchar '1234' AS text). sie in den Typ text umzuwandeln: SELECT substr(varchar '1234'. 3).

3. dies in den Typen text umzuwandeln: SELECT substr(1234. weil es einen impliziten Umwandlungsweg (Cast) von integer nach text gibt. Ein solche Funktion hat den gleichen Namen wie der Datentyp. Wenn der Ausdruck den Typ unknown hat.Kapitel 10 Anmerkung Dem Parser ist bekannt. wobei die deklarierte Länge der Spalte als zweiter Parameter übergeben wird. Beispiel 10. das heißt. die eigentlich den anderen Typ verlangt. dass der eine Typ einer Funktion übergeben werden kann. wenn es einen registrierten Umwandlungsweg (Cast) zwischen den Typen gibt. die als character(20) erzeugt wurde. dass der Wert an die richtige Größe angepasst wird: CREATE TABLE vv (v character(20)). ohne dass eine tatsächliche Umwandlung vorgenommen werden muss. versuche. Wenn die Funktion mit einem Argument vom Typ integer aufgerufen wird. dann wird der Inhalt der Zeichenkette der Eingaberoutine des Zieldatentyps übergeben. und hat den gleichen Ergebnistyp. wovon der erste der Zieldatentyp und der zweite vom Typ integer ist.4 Wertspeicherung Wenn ein Wert in eine Tabelle eingefügt wird. dann wird der Parser versuchen. 2. SELECT v. Typumwandlung bei der Wertspeicherung 1. Wenn der Zieltyp eine feste Länge hat (zum Beispiel char oder varchar mit Längenangabe). für den Zieltyp eine Funktion zur Größeneinstellung zu finden. v | length 188 . 10. wird bei den folgenden Befehlen automatisch darauf geachtet. dann wird sie angewendet. Ansonsten versuchen den Ausdruck in den Zieltyp umzuwandeln. substr -------34 (1 row) Das wird in Wirklichkeit so ausgeführt: SELECT substr(CAST (1234 AS text). length(v) FROM vv. hat zwei Argumente. INSERT INTO vv SELECT 'abc' || 'def'. dann wird er in den Typ der Zielspalte nach folgender Prozedur umgewandelt. dass text und varchar binärkompatibel sind. Prüfe. ob eine exakte Übereinstimmung zwischen Wert und Zielspalte vorliegt. Wenn eine gefunden wurde. Daher wird in diesem Fall keine wirkliche Typumwandlung eingefügt. Das ist erfolgreich.6: Typumwandlung bei der Speicherung beim Typ character Bei einer Zielspalte. Diese Transformation kann automatisch geschehen. 3). 3).

7: Typauflösung in einer UNION-Konstruktion mit fehlenden Typen SELECT text 'a' AS "text" UNION SELECT 'b'. Wenn alle Eingabewerte den Typ unknown haben. Typauflösung bei UNION.) Schließlich wird die Funktion zur Größenanpassung bpchar(bpchar. um eine einheitliche Ergebnismenge zu erzeugen. für blankpadded char). In INTERSECT. numeric 189 .und EXCEPT-Klauseln werden unterschiedliche Typen genauso wie bei UNION aufgelöst. Wenn die Eingabewerte. der ein bevorzugter Typ in seiner Kategorie ist oder in den alle Eingabetypen. außer unknown. Beispiel 10.8: Typauflösung in einer einfachen UNION-Konstruktion SELECT 1. Ein CASE-Ausdruck verwendet auch denselben Algorithmus. Diese typenspezifische Funktion führt dann entsprechende Längenprüfungen durch und füllt den Wert mit Leerzeichen auf. nicht alle in derselben Typenkategorie sind. Der Auflösungsalgorithmus wird für jede Spalte einer solchen Anfrage getrennt angewendet. Einige Beispiele folgen. (Da die Typen text und bpchar binärkompatibel sind. Danach wird das Ergebnis des Operators in den Typ bpchar umgewandelt (der interne Name des Typs character. 3.2 AS "numeric" UNION SELECT 1.und CASE-Konstruktionen 1. Wandle alle Eingabewerte in den gewählten Typ um. war. wodurch der Operator || als Verknüpfung von text-Werten aufgelöst werden konnte. die nicht vom Typ unknown sind. 4. 2. dass die beiden Zeichenkettenkonstanten als Typ text aufgelöst wurden.5 UNION. um mit der Zielspalte übereinzustimmen. Ansonsten ignoriere die Werte vom Typ unknown bei der Ermittlung des Ergebnistyps. dann erzeuge einen Fehler.Typumwandlung ----------------------+-------abcdef | 20 (1 row) Was hier wirklich passierte. Wähle den ersten der Eingabetypen. um aus den Teilausdrücken einen Ergebnistyp zu ermitteln. integer) im Systemkatalog gefunden und mit dem Ergebnis des Operators und der gespeicherten Spaltenlänge aufgerufen. Beispiel 10.und CASE-Konstruktionen In UNION-Konstruktionen müssen möglicherweise verschiedene Typen aneinander angepasst werden. 10. außer unknown. wähle den Typ text (der bevorzugte Typ der Kategorie string). wird zu dieser Umwandlung kein Funktionsaufruf benötigt. implizit umgewandelt werden können. text -----a b (2 rows) Hier wird die Konstante 'b' mit unbekanntem Typ als Typ text aufgelöst.

Kapitel 10 --------1 1. aber integer kann implizit in real gewandelt werden.2' AS REAL). Beispiel 10. integer kann implizit in numeric umgewandelt werden.9: Typauflösung in einer umgekehrten UNION-Konstruktion SELECT 1 AS "real" UNION SELECT CAST('2.2 (2 rows) Die Konstante 1. 190 . real -----1 2. also wird numeric verwendet.2 hat den Typ numeric und die Konstante 1 hat den Typ integer. Daher hat das Ergebnis den Typ real.2 (2 rows) Hier kann der Typ real nicht implizit in integer umgewandelt werden.

dass es einen Index für die Spalte id unterhalten soll. um eine relevante Stelle zu finden. welche Indexe von Vorteil sein würden. werden in einem alphabetischen Stichwortverzeichnis (auf Englisch: index) am Ende des Buchs zusammengestellt. Genauso wie es die Aufgabe des Buchautors ist. die Begriffe. erfordert. bestimmte Zeilen viel schneller zu finden und auszugeben. ist das ganz klar eine ineffiziente Methode. In den meisten Sachbüchern gibt es einen ähnlichen Ansatz: Begriffe. ist es die Aufgabe des Datenbankprogrammierers. welche die Leser oft nachschlagen wollen. Normalerweise müsste das System die gesamte Tabelle test1 Zeile für Zeile absuchen.1 Einführung Das klassische Beispiel. vorherzubestimmen. die viele Anfragen der Form SELECT inhalt FROM test1 WHERE id = konstante. Zum Beispiel muss es vielleicht nur ein paar Ebenen in einem Suchbaum überprüfen. und einer Anwendung. vorherzusehen. ist mit einer Tabelle wie dieser: CREATE TABLE test1 ( id integer. 11. die ein Leser am wahrscheinlichsten nachschlagen will. Aber Indexe erhöhen auch den Verwaltungsaufwand im Datenbanksystem und sollten daher nicht ohne Überlegung verwendet werden. Ein Index gestattet dem Datenbankserver. er muss nicht das gesamte Buch durchlesen. Wenn dem System mitgeteilt worden wäre. inhalt varchar ). als es ohne Index möglich wäre. um die passenden Zeilen zu finden. könnte es eine viel effizientere Methode verwenden. um die Notwendigkeit eines Index darzustellen. Wenn die Anfrage nur wenige Zeilen als Ergebnis liefert (möglicherweise nur eine oder gar keine). Ein Leser kann das Stichwortverzeichnis relativ schnell überfliegen und dann schnell die richtige Seite aufschlagen. die Leistung der Datenbank zu verbessern.11exe 11 Indexe Die Verwendung von Indexen ist eine häufig benutzte Möglichkeit. um alle passenden Einträge zu finden. 191 .

Dadurch wird der Aufwand bei Datenmanipulationsoperationen erhöht. Im Einzelnen heißt das. aber Sie sollten einen Namen wählen. && (Die Bedeutung dieser Operatoren finden Sie in Abschnitt 9.9. ist kein weiteres Eingreifen erforderlich: Das System wird den Index verwenden. sollten daher entfernt werden. Anmerkung In Tests hat es sich gezeigt. Indexe können jederzeit zu einer Tabelle hinzugefügt oder entfernt werden. die Teil einer Verbundbedingung ist. ob ein Index verwendet wird und wann und warum der Planer auch manchmal zu dem Entschluss kommt. und die Indexgröße und die Zeit zum Aufbauen des Index viel schlechter sind. kann also Anfragen mit Verbundoperationen erheblich beschleunigen. Indexe. verwenden Sie den Befehl DROP INDEX. Um einen Index zu entfernen. Indexe können auch in UPDATE. > R-Tree-Indexe sind besonders für räumliche Daten geeignet. Der Anfrageplaner in PostgreSQL wird einen R-Tree-Index in Betracht ziehen. 192 . an dem Sie später immer noch erkennen können. R-Tree. wenn eine indizierte Spalte in einem Ausdruck mit folgenden Operatoren vorkommt: << . muss er vom System mit der Tabelle in Übereinstimmung gehalten werden. 11. erstellt der Befehl CREATE INDEX einen B-Tree-Index. von einem Index nicht Gebrauch zu machen. Aber Sie müssen möglicherweise den Befehl ANALYZE regelmäßig ausführen. Der Name test1_id_index kann frei bestimmt werden. Jeder Indextyp ist wegen seines Algorithmus für bestimmte Arten von Anfragen am besten geeignet. &< .und DELETE-Befehlen mit Suchbedingungen von Nutzen sein. um den besprochenen Index für die Spalte id zu erzeugen: CREATE INDEX test1_id_index ON test1 (id). >> . dass er effizienter als eine sequenzielle Suche durch die Tabelle ist. Aus diesen Gründen wird die Verwendung eines Hash-Index nicht empfohlen. Ein Index für eine Spalte. Wenn der Index einmal erzeugt worden ist. >= .Kapitel 11 Der folgende Befehl wird verwendet. wenn eine indizierte Spalte in einem Vergleich unter Verwendung des Operators = vorkommt. Wenn nichts anderes angegeben wird. Außerdem können Indexe auch in Verbundanfragen verwendet werden. die nicht wichtig sind oder überhaupt nicht verwendet werden. &> . dass eine Anfrage oder ein Datenmanipulationsbefehl nur höchstens einen Index pro Tabelle verwenden kann. Wenn ein Index erzeugt wurde. wenn es denkt. um die Statistiken zu aktualisieren. ~= . Beachten Sie. die es dem Planer erlauben realitätsnahe Schätzungen abzugeben.) Der Anfrageplaner wird einen Hash-Index in Betracht ziehen. dass der Anfrageplaner in PostgreSQLPostgreSQL einen B-Tree-Index in Betracht ziehen wird. Um einen R-Tree-Index zu erzeugen. = . welcher für die am häufigsten vorkommenden Situationen geeignet ist.wie man herausfinden kann. Lesen Sie auch in Kapitel 13 . wofür der Index war. verwenden Sie einen Befehl der Form CREATE INDEX name ON tabelle USING RTREE (spalte). @ . Folgender Befehl erzeugt einen Hash-Index: CREATE INDEX name ON tabelle USING HASH (spalte). <= . HashIndexe zeigen auch einen schlechte Leistung bei vielen gleichzeitigen Zugriffen. wenn eine indizierte Spalte in einem Vergleich unter Verwendung folgender Operatoren vorkommt: < .2 Indextypen In PostgreSQLPostgreSQL gibt es mehrere Indextypen: B-Tree. dass Hash-Indexe in PostgreSQL ähnlich schnell oder langsamer als B-TreeIndexe sind. GiST und Hash.

name varchar ). Die R-Tree-Indexmethode ist eine Implementierung des normalen R-Trees mit dem quadratischen Split-Algorithmus von Guttman.und GiST-Implementierungen unterstützt. wenn die Anfrage die in der Indexdefinition ganz links aufgezählte Spalte und beliebig viele weitere Spalten. Wir erwähnen die Algorithmen hier nur. siehe die Datei pg_config.. (In einer Anfrage mit a und c könnte der Anfrageplaner entscheiden.) und Sie oft Anfragen der Form SELECT name FROM test2 WHERE major = konstante AND minor = konstante.in der Anfrage SELECT name FROM test2 WHERE major = konstante OR minor = konstante.h. b und c verwendet oder wenn sie a und b verwendet oder wenn sie nur a verwendet. Bis zu 32 Spalten können angegeben werden. Wenn Sie zum Beispiel eine Tabelle dieser Form haben: CREATE TABLE test2 ( major int. wenn eine Anfrage a. ausführen. 193 .) Mehrspaltige Indexe sollten sparsam verwendet werden. wenn die Ausdrücke.3 Mehrspaltige Indexe Ein Index kann auch für mehrere Spalten definiert werden. wenn Sie einen Index für die Spalten major und minor zusammen definieren. kann der oben definierte Index test2_mm_idx nicht für die Suche in beiden Spalten verwendet werden. Zum Beispiel: CREATE INDEX test2_mm_idx ON test2 (major. c) kann verwendet werden.) Ein mehrspaltiger Index kann nur verwendet werden. kann es angebracht sein. Sie speichern Ihr /dev Verzeichnis in einer Datenbank . Meistens reicht ein Index für eine einzelne Spalte aus und spart Platz und Zeit. die rechts von ihr ohne Lücke gelistet wurden. b.) Der Anfrageplaner kann einen mehrspaltigen Index verwenden. Indexe mit mehr als drei Spalten sind fast immer unangebracht. um nur in der Spalte major zu suchen. Zum Beispiel. dass alle Indexmethoden voll dynamisch sind und nicht regelmäßig optimiert werden müssen (wie es zum Beispiel bei statischen Hash-Methoden der Fall ist).. bevor man PostgreSQL compiliert. Die Hash-Indexmethode ist eine Implementierung des linearen Hashs von Litwin. Zum Beispiel: Ein Index für (a. die die indizierten Spalten enthalten. minor). minor int. 11. verwendet (mit passenden Operatoren).Indexe Die B-Tree-Indexmethode ist eine Implementierung der hochparallelen B-Trees von Lehman und Yao. (Er kann aber verwendet werden. (Nehmen wir an. (Diese Grenze kann verändert werden. Gegenwärtig werden mehrspaltige Indexe nur von den B-Tree. mit AND verbunden wurde. um zu zeigen. den Index nur für a zu verwenden und c wie eine normale nichtindizierte Spalte zu behandeln. aber nicht bei anderen Kombinationen.

.Kapitel 11 11. selbst wenn die Funktion mehr als eine Spalte verwendet. ist ALTER TABLE . Zum Beispiel verwendet man oft. dass in der Tabelle keine Zeilen mit gleichen indizierten Werten auftreten können. Ein solcher Index kann zu einer Tabelle auch später hinzugefügt werden.5 Funktionsindexe Ein Funktionsindex ist ein Index. Funktionsindexe können verwendet werden. die das gewünschte Ergebnis intern berechnet. wenn er für das Ergebnis des Ausdrucks lower(spalte1) erzeugt wurde: CREATE INDEX test1_lower_spalte1_idx ON test1 (lower(spalte1)). Tipp Die im letzten Absatz erwähnten Beschränkungen kann man leicht umgehen. um einen Unique Constraint zu erzeugen. dass Indexe verwendet werden. auf dass man nicht direkt zugreifen sollte. zu einer Tabelle einen Unique Constraint hinzuzufügen. um diesen Constraint umzusetzen. wird dafür gesorgt. um Unique Constraints umzusetzen. Diese Anfrage kann einen Index verwenden.4 Indexe für Unique Constraints Indexe können auch verwendet werden. CREATE UNIQUE INDEX name ON tabelle (spalte [. die auf eine oder mehrere Spalten einer Tabelle angewendet wird. 194 . . PostgreSQL erzeugt automatisch einen solchen UNIQUE-Index.. um sicherzustellen. definiert ist. die einen Unique Constraint oder einen Primärschlüssel hat.und Kleinschreibung durchzuführen. den Primärschlüssel ausmachen. die Funktion lower: SELECT * FROM test1 WHERE lower(spalte1) = 'wert'. könnte man als internes Implementierungsdetail betrachten. nicht aber Konstanten. Gegenwärtig können nur B-Tree-Indexe als UNIQUE deklariert werden. der über das Ergebnis einer Funktion. Anmerkung Die bevorzugte Methode. Die Tatsache. Die Funktion in der Indexdefinition kann mehrere Argumente haben.. bilden die Spalten für den Index (ein mehrspaltiger Index. die den Unique Constraint bzw. Die Spalten. Wenn ein Index als UNIQUE deklariert ist. Funktionsindexe sind immer einspaltig (nämlich das Ergebnis der Funktion). wenn nötig). indem man selbst eine Funktion erzeugt. wenn eine Tabelle erzeugt wird. um Vergleiche ohne Beachten der Groß. 11.. dass ein Spaltenwert oder eine Gruppe von Werten in mehreren Spalten in einer Tabelle nur einmal vorkommt. NULL-Werte zählen nicht als gleich. aber diese müssen Spalten der Tabelle sein. Mehrspaltige Indexe mit Funktionsaufrufen sind nicht möglich. um auf Grundlage der Ergebnisse von Funktionsaufrufen schnell auf Daten zugreifen zu können. ADD CONSTRAINT.]).

Die Operatorklasse bestimmt. welche Operatoren vom Index für diese Spalte verwendet werden sollen. Wenn der Bereich. die das Prädikat erfüllen. wenn man den Index definiert.]). ist. dass es für manche Datentypen mehrere sinnvolle Sortierreihenfolgen geben kann. der Teil wird durch einen Bedingungsausdruck (das so genannte Prädikat des partiellen Index) bestimmt. Der Unterschied zwischen beiden ist. Das könnte man erreichen. Sie kann auch erweitert werden um alle Operatoren in einer Klasse mit zu zeigen: SELECT am.. diese Operatorklasse enthält die Vergleichsfunktionen für Werte vom Typ int4. opclass_name. opclass_name. Ein B-Tree-Index für eine Spalte vom Typ int4 würde die Operatorklasse int4_ops verwenden.amopclaid = opc.6 Operatorklassen Eine Indexdefinition kann für jede Spalte eines Index eine Operatorklasse angeben.opcname AS opclass_name FROM pg_am am. dass häufig vorkommende Werte indiziert werden. der mehr als ein paar Prozent aller Tabellenzeilen ausmacht).Indexe 11.oid ORDER BY index_method. Die folgende Anfrage zeigt alle vorhandenen Operatorklassen: SELECT am. Normalerweise reicht die vorgegebene Operatorklasse für den Datentyp der Spalte aus. 11. zu verhindern. pg_amop amop. dass bigbox_ops die Koordinaten der Rechtecke herunterskaliert. warum es Operatorklassen gibt. indem man zwei Operatorklassen erzeugt und die passende wählt.oprname AS opclass_operator FROM pg_am am. Zum Beispiel könnte man komplexe Zahlen nach Betrag oder nach dem reellen Teil sortieren. pg_opclass opc WHERE opc.oid ORDER BY index_method. opclass_operator. CREATE INDEX name ON table (spalte opklasse [. opc. Der Index enthält nur Einträge für jene Tabellenzeilen.7 Partielle Indexe Ein partieller Index wird über einen Teil einer Tabelle erstellt. opr. Es gibt auch eingebaute Operatorklassen neben den Standardklassen: ❏ Die Operatorklassen box_ops und bigbox_ops unterstützen beide R-Tree-Indexe für den Datentyp box.amname AS index_method.opcamid = am.amname AS index_method. pg_opclass opc. in dem Ihre Rechtecke liegen.amopopr = opr.opcname AS opclass_name. Addition und Subtraktion von sehr großen Fließkommazahlen zu vermeiden. um Fließkommafehler bei der Multiplikation. sollten Sie bigbox_ops verwenden.oid AND amop. opc. den Index sowieso nicht verwenden wird. gibt es auch keinen 195 . Der Hauptgrund..oid AND amop.opcamid = am. die nach einem häufig vorkommenden Wert sucht (einer. Ein Hauptanliegen der partiellen Indexe ist es. pg_operator opr WHERE opc. Da eine Anfrage. größer als etwas 20000 Quadrateinheiten ist. .

um uninteressante Werte auszuschließen Nehmen wir an.32'. .78. wodurch Anfragen.168. Beispiel 11. Sie haben eine Tabelle mit Bestellungen.Kapitel 11 Grund. die für die meisten Anfragen nicht von Interesse sind. aber man verhindert dadurch.. die den Index tatsächlich benutzen. ). selbst wenn eine Indexsuche in diesem Fall vorteilhaft wäre. diese Zeilen überhaupt im Index zu speichern. dass die häufigen Werte vorher ermittelt werden.255').168.2 gezeigt. verwenden Sie folgenden Befehl: CREATE INDEX access_log_client_ip_ix ON access_log (client_ip) WHERE NOT (client_ip > inet '192. würde so aussehen: CREATE INDEX bestell_ohne_rechnung_index ON bestellungen (bestell_nr) WHERE rechnung is not true. Sie speichern die Zugriffsstatistiken eines Webservers in einer Datenbank. indem Sie einen Index nur für die Zeilen ohne Rechnung erstellen. Die meisten Zugriffe sind aus dem IP-Adressbereich Ihrer Organisation. Wenn Ihren Suchanfragen nach IP-Adresse hauptsächlich die externen Zugriffe betreffen.. aber einige sind von woandersher (sagen wir Angestellte. die den Index nicht verwenden kann. der dem Subnetz Ihrer Organisation entspricht. Beispiel 11. Dann können Sie die Leistung verbessern. wovon für einige schon die Rechnung gestellt wurde und für andere nicht. das wird in Beispiel 11. Der Befehl um den Index zu erstellen.1 zeigt eine mögliche Anwendung dieser Idee.100.168. Daraus ergeben sich die gleichen Vorteile wie oben.0' AND client_ip < inet '192. beschleunigt werden. Um einen partiellen Index zu erstellen. Beispiel 11. dass diese Art eines partiellen Index erfordert. aber die Zeilen mit den meisten Zugriffen. der zu unserem Beispiel passt. weil der Index nicht in jedem Fall mit aktualisiert werden muss.100. kann das einen hohen Wartungsaufwand mit sich ziehen.2: Einrichtung eines partiellen Index.1: Einrichtung eines partiellen Index. Nehmen wir folgende Tabelle an: CREATE TABLE access_log ( url varchar. Es sollte klar sein.html' AND client_ip = inet '212. 196 . ist: SELECT * FROM access_log WHERE client_ip = inet '192. wahrscheinlich gar nicht indizieren. dass man überhaupt mit einem Index auf die “uninteressanten” Werte zugreifen kann. Dadurch wir die Größe des Index verringert. Sie werden bemerken. Eine Anfrage.23'. Außerdem können dadurch viele Aktualisierungen der Tabelle beschleunigt werden. ist folgende: SELECT * FROM access_log WHERE url = '/index. müssen Sie den IP-Bereich. dass ein partieller Index in diesem Szenario eine Menge Sorgfalt und Experimentierfreude voraussetzt. die diesen Index verwenden kann. Eine typische Anfrage. um häufige Werte auszuschließen Nehmen wir an. Werte aus dem Index auszuschließen. dann ist das nicht schwer. aber wenn die häufigen Werte nur auf dem zufälligen Datenaufkommen beruhen.10. Wenn die Verteilung der Werte sich aus der Anwendung ergibt oder sich nach einer Zeit nicht mehr verändert. die sich von außerhalb einwählen).100. client_ip inet. die Bestellungen ohne Rechnung sind ein kleiner Teil der Tabelle. Nehmen wir weiter an. Eine weitere Möglichkeit besteht darin.

Beachten Sie. dass aus “x < 1” folgt. übereinstimmen muss.3: Einrichtung eines partiellen UNIQUE-Index Nehmen wir an. dass das Prädikat mit den Suchbedingungen der Anfragen. dass der Index überhaupt in Anfragen eingesetzt wird. Genau heißt das. soweit nur Spalten der zu indizierenden Tabelle verwendet werden. die das Indexprädikat erfüllen. zum Beispiel. wie in Beispiel 11. ansonsten wird nicht erkannt werden. könnte die Verwendung dieses partiellen Index. Wir möchten sicherstellen. Beispiel 11. die Testergebnisse speichert. Das ist nicht so effizient wie ein partieller Index für die Spalte betrag wäre. dass die indizierte Spalte und die Spalte im Indexprädikat nicht die gleiche sein müssen. in anderen Fällen muss das Indexprädikat genau mit der Bedingung in der WHERE-Klausel der Anfrage übereinstimmen. die bestell_nr gar nicht verwenden. wenn das System erkennen kann. Die Idee ist. einen UNIQUE-Index über einen Teil einer Tabelle zu erzeugen. testobjekt) WHERE erfolg. Dadurch wird die Eindeutigkeit der Zeilen. zum Beispiel: SELECT * FROM bestellungen WHERE rechnung is not true AND betrag > 5000. testobjekt text.2 zeigt auch. die diesen Index verwendet. 197 . dass das Indexprädikat logisch aus der WHERE-Bedingung der Anfrage folgt. Beispiel 11. dass “x < 2”.00. wäre SELECT * FROM bestellungen WHERE rechnung is not true AND bestell_nr < 10000. diese Anforderungen umzusetzen.Indexe Eine mögliche Anfrage. die mathematisch äquivalente Ausdrücke. ). sie wäre wahrscheinlich auch viel zu langsam für die Praxis. Das ist eine besonders effiziente Art. ein partieller Index kann nur verwendet werden. . PostgreSQL enthält keine sonderlich schlaue Beweismaschine. besonders wenn es wenige erfolgreiche und viele nicht erfolgreiche Tests gibt. dass diese Anfrage den Index nicht verwenden kann: SELECT * FROM bestellungen WHERE bestell_nr = 3501. aber es darf beliebig viele “erfolglose” Tests geben. Der Index kann allerdings auch in Anfragen verwendet werden. So könnte man das machen: CREATE TABLE tests ( thema text. ohne Auswirkungen auf andere Zeilen zu haben. (Eine solche Beweismaschine ist nicht nur sehr schwer herzustellen. Wenn es aber relativ wenige Bestellungen ohne Rechnung gibt. Die Bestellung 3501 könnte unter den Bestellungen mit oder ohne Rechnung sein. CREATE UNIQUE INDEX tests_erfolg_constraint ON tests (thema.. erreicht. erkennen kann. die auf unterschiedliche Arten geschrieben wurde. erfolg boolean. dass es nur einen “erfolgreichen” Test für jede Kombination von Thema und Testobjekt gibt. da das System den gesamten Index durchsuchen muss.) Das System kann einfache Implikationen aus Ungleichungen erkennen. die aus dem Index Nutzen ziehen sollen. dass der Index verwendet werden kann.3. Sie haben eine Tabelle.. Beachten Sie aber. um diese Bestellungen zu finden trotzdem von Vorteil sein. Eine dritte Möglichkeit zur Verwendung eines partiellen Index verlangt gar nicht danach. PostgreSQL unterstützt partielle Indexe mit beliebigen Prädikaten.

Seien Sie auch vorsichtig. ist es wichtig zu prüfen. wie viele Zeilen eine Anfrage als Ergebnis haben wird. wird das bei 1 aus 100 Zeilen kaum der Fall sein. weil die 100 Zeilen wahrscheinlich in eine einzige Speicherseite auf der Festplatte passen und es keinen Plan gibt. Merken Sie sich. wann ein Index verwendet wird und wann nicht (zum Beispiel wird ein Index nicht verwendet. In den meisten Fällen wird der Vorteil gegenüber einem normalen Index nicht viel sein. um vorherzubestimmen.1 beschrieben. sodass das Beispiel weiter oben wirklich nur an Indexgröße spart und nicht notwendig ist. Es gibt Konfigurationsparameter. Diese Informationen sind notwendig. was oft nicht zu vermeiden ist. Wenn man zum Beispiel sequentielle Suchen (enable_seqscan) und Nested-Loop-Verbunde (enable_nestloop). die in den Beispielen der vorangegangenen Abschnitte gezeigt wurden. abschaltet. PostgreSQL trifft eigentlich vernünftige Einscheidungen darüber. die sehr ähnlich oder komplett zufällig sind oder in vorsortierter Reihenfolge eingefügt werden. In den meisten Fällen wird man nicht um das Ausprobieren umhinkommen. die ganz bestimmt ungenau sind. Wenn das System trotzdem eine sequentielle Suche oder einen Nested-Loop-Verbund verwendet. In einem solchen Fall kann der Index so eingerichtet werden. um jedem möglichen Anfrageplan einen realistische Kostenfaktor zuzuordnen. wenn ein häufiger Wert ausgelesen wird. ohne ANALYZE ausgeführt zu haben. aber das war auch schon alles. allgemeingültige Regeln aufzustellen. werden Sie erfahren. welche die einfachsten Plantypen sind. wann ein Index von Nutzen sein kann. insbesondere dass Sie wissen. Es ist besonders fatal. einen anderen Plan zu verwenden. wie er zu diesem Zweck angewendet wird. ❏ Wenn Indexe nicht verwendet werden. Es kann vorkommen.4).8 Indexverwendung überprüfen Trotzdem Indexe in PostgreSQL nicht manuell gewartet oder eingestellt werden müssen. ❏ Führen Sie immer zuerst den Befehl ANALYZE aus. gibt es wahrscheinlich ein grundlegenderes Problem. muss das System versuchen. Der Erwerb dieses Wissens erfordert Erfahrung und ein Verständnis dafür. ist das ein hoffnungsloses Unterfangen. dass Sie mindestens so viel wissen wie der Anfrageplaner. zum Beispiel weil die Bedin- 198 . dass Datenmengen mit eigentümlicher Wertverteilung das System dazu bringen. ist in Abschnitt 13. ❏ Verwenden Sie echte Daten zum Ausprobieren. wenn es nicht von Vorteil ist. Ohne wirkliche Statistiken werden irgendwelche Vorgabewerte verwendet. und grotesk falsche Planerentscheidungen sind auch ein guter Grund für einen Fehlerbericht an die Entwickler. um die Wahl der Anfragepläne im System zu übergehen. einen Index einzusetzen. um die Verwendung des Index zu vermeiden). Olson 1993 und Seshardri & Swami 1995 (siehe Literaturverzeichnis). Wenn man also die Indexverwendung einer Anwendung untersucht. Weitere Informationen über partielle Indexe finden Sie in den Abhandlungen Stonebraker 1989. wenn die Anwendung noch nicht eingesetzt wird. welche Indexe Sie für die Testdaten brauchen. Die Verwendung der Indexe kann mit dem Befehl EXPLAIN betrachtet werden. warum der Index nicht verwendet wird.Kapitel 11 Schließlich kann man einen partiellen Index auch einsetzen. ihre Verwendung zu erzwingen. Wenn Sie Testdaten verwenden. Dieser Befehl erstellt Statistiken über die Verteilung der Werte in der Tabelle. Der Rest dieses Abschnitts gibt dazu ein paar Hinweise. können die Statistiken gegenüber praxisnahen Daten verfälschen. wann man einen Index einrichten sollte. was vom Planer benötigt wird. 11. Es ist sehr schwer. dass er für die betroffene Anfrage nicht verwendet werden kann. Werte. welche Indexe von den tatsächlich anfallenden Anfragen wirklich verwendet werden. kann es beim Testen von Nutzen sein. der besser ist als sequenziell 1 Seite von der Festplatte zu laden. Obwohl beispielsweise die Auswahl von 1000 Zeilen aus 100000 für einen Index geeignet sein könnte. wie Indexe in PostgreSQL funktionieren. Es gibt eine Reihe typischer Fälle. die bestimmen. dass die Einrichtung eines partiellen Index aussagt. proportional verkleinerte Datenmengen zu verwenden. wenn Sie Testdaten erfinden. mit denen die verschiedenen Plantypen ausgeschaltet werden können (beschrieben in Abschnitt 16.

Die Kosten der Planknoten können mit Konfigurationsparametern eingestellt werden (beschrieben in Abschnitt 16. dass die Kostenschätzungen realistisch werden. um die Angelegenheit zu untersuchen. Sie sollten also die Zeit Ihrer Anfrage mit und ohne Index messen. wurde in den vorangegangenen Abschnitten erklärt. Eine ungenaue Schätzung der Zeilenzahl kommt von unzureichenden Statistiken. gibt es wiederum zwei Möglichkeiten.Indexe gung in der Anfrage nicht auf den Index passt. gibt es zwei Möglichkeiten: Entweder hat das System Recht und die Verwendung des Index ist tatsächlich nicht angebracht oder die Kostenschätzungen der Anfragepläne entsprechen nicht der Wirklichkeit. ❏ Wenn es sich herausstellt. 199 . dann werden Sie womöglich als letzten Ausweg die Verwendung der Indexe ausdrücklich erzwingen müssen. Wenn es Ihnen nicht gelingt. Die Gesamtkosten werden aus den Kosten pro Zeile jedes Planknotens multipliziert mit der Schätzung. dass die Kostenschätzungen falsch sind.4). die Parameter so einzustellen. Möglicherweise kann man da Abhilfe schaffen.) ❏ Wenn Sie die Verwendung des Index erzwungen haben und dadurch ein Index tatsächlich verwendet wird. Der Befehl EXPLAIN ANALYZE kann hier nützlich sein. wie viele Zeilen der Planknoten ergeben wird (englisch selectivity estimate). indem man die Parameter zur Statistikeinholung ändert (siehe Referenz von ALTER TABLE). Vielleicht sollten Sie sich auch mit den PostgreSQL-Entwicklern in Verbindung setzen. (Welche Anfragen welche Arten von Index verwenden können.

.

dass während einer Anfrage jede Transaktion einen Schnappschuss der Daten (eine Datenbankversion). die von anderen Transaktionen durch Änderung an denselben Datenzeilen erzeugt werden könnten. und daher blockiert das Lesen niemals das Schreiben und das Schreiben niemals das Lesen. wie sie vor einiger Zeit waren. welche Sperren verwenden.12Konsistenzkontrolle im Mehrbenutzerbetrie 12 Konsistenzkontrolle im Mehrbenutzerbetrieb Dieses Kapitel beschreibt das Verhalten des PostgreSQL-Datenbanksystems. aber noch nicht abgeschlossenen Transaktion geschrieben wurden. jeder Sitzung effizienten Zugriff zu ermöglichen. die von einer gleichzeitigen. sieht. Durch die richtige Verwendung von MVCC kann normalerweise aber eine bessere Leistung erzielt werden. zur selben Zeit auf die selben Daten zuzugreifen. MVCC). inkonsistente Daten zu lesen. Das Ziel in dieser Situation ist. dass in MVCC die Sperren zum Lesen von Daten nicht mit Sperren zum Schreiben von Daten in Konflikt stehen. aber die Integrität der Daten strikt zu gewährleisten. die nicht leicht an das MVCC-Verhalten angepasst werden können. ungeachtet des aktuellen Zustands der zugrunde liegenden Daten. wenn zwei oder mehr Sitzungen versuchen. Jeder Entwickler von Datenbankanwendungen sollte mit den Themen dieses Kapitels vertraut sein. 12. die zwischen gleichzeitigen Transaktionen verhindert werden müssen. Das schützt eine Transaktion davor. Die unerwünschten Phänomene sind: Dirty Read (Lesen ungültiger Daten) Eine Transaktion liest Daten. um Konsistenz im Mehrbenutzerbetrieb zu gewährleisten. verwendet PostgreSQL ein Multiversionsmodell (Multiversion Concurrency Control. Dadurch erhält jede Datenbanksitzung Transaktionsisolation.2 Transaktionsisolation Der SQL definiert Transaktionsisolation in vier Graden durch drei Phänomene. Das bedeutet. für Anwendungen.1 Einführung Im Gegensatz zu herkömmlichen Datenbanksystemen. 201 . Sperren für Tabellen und Zeilen sind in PostgreSQLPostgreSQL auch vorhanden. 12. Der Hauptunterschied zwischen dem Multiversionsmodell und einem Sperrenmodell ist.

ehe sie gefunden wurde. dass die Daten von einer anderen Transaktion (die seit dem ersten Lesen abgeschlossen wurde) verändert worden sind.1 beschrieben. wenn es um das Suchen von Zielzeilen geht: Sie finden nur Zeilen. Phantom Read (Lesen von Phantomdaten) Eine Transaktion führt eine Anfrage mit Suchbedingung. war. dass ein aktualisierender Befehl einen inkonsistenten Schnappschuss sieht: Er sieht die Auswirkungen von gleichzeitig ablaufenden Transaktionen. die während der Ausführung der Anfrage abgeschlossen wurden. welche eine Gruppe von Zeilen ergibt. als die Ausführung des Befehls begann.Kapitel 12 Nonrepeatable Read (nichtwiederholbares Lesen) Eine Transaktion liest Daten. Die vier Transaktionsisolationsgrade und die sich daraus ergebenden Verhalten werden in Tabelle 12. DELETE und SELECT FOR UPDATE verhalten sich genauso wie SELECT. die die Suchbedingung erfüllen. obwohl die eigene Transaktion ja noch nicht abgeschlossen wurde. 12.1 Der Isolationsgrad Read Committed Read Committed ist der Standard-Isolationsgrad in PostgreSQL.) Im Endeffekt sieht die SELECT-Anfrage einen Schnappschuss der Datenbank. die schon abgeschlossen waren. die von Transaktionen stammen. Isolationsgrad Read Uncommitted Read Committed Repeatable Read Serializable Dirty Read möglich nicht möglich nicht möglich nicht möglich Nonrepeatable Read möglich möglich nicht möglich nicht möglich Phantom Read möglich möglich möglich nicht möglich Tabelle 12. Wenn die erste Transaktion erfolgreich abgeschlossen wird. bevor die Anfrage begann. In diesem Fall wartet die zweite aktualisierende Transaktion. Wenn ja. Wenn eine Transaktion in diesem Isolationsgrad läuft. dann sieht eine SELECT-Anfrage nur Daten aus Transaktionen. welche abgeschlossen wurden (commit).2. Es kann aber sein. ansonsten wird die zweite versuchen. Die Suchbedingung der Anfrage (die WHERE-Klausel) wird erneut ausgewertet. ob sie von der aktualisierten Version der Zeile immer noch erfüllt wird. schon von einer gleichzeitig laufenden Transaktion aktualisiert (oder gelöscht oder zur Aktualisierung markiert) worden ist. wiederholt aus und stellt fest. ob die erste Transaktion erfolgreich abgeschlossen (commit) oder zurückgerollt (rollback) wird (wenn sie überhaupt noch unabgeschlossen ist). wegen einer anderen Transaktion. wie sie in dem Moment. dass sich die Gruppe der Zeilen. dann fährt die zweite Transaktion mit ihrer Operation fort. Beachten Sie aber. selbst wenn sie in derselben Transaktion ausgeführt werden. sind ihre Auswirkungen hinfällig und die zweite Transaktion kann fortfahren und die ursprünglich gefundene Zeile aktualisieren. um zu prüfen. als die Anfrage mit der Ausführung begonnen hat. Wenn die erste Transaktion zurückgerollt wird. welche sie vorher schon gelesen hat. dass eine solche Zielzeile. wenn andere Transaktionen während der Ausführung des ersten SELECT abgeschlossen wurden. erneut und stellt fest. wenn sie von der ersten gelöscht wurde. ihre Operation an der aktualisierten Zeile auszuführen. ausgehend von der aktualisierten Version der Zeile. dann wird die Zeile von der zweiten Transaktion ignoriert. sie sieht niemals Daten aus nicht abgeschlossenen Transaktionen oder aus Transaktionen. Wegen der obigen Regel ist es möglich.1: SQL-Transaktionsisolationsgrade PostgreSQL bietet die Isolationsgrade Read Committed und Serializable an. die die Zeilen betref- 202 . die seitdem abgeschlossen wurde. Die Befehle UPDATE. geändert hat. (Das SELECT sieht allerdings die Auswirkungen von vorherigen Aktualisierungen in der eigenen Transaktion. dass zwei aufeinander folgende SELECT-Befehle unterschiedliche Daten sehen könnten.

welcher die Änderungen aus allen bis zu diesem Zeitpunkt abgeschlossenen Transaktionen enthält. Da jeder Befehl nur eine vorherbestimmte Zeile bearbeitet. Wenn zwei solche Transaktionen gleichzeitig versuchen.2. wenn die “Serialisierung” fehlschlägt. Wenn die erste Transaktion zurückgerollt wird. Da im Modus Read Committed jeder neue Befehl mit einem neuen Schnappschuss anfängt. nicht vom Anfang des aktuellen Befehls innerhalb der Transaktion. er sieht niemals Daten aus nicht abgeschlossenen Transaktionen oder Änderungen aus Transaktionen. ergibt sich keine besorgniserregende Inkonsistenz daraus. müssen allerdings darauf vorbereitet sein. UPDATE konten SET kontostand = kontostand . ehe sie gefunden wurde. die von Transaktionen stammen. Dieser Grad emuliert die serielle Ausführung von Transaktionen. Wenn eine Transaktion im Modus Serializable ist. Der Sinn und Zweck hier ist. Aufeinander folgende SELECT-Befehle innerhalb derselben Transaktion sehen also immer die gleichen Daten. In Anwendungen mit komplexen Anfragen und Aktualisierungen kann es allerdings notwendig sein. den Kontostand von Konto 12345 zu ändern. Die Befehle UPDATE.00 WHERE kontonr = 12345. Die teilweise Transaktionsisolation. obwohl die eigene Transaktion ja noch nicht abgeschlossen wurde. als die Ausführung der Transaktion begann. dass wir innerhalb eines einzelnen Befehls einen absolut konsistenten Blick auf die Datenbank haben. die schon abgeschlossen waren. ob die erste Transaktion erfolgreich abgeschlossen oder zurückgerollt wird (wenn sie überhaupt noch unabgeschlossen ist). DELETE und SELECT FOR UPDATE verhalten sich genauso wie SELECT. Transaktionen neu zu versuchen. dass die zweite Transaktion von der aktualisierten Version der Kontozeile ausgeht.100. die durch den Modus Read Committed geboten wird. ist für viele Anwendungen ausreichend und ist auch schnell und leicht zu verwenden. die während der Ausführung der aktuellen Transaktion abgeschlossen wurden.Konsistenzkontrolle im Mehrbenutzerbetrieb fen. dass ein SELECT einen Schnappschuss vom Anfang der Transaktion sieht. Betrachten Sie zum Beispiel das Aktualisieren von Kontoständen mit Transaktionen wie BEGIN. In diesem Fall wartet die serialisierbare Transaktion. dann wollen wir zweifellos. Anwendungen. welche der Befehl aktualisieren will.00 WHERE kontonr = 7534. eine noch strengere Konsistenz der Datenbankansicht zu garantieren. als ob die Transaktionen nacheinander statt gleichzeitig ausgeführt worden wären. dass eine solche Zielzeile. aber er sieht nicht die Auswirkungen der gleichzeitigen Transaktionen auf andere Zeilen in der Datenbank. wenn es um das Suchen von Zielzeilen geht: Sie finden nur Zeilen. dann sind ihre Auswirkungen hinfällig und die serialisierbare Transaktion kann fortfahren und die ursprünglich gefundene Zeile aktualisieren. wird die serialisierbare Transaktion mit der Meldung ERROR: Can't serialize access due to concurrent update 203 .) Das unterscheidet sich vom Modus Read Committed dadurch. UPDATE konten SET kontostand = kontostand + 100. Es kann aber sein. dass die zweite Transaktion die aktualisierten Daten sieht. Für einfachere Fälle ist er aber genau richtig. Dieses Verhalten macht den Modus Read Committed für Befehle mit komplexen Suchbedingungen ungeeignet. (Das SELECT sieht allerdings die Auswirkungen von vorherigen Aktualisierungen in der eigenen Transaktion. die diesen Grad verwenden. Aber wenn die erste Transaktion erfolgreich abgeschlossen wird (und die Zeile tatsächlich aktualisiert oder gelöscht und nicht nur zur Aktualisierung ausgewählt wurde). welche abgeschlossen wurden. sehen nachfolgende Befehle die Auswirkungen von gleichzeitig ablaufenden. schon von einer gleichzeitig laufenden Transaktion aktualisiert (oder gelöscht oder zur Aktualisierung markiert) worden ist. bevor die neue Transaktion begann. 12. abgeschlossenen Transaktionen sowieso. COMMIT.2 Der Isolationsgrad Serializable Der Isolationsgrad Serializable bietet die strikteste Transaktionsisolation. dann sieht ein SELECT-Befehl nur Daten aus Transaktionen.

um sicherzustellen. dass einige Sperrmodi mit sich selbst in Konflikt stehen (zum Beispiel kann eine ACCESS EXCLUSIVE-Sperre nicht von mehreren Transaktionen gleichzeitig gehalten werden). die so komplex sind. haben niemals Serialisierungskonflikte. Der einzige wirkliche Unterschied zwischen den Sperrmodi ist. dass alle diese Sperren auf Tabellenebene wirken. wenn MVCC nicht das gewünschte Verhalten bietet. dass die verwendeten Tabellen nicht entfernt oder auf nichtverträgliche Art verändert werden. um den gleichzeitigen Zugriff auf Tabellendaten zu kontrollieren. Wenn eine Anwendung diese Fehlermeldung sieht. In gewisser Weise spiegeln die Namen die typischen Verwendungssituationen eines Sperrmodus wider. (Zum Beispiel kann ALTER TABLE nicht gleichzeitig mit irgendeiner anderen Operation an der gleichen Tabelle ausgeführt werden. die einen identischen Blick auf die Datenbank haben müssen. aber einige nicht (zum Beispiel kann eine ACCESS-SHARE Sperre von mehreren Transaktionen gehalten werden). können Sie die Systemsicht pg_locks verwenden. Sie kann zum Beispiel eine ACCESS EXCLUSIVE-Sperre setzen und später eine ACCESS-SHARE Sperre für dieselbe Tabelle. Beachten Sie. komplexe Transaktionen zu wiederholen. die Illusion der aufeinander folgenden Ausführung aufrechtzuerhalten. Im zweiten Versuch sieht die Transaktion die Auswirkungen der anderen Transaktion als Teil ihres anfänglichen Schnappschusses von der Datenbank. wenn aktualisierende Transaktionen Befehle enthalten.) Sperren. können von mehreren Transaktionen gleichzeitig gehalten werden. Denken Sie daran. sodass es keine logischen Widersprüche gibt. Beachten Sie auch besonders. wie Sie das Sperrensystem überwachen können. dass jede Transaktion einen vollständig konsistenten Blick auf die Datenbank hat.3.3 Ausdrückliche Sperren PostgreSQL bietet verschiedene Sperrmodi.) 12. Meistens ist der Modus Serializable notwendig. Transaktionen. um Sperren von der Anwendung aus zu kontrollieren. Transaktionen zu wiederholen.Kapitel 12 zurückgerollt. Der Modus Serializable gibt einem eine rigorose Garantie. die von anderen Transaktionen nach Beginn der serialisierbaren Transaktion geändert wurden. aber die Bedeutung ist bei allen Sperren die gleiche. Um zu überprüfen. weil eine serialisierbare Transaktion keine Zeilen ändern kann. Wenn eine Sperre gesetzt wurde. finden Sie in Kapitel 23. Weitere Informationen. Da es mit enormem Aufwand verbunden sein kann. die nur lesen. 12. wenn die neue Version der Zeile als Ausgangspunkt für die Aktualisierungen in der neuen Transaktion verwendet wird. welche Sperren gerade im Datenbankserver gehalten werden. dass sie im Modus Read Committed falsche Ergebnisse liefern könnten. Die meisten PostgreSQL-Befehle setzen auch automatisch die passenden Sperren. selbst wenn der Name das Wort “row” (Zeile) enthält. wenn eine Transaktion mehrere aufeinander folgende Befehle ausführt. wenn gleichzeitige Änderungen es unmöglich machen. Anwendungen müssen aber bereit sein. bleibt sie bis zum Ende der Transaktion erhalten. die nicht in Konflikt miteinander stehen. mit welchen anderen Modi sie in Konflikt stehen. dass nur schreibende Transaktionen gelegentlich wiederholt werden müssen. sollte sie die aktuelle Transaktion abbrechen und die ganze Transaktion von vorne versuchen. 204 .1 Tabellensperren Die unten folgende Liste zeigt die vorhandenen Sperrmodi und in welchen Zusammenhängen die Sperren von PostgreSQL automatisch gesetzt werden. Diese Modi können verwendet werden. während der Befehl ausgeführt wird. ist dieser Modus nur empfohlen. (Eine Transaktion kann allerdings nie mit sich selbst in Konflikt stehen. die Namen der Sperrmodi sind historisch bedingt. die in Konflikt zueinander stehen. Zwei Transaktionen können nicht zur gleichen Zeit für die gleiche Tabelle Sperren innehaben.

Dieser Modus schützt eine Tabelle gegen gleichzeitige Schemaveränderungen oder VACUUM-Läufe. Dieser Modus schützt eine Tabelle gegen gleichzeitige Datenänderungen. ROW SHARE. dass die Transaktion. Dieser Modus garantiert. ROW SHARE Steht in Konflikt mit den Sperrmodi EXCLUSIVE und ACCESS EXCLUSIVE. können nur Lesevorgänge in der Tabelle stattfinden. EXCLUSIVE und ACCESS EXCLUSIVE. SHARE ROW EXCLUSIVE. Generell setzt jede Anfrage. SHARE ROW EXCLUSIVE. die nur eineTabelle liest und nicht verändert. SHARE ROW EXCLUSIVE Steht in Konflikt mit den Sperrmodi ROW EXCLUSIVE. wenn kein anderer Sperrmodus ausdrücklich angegeben wurde.Konsistenzkontrolle im Mehrbenutzerbetrieb Tabellensperrmodi ACCESS SHARE Steht nur in Konflikt mit dem Sperrmodus ACCESS EXCLUSIVE. SHARE UPDATE EXCLUSIVE. ACCESS EXCLUSIVE Steht in Konflikt mit allen Sperrmodi (ACCESS SHARE. EXCLUSIVE Steht in Konflikt mit den Sperrmodi ROW SHARE. DELETE und INSERT setzen Sperren dieses Modus für die Zieltabelle (zusätzlich zu ACCESS-SHARE Sperren für alle anderen verwendeten Tabellen). EXCLUSIVE und ACCESS EXCLUSIVE. gleichzeitig mit einer Transaktion. SHARE UPDATE EXCLUSIVE. SHARE UPDATE EXCLUSIVE. SHARE. SHARE. aber nicht in der FOR UPDATE-Klausel stehen). SHARE ROW EXCLUSIVE. ROW EXCLUSIVE. die einzige Transaktion ist. SHARE Steht in Konflikt mit den Sperrmodi ROW EXCLUSIVE. Dieser Sperrmodus wird von keinem PostgreSQL-Befehl automatisch verwendet. ROW EXCLUSIVE Steht in Konflikt mit den Sperrmodi SHARE. diesen Sperrmodus. Automatisch von CREATE INDEX gesetzt. Der Befehl SELECT setzt Sperren dieses Modus für alle verwendeten Tabellen. EXCLUSIVE und ACCESS EXCLUSIVE. die verwendet werden. SHARE UPDATE EXCLUSIVE Steht in Konflikt mit den Sperrmodi SHARE UPDATE EXCLUSIVE. diesen Sperrmodus. Automatisch von VACUUM (ohne FULL) gesetzt. Der Befehl UPDATE. SHARE. der die Daten in einer Tabelle verändert. die diesen Sperrmodus hält. Der Befehl SELECT FOR UPDATE setzt Sperren dieses Modus für die Zieltabelle(n) (zusätzlich zu ACCESS SHARE-Sperren für alle anderen Tabellen. die auf diese Tabelle auf irgendeine Art zugreift. SHARE UPDATE EXCLUSIVE. Generell setzt jeder Befehl. Wird automatisch von den Befehlen ALTER TABLE. EXCLUSIVE und ACCESS EXCLUSIVE. DROP TABLE und VACUUM FULL gesetzt. SHARE ROW EXCLUSIVE. die diese Sperre hält. das heißt. EXCLUSIVE und ACCESS EXCLUSIVE. ROW EXCLUSIVE. Dieser Modus erlaubt nur eine gleichzeitige ACCESS SHARE-Sperre. Dieser Sperrmodus wird von keinem PostgreSQL-Befehl automatisch verwendet. Dieser Modus wird auch vom Befehl LOCK TABLE verwendet. SHARE. SHARE ROW EXCLUSIVE. 205 . EXCLUSIVE und ACCESS EXCLUSIVE). SHARE ROW EXCLUSIVE.

endlos darauf warten. dass die erste Sperre. ein SELECT FOR UPDATE verändert die ausgewählten Zeilen zum Beispiel. dass man sie vermeidet. Das bedeutet. wird eine Transaktion. dass alle Anwendungen in einer Datenbank Sperren für mehrere Objekte in einer einheitlichen Reihenfolge anfordern. 12. Wenn eine bestimmte Zeilensperre gesetzt wurde. PostgreSQL speichert keine Informationen über veränderte Zeilen im Hauptspeicher und hat daher keine Höchstgrenze. die wegen Verklemmungen abgebrochen wurden. 12. sobald eine Zeile gelesen oder aktualisiert wurde. Zum Beispiel.) Die beste Vorsorge gegen Verklemmungen ist im Allgemeinen. wenn Transaktion 1 eine exklusive Sperre für Tabelle 1 setzt und danach versucht. kann man Verklemmungen zur Laufzeit behandeln. den höchsten Modus. Eine Zeilensperre für eine bestimmte Zeile wird automatisch gesetzt. Außerdem sollte man sicherstellen. Solange keine Verklemmung entdeckt wird.3. dann kann keine der beiden Transaktionen fortfahren. die für ein Objekt in einer Transaktion angefordert wird. indem eine der verwickelten Transaktionen abgebrochen wird. Zeilensperren haben keine Auswirkungen auf das Anfragen von Daten. dass es keine gute Idee ist. den man für das Objekt benötigen wird. hat. die eine Tabellen. indem man darauf achtet.4 Konsistenzkontrolle auf der Anwendungsseite Da Lesevorgänge in PostgreSQL ungeachtet des Transaktionsisolationsgrads keine Daten sperren. (Welche Transaktion genau abgebrochen wird.2 Zeilensperren Neben Tabellensperren gibt es Zeilensperren.3. 12. Um eine Zeilensperre zu setzen.und Zeilensperren gibt es noch exklusive und nichtexklusive Sperren auf Speicherseitenebene. die die anderen erlangen wollen. indem man Transaktionen. Wenn es nicht praktikabel ist. kann eine Transaktion eine Zeile mehrfach aktualisieren.oder Zeilensperre angefordert hat. Anwendungsentwickler müssen sich in der Regel nicht mit diesen Sperren befassen. Die Sperre wird gehalten. dass in Konflikt stehende Sperren aufgehoben werden. wie viele Zeilen auf einmal gesperrt sein können. ohne vor Konflikten Angst haben zu müssen. und dadurch muss auf die Festplatte geschrieben werden. Transaktionen über längere Zeiträume offen zu lassen (z.Kapitel 12 Tipp Nur eine ACCESS EXCLUSIVE-Sperre blockiert einen SELECT-Befehl (ohne FOR UPDATE).und Schreibzugriff auf die Tabellenspeicherseiten im gemeinsamen Pufferpool kontrollieren. ohne die Zeile wirklich zu verändern. eine exklusive Sperre für Tabelle B zu erlangen. Diese Sperren werden sofort wieder aufgehoben. wodurch die andere(n) fortfahren können. die von einer Transaktion gelesen werden. während man auf eine Eingabe des Anwenders wartet). sie blockieren nur Schreibvorgänge in der selben Zeile. PostgreSQL entdeckt Verklemmungen automatisch und löst sie. Außer Tabellen. wenn die Zeile aktualisiert (oder gelöscht oder zur Aktualisierung markiert) wird. welche den Lese. dies vorher zu überprüfen.3 Verklemmungen Durch die Verwendung von expliziten Sperren können Verklemmungen (englisch deadlock) auftreten. wählen Sie die Zeile mit SELECT FOR UPDATE aus. während Transaktion 2 schon eine exklusive Sperre für Tabelle B hält und jetzt eine exklusive Sperre für Tabelle A möchte.B. neu startet. Das sperren einer Zeile kann allerdings Schreibvorgänge auf die Festplatte verursachen. aber wir erwähnen sie hier der Vollständigkeit halber. können die Daten. bis die Transaktion abgeschlossen oder zurückgerollt wird. von einer anderen Transaktion zeitgleich überschrie- 206 . ist schwer vorherzusagen und man sollte sich nicht darauf verlassen. wenn zwei (oder mehr) Transaktionen jeweils Sperren halten.

wenn man von PostgreSQL-Versionen vor 6. außer der eigenen.5 hat auch PostgreSQL Lesesperren verwendet.)-Anfragen würde im Isolationsgrad Read Committed nicht verlässlich sein. dann sollte man den Isolationsgrad Read Committed verwenden. bevor sie die Prüfung durchführt. wenn man ausdrückliche Sperren verwendet. aber wenn der von der Transaktion gesehene Schnappschuss vor dem Setzen der Sperre gemacht wurde. Aber es stellt sich die legitime Frage. Eine Sperre im Modus SHARE (oder höher) garantiert.. (SELECT FOR UPDATE sperrt nur die Ergebniszeilen gegen gleichzeitige Aktualisierungen. aber nicht alle Änderungen.Konsistenzkontrolle im Mehrbenutzerbetrieb ben werden. Wenn die serialisierbare Transaktion selbst einige Änderungen vornimmt. Die Zeile könnte von einer Transaktion. dann wird die Bedeutung des Prüfungsergebnisses noch fragwürdiger. um so ein unstrittiges Bild der gegenwärtigen Tatsachen zu erhalten. die Daten in der gesperrten Tabelle verändert hat.5 kommt. wenn man sehr sorgfältig ist. enthält. dass die Zeile im Moment der Rückgabe (d. die von einer serialisierbaren Transaktion gesetzt wurde. Globale Datenprüfungen erfordern unter MVCC etwas mehr Überlegung. wenn sie endlich ausgegeben wird. Wenn man die Summen in einer einzelnen serialisierbaren Transaktion berechnen lässt. bevor die serialisierbare begann. wenn die erste Anfrage oder der erste Datenmodifikationsbefehl (SELECT. wenn eine Zeile von einem SELECT zurückgegeben wird. In solchen Fällen könnte man. die die Tabelle verändern. ob die Antwort. und gleichzeitig ablaufende Transaktionen können sehr wohl unterschiedliche Schnappschüsse sehen. dass keine anderen Transaktionen. die abgeschlossen wurden. Anders ausgedrückt. Daher gelten die obigen Überlegungen auch. dass es keine unabgeschlossene Transaktion. Das ist normalerweise kein großes Problem. da in die zweite Anfrage wahrscheinlich Ergebnisse von Transaktionen mit einfließen. Sperren zu setzen. dass man die Sperren setzt. bevor die aktuelle Transaktion abgeschlossen oder zurückgerollt wird. müssen Sie den Befehl SELECT FOR UPDATE oder einen passenden LOCK TABLE-Befehl verwenden. kann das zu einem ernsthaften Durcheinander führen. weil es jetzt einige. oder im Modus Serializable darauf achten. noch am laufen sind. UPDATE oder DELETE) ausgeführt wird. könnte sie geändert oder gelöscht werden. um gleichzeitige Änderungen auszuschließen. garantiert. geändert oder gelöscht worden sein. Anmerkung Vor Version 6. wogegen LOCK TABLE die ganze Tabelle sperrt. irgendwann nachdem die Anfrage anfing) noch aktuell ist. dass jede Transaktion einen Schnappschuss des Datenbankinhalts sieht. wenn die Clientanwendungen voneinander getrennt sind. dann ist es möglich.. Der Schnappschuss einer serialisierbaren Transaktion wird eingefroren. Selbst wenn die Zeile “jetzt” noch gültig ist.) Das sollte man mit in die Überlegungen einfließen lassen. Eine andere Möglichkeit. Der ganze Begriff des “Jetzt” ist also sowieso etwas zweifelhaft. Eine ausdrückliche Sperre.h. Eine Bankanwendung könnte zum Beispiel überprüfen wollen. aber wenn Clients über Kanäle außerhalb der Datenbank miteinander kommunizieren. dann erhält man ein genaues Bild über die Auswirkungen der Transaktionen. also ist es möglich. bevor man Anfragen ausführt. Um den aktuellen Zustand einer Zeile abzusichern und sie gegen gleichzeitig ablaufende Aktualisierungen zu schützen. wobei beide Tabellen ständig aktualisiert werden. wenn man Anwendungen von anderen Umgebungen nach PostgreSQL übertragt. Beachten Sie auch. INSERT. die nach dem Start der Transaktion getätigt wurden. dass er auch vor einigen Änderungen gemacht wurde. alle für die Prüfung notwendigen Tabellen sperren. ob die Summe aller Soll-Beträge in einer Tabelle gleich der Summe aller Haben-Beträge in einer anderen Tabelle ist. 207 . die nicht von der ersten mitgezählt wurden. heißt das nicht. ist. die nach dieser abgeschlossen wurde. gibt. überhaupt noch relevant ist. Das Vergleichen zweier aufeinander folgender SELECT sum(. sich das vorzustellen. bevor der Schnappschuss eingefroren wird. die aus seit dem abgeschlossenen Transaktionen stammen.

Kapitel 12 12. wird nicht blockierendes Lesen und Schreiben gegenwärtig nicht für alle in PostgreSQL vorhandene Indextypen geboten. Die verschiedenen Indextypen werden folgendermaßen behandelt: B-Tree-Indexe Es werden kurzzeitige Lese. sind aber für Verklemmungen anfällig. wenn der Befehl beendet ist. Die Sperren werden aufgehoben.und Schreibsperren auf Seitenebene verwendet. die ein hohes Maß an Parallelität erfordern. nachdem die Seite verarbeitet worden ist. B-Tree-Indexe bieten das beste Maß an gleichzeitigem Zugriff ohne Verklemmungsgefahr. GIST.und Schreibsperren auf Seitenebene verwendet. Die Sperren werden sofort.und Schreibsperren auf Indexebene verwendet.5 Sperren und Indexe Obwohl PostgreSQL nicht blockierendes Lesen und Schreiben in Tabellen ermöglicht. Hash-Indexe Es werden Lese. aufgehoben. nachdem eine Indexzeile gelesen oder eingefügt wurde. Die Sperren werden aufgehoben. 208 .und R-Tree-Indexe Es werden Lese. Seitensperren bieten bessere gleichzeitige Ausführung als Indexsperren. Kurz gesagt sind B-Tree-Indexe empfohlen für Anwendungen.

Dieses Kapitel gibt einige Hinweise. Es ist auch wichtig zu bedenken. dass die Kosten eines übergeordneten Knotens die Kosten aller untergeordneten Knoten enthalten.) ❏ geschätzte Zahl der Zeilen. Einige davon können vom Benutzer verändert werden. Wenn Sie mit diesen Faktoren experimentieren wollen. dann schauen Sie sich die Liste der Laufzeiteinstellungen in Abschnitt 16. die benötigt wird. einen Anfrageplan (englisch query plan). was dies hier nicht ist. welchen Anfrageplan das System für jede beliebige Anfrage erstellt. um die Ergebnisse an den Client zu schicken. z. die dieser Planknoten ausgeben wird (wiederum nur. Sie können den Befehl EXPLAIN verwenden. für die es eigentlich eine ausführliche Anleitung geben sollte. aber wir geben hier einige grundsätzliche Informationen. was in der tatsächlich abgelaufenen Zeit ein ziemlich beherrschender Faktor sein könnte. 13. sind: ❏ geschätzte Startkosten (Zeit. (Die CPU-Bemühungen werden mit relativ willkürlichen Umrechnungsfaktoren in Diskseiten-Einheiten umgewandelt. um zu sehen. die dieser Planknoten ausgibt Die Einheiten der Kostenwerte ist das Lesen (fetch) einer Diskseite (disk page). aber vom Planer ignoriert wird. bis die Ausgabe anfangen kann.4 an.1 EXPLAIN verwenden PostgreSQLPostgreSQL entwirft für jede Anfrage. wie Sie die Leistungsfähigkeit von PostgreSQL verstehen und verbessern können. ( Jeder korrekte Plan ergibt dieselbe Zeilenmenge. Das Lesen des Plans ist eine Kunst für sich. dass die Kosten nur die Vorgänge einberechnen. hoffen wir doch. was nicht sein muss: Eine Anfrage mit einer LIMIT-Klausel wird zum Beispiel nicht die gesamten Kosten verursachen. Die Zahlen. aber andere Faktoren sind fest im Design des Systems verankert. die gegenwärtig von EXPLAIN ausgegeben werden. Insbesondere beinhalten die Kosten nicht die Zeit. die ausgeführt werden soll. weil es nicht durch Veränderung des Plans verbessert werden kann. der der Struktur der Anfrage und den Eigenschaften der Daten entspricht. Zeit zum Sortieren in einem Sortierknoten) ❏ geschätzte Gesamtkosten (Wenn alle Zeilen zurückgegeben würden. um die sich der Planer/Optimierer kümmert. ist für eine gute Leistung absolut kritisch.) Es ist wichtig anzumerken.B. die benötigt wird. Die Wahl des richtigen Plans.13 13 Tipps zur Leistungsverbesserung Die Leistung von Anfragen kann von vielen Dingen beeinflusst werden. wenn er ganz ausgeführt wird) ❏ geschätzte Breite (in Bytes) der Zeilen.) 209 .

was es gibt. Die tatsächliche Anzahl der Zeilen. dass tenk1 Diskseiten und 10000 Zeilen hat.00 rows=1033 width=148) Filter: (unique1 < 1000) Die Schätzung der Ergebniszeilen hat sich wegen der WHERE-Klausel verringert. weswegen die Kosten nicht gefallen sind. aber die Schätzung ist nur annähernd. werden Sie wahrscheinlich geringfügig andere Schätzungen sehen. dieses Experiment selbst zu wiederholen...01 ist (probieren Sie SHOW cpu_tuple_cost).33 rows=49 width=148) Index Cond: (unique1 < 50) 210 .00. ist 1000. Ändern Sie die Anfrage noch einmal. Im Idealfall wird die Zeilenschätzung für den obersten Knoten in etwa gleich der Zahl der tatsächlich von dieser Anfrage ausgewählten. weil die geschätzten Effekte einer etwaigen Bedingung in einer WHERE-Klausel in diesem Knoten mit einfließen.und Gesamtkosten. QUERY PLAN ------------------------------------------------------------- Seq Scan on tenk1 (cost=0. plus 10000 mal cpu_tuple_cost (CPU-Kosten pro Zeile). was gegenwärtig 0.179.00. um der gestiegenen CPU-Leistung vom Prüfen der WHERE-Bedingung Rechnung zu tragen. außerdem wird sich die Schätzung nach jedem ANALYZE-Befehl ändern.333. mit den Entwicklungsquelltext von 7.00.. sie ist normalerweise geringer. werden Sie feststellen. um die Bedingung noch stärker einschränkend zu machen: EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50. tatsächlich sind sie sogar ein bisschen gestiegen. die per Definition 1. die diese Anfrage liefert. weil sie nicht die Zahl der Zeilen darstellt. was so ziemlich das einfachste ist.0 pro Stück kosten. ausführen. da die von ANALYZE erstellten Statistiken aus einer zufälligen Auswahl aus der Tabelle erstellt werden. Allerdings muss immer noch die gesamte Tabelle mit 10000 Zeilen durchsucht werden. Die Kosten werden also berechnet aus 233 zu lesenden Seiten. aktualisierten oder gelöschten Zeilen sein. QUERY PLAN ------------------------------------------------------------------------------Index Scan using tenk1_unique1 on tenk1 (cost=0.00 rows=10000 width=148) Das ist ein Sequential Scan. Wenn Sie versuchen. QUERY PLAN -----------------------------------------------------------Seq Scan on tenk1 (cost=0.Kapitel 13 Die Zahl der ausgegebenen Zeilen ist etwas knifflig. rows die Zeilenschätzung und width die Zeilenbreite.) Wenn Sie die Anfrage SELECT * FROM pg_class WHERE relname = 'tenk1'. Hier sind einige Beispiele (aus der Regression-Test-Datenbank nach einem VACUUM ANALYZE. (cost sind die Start. Jetzt modifizieren wir die Anfrage und fügen eine WHERE-Klausel hinzu: EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 1000.3): EXPLAIN SELECT * FROM tenk1. die von der Anfrage gelesen oder verarbeitet werden.358. also eine Suche durch die Tabelle von Anfang bis Ende.

unique2 = konstante..00.01 rows=1 width=148) Index Cond: ("outer". In diesem Beispiel ist die Ergebniszeilenzahl des Verbunds gleich dem Produkt der Zeilenzahlen aus den beiden Schleifen. die wir im vorletzten Beispiel gesehen hatten. 211 . Daher haben sich die Kosten ein bisschen erhöht.33 rows=49 width=148) Index Cond: (unique1 < 50) -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0. Wenn wir zum Beispiel WHERE . Fügen Sie der WHERE-Klausel eine weitere Bedingung hinzu: EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50 AND stringu1 = 'xxx'. sagen wir EXPLAIN SELECT * FROM tenk2 WHERE unique2 = 42 sehen würden. Jetzt verbinden wir zwei Tabellen unter Verwendung der besprochenen Spalten: EXPLAIN SELECT * FROM tenk1 t1. aber nicht die Kosten.. Wir sehen folglich den gleichen Plan und die gleichen Kosten. Die Klausel t1. weil wir immer noch die gleiche Menge von Zeilen durchsuchen müssen.327. ein Index Scan (eine Indexsuche) billiger ist als eine sequenzielle Suche. also sind die Kosten und Zeilenzahlen gleich. Die Kosten des Nested-Loop-Knotens werden dann berechnet aus den Kosten für die äußere Schleife plus einer Wiederholung der inneren Schleife für jede äußere Zeile (hier 49 * 3. QUERY PLAN ---------------------------------------------------------------------------Nested Loop (cost=0. dann würde dadurch die Zahl der Ergebniszeilen sinken. aber das muss nicht immer der Fall sein.45 rows=1 width=148) Index Cond: (unique1 < 50) Filter: (stringu1 = 'xxx'::name) Die zusätzliche Bedingung stringu1 = 'xxx' verringert die Schätzung der Ausgabezeilen. QUERY PLAN ------------------------------------------------------------------------------Index Scan using tenk1_unique1 on tenk1 (cost=0.unique1 < 50 AND t1.Tipps zur Leistungsverbesserung Sie sehen. wird der Planer irgendwann entscheiden..hundred < t2..3. die auf beide Tabellen verweisen und daher nur im Verbundknoten angewendet werden können. weil wir die WHERE-Klausel unique1 < 50 in diesem Knoten anwenden. In der inneren Schleife wird der Wert von unique2 in der aktuellen Zeile der äußeren Schleife in die Indexsuche eingesetzt und erzeugt dadurch eine Indexbedingung wie t2.hundred hinzufügen würden.02 rows=49 width=296) -> Index Scan using tenk1_unique1 on tenk1 t1 (cost=0.01) plus etwas CPU für die Bearbeitung der Verbundoperation. die wir für.unique2 = t2. AND t1. um diese zusätzlichen Berechnungen mit einzuschließen. als eine Diskseite sequenziell zu lesen. weil man im Allgemeinen WHERE-Klauseln haben kann. dass die Bedingung mit stringu1 nicht als Suchbedingung für den Index verwendet werden kann (da der Index nur für die Spalte unique1 ist). tenk2 t2 WHERE t1.unique2 ist noch nicht relevant und beeinflusst folglich die Zeilenzahl der äußeren Schleife nicht. dass. Anstelle dessen wird sie als Filter für die Zeilen.unique2 = t2.00. Beachten Sie. nicht in einer der beiden Schleifen. verwendet.00.unique2...179. Dieser Plan wird wegen des Index nur 50 Zeilen aufsuchen müssen und ist daher besser. aber die beiden untergeordneten Schleifen bleiben gleich.unique2) In diesem Nested-Loop-Verbund (geschachtelte Schleifen) verwendet die äußere Schleife die gleiche Indexsuche. die aus der Indexsuche kommen.00. obwohl das Aufsuchen jeder einzelnen Zeile teurer ist.unique2 = t2. wenn Sie die WHERE-Bedingung ausreichend restriktiv machen.179.

00.0.Kapitel 13 Eine Möglichkeit. QUERY PLAN ------------------------------------------------------------------------------Nested Loop (cost=0. die ein einfaches EXPLAIN zeigt. dass die Kosten nicht 10000 mal 179.. von der er dachte. Die Kosten.unique2. QUERY PLAN -------------------------------------------------------------------------Hash Join (cost=179. diese dann in einer Hash-Tabelle im Hauptspeicher abzulegen.00..3.unique2) Total runtime: 31.00. tenk2 t2 WHERE t1.327. Wir könnten zum Beispiel ein Ergebnis wie dieses erhalten: EXPLAIN ANALYZE SELECT * FROM tenk1 t1.unique2 zu suchen. da wir keine Zeilen geliefert bekommen.32 rows=1 loops=50) Index Cond: ("outer"..82 rows=50 loops=1) -> Index Scan using tenk1_unique1 on tenk1 t1 (cost=0.179. aber eine sehr nützliche.unique2) -> Seq Scan on tenk2 t2 (cost=0. bis wir mit dem Lesen von tenk2 anfangen. um sich andere Pläne anzuschauen. Man kann die Genauigkeit der vom Planer geschätzten Kosten mit dem Befehl EXPLAIN ANALYZE überprüfen.) SET enable_nestloop = off.unique2.06 rows=49 width=296) Hash Cond: ("outer"..unique2 = t2. dass sie die beste wäre. die Strategie.179.unique2 = t2.45. (Das ist eine ziemlich primitive Methode.63.91 rows=50 loops=1) Index Cond: (unique1 < 50) -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0..8. EXPLAIN SELECT * FROM tenk1 t1.333. Die Schätzung der Gesamtzeit für den Verbund enthält auch einen hohen Preis für den CPU-Aufwand. um tenk1 zu lesen und die HashTabelle einzurichten.3. Dieser Befehl führt die Anfrage aus und zeigt dann die in jedem Planknoten gemessene Laufzeit zusammen mit den geschätzten Kosten. tenk2 t2 WHERE t1. die 50 interessanten Zeilen aus tenk1 mit demselben guten alten Indexscan herauszusuchen.01 rows=1 width=148) (actual time=0. den Planer zu zwingen. die Einrichtung der Hash-Tabelle findet bei diesem Plantyp nur einmal statt. Beachten Sie aber.18.33. um die Hash-Tabelle 10000 Mal zu prüfen.33 rows=49 width=148) Index Cond: (unique1 < 50) Dieser Plan schlägt vor..unique2 = "inner".. ist.33 betragen.00... Siehe auch Abschnitt 13.33 rows=49 width=148) -> Index Scan using tenk1_unique1 on tenk1 t1 (cost=0.00 rows=10000 width=148) -> Hash (cost=179. mithilfe der entsprechenden Laufzeiteinstellungen zu ignorieren.60 msec 212 .00.33 rows=49 width=148) (actual time=0. gehören vollständig zu den Startkosten des Hash-Verbunds.29.563.29.unique1 < 50 AND t1..unique1 < 50 AND t1.unique2 = t2.179.unique2 = t2.02 rows=49 width=296) (actual time=1. dann eine sequenzielle Suche durch tenk2 durchzuführen und für jede Reihe von tenk2 in der Hash-Tabelle nach möglichen Übereinstimmungen für t1.

dass die tatsächliche Laufzeit in Millisekunden Echtzeit ausgegeben wird. um die Tabelle zu verarbeiten. um beim Anfrageplan eine gute Wahl treffen zu können. relpages FROM pg_class WHERE relname LIKE 'tenk1%'. Wir können sie mit einer Anfrage wie dieser ansehen: SELECT relname. Bei INSERT-. Man kann zum Beispiel nicht davon ausgehen. Bei einer Anfrage mit SELECT wird die Gesamtlaufzeit normalerweise nur etwas größer sein als die vom obersten Planknoten berichtete Zeit. dass die Zahlen übereinstimmen. UPDATE. Die Kostenschätzungen des Planers sind nicht linear und so könnte er sehr wohl für große und kleine Tabellen unterschiedliche Pläne auswählen. Der Planer erkennt. reltuples. um die Ergebniszeilen zu verarbeiten. Umschreiben oder Planen. und die berichtete Ausführungszeit ist der Durchschnitt aus allen Läufen. sowie die Zeit. relkind. wie oft der Planknoten insgesamt ausgeführt wurde. Im oben gesehenen Nested-Loop-Plan zum Beispiel. muss der Anfrageplaner die Zahl der von einer Anfrage zurückgegebenen Zeilen abschätzen können. um die gesamte in dem Planknoten gebrauchte Zeit zu berechnen. wohingegen die Kostenschätzungen in willkürlichen Einheiten (Diskseiten-Fetch) sind. um in einen Index zu schauen. In solchen Fällen steht bei loops. Ein Bestandteil der Statistiken ist die Gesamtzahl der Einträge in jeder Tabelle und in jedem Index sowie die Zahl der Diskblöcke. die von jeder Tabelle und von jedem Index belegt werden. weil die Zeit zum Verarbeiten der Ergebniszeilen mitgerechnet wird. relname | relkind | reltuples | relpages ---------------+---------+-----------+---------tenk1 | r | 10000 | 233 tenk1_hundred | i | 10000 | 30 tenk1_unique1 | i | 10000 | 30 tenk1_unique2 | i | 10000 | 30 (4 rows) 213 . und dass es also keine Sinn macht. Diese Informationen werden in der Tabelle pg_class in den Spalten reltuples und relpages abgelegt. die nur eine Diskseite belegt. sind die Verhältnisse.Tipps zur Leistungsverbesserung Beachten Sie. 13. dass die Ergebnisse von kleinen Testtabellen auch für große Tabellen gelten. um die neuen Zeilen zu berechnen und/oder die alten zu finden. damit die Zahlen leicht mit den Kostenschätzungen verglichen werden können. die das System für diese Schätzungen verwendet.2 Vom Planer verwendete Statistiken Wie wir im vorigen Abschnitt gesehen haben. wird die innere Indexsuche einmal für jede Zeile in der äußeren Schleife ausgeführt. Die von EXPLAIN ANALYZE gezeigte Gesamtlaufzeit (Total runtime) enthält die Zeit. aber sie enthält nicht die Zeit. Dieser Abschnitt bietet einen kurzen Überblick über die Statistiken. Es ist also unwahrscheinlich. In einigen Anfrageplänen ist es möglich. dass ein Subplan mehrmals ausgeführt wird. um den Executor zu starten und zu beenden. Bei diesen Befehlen ist die Zeit des obersten Planknoten. erhalten Sie fast immer einen Plan mit sequenzieller Suche. Um ein extremes Beispiel zu nehmen: Bei einer Tabelle. worauf Sie achten sollten. egal ob Indexe vorhanden sind oder nicht. um die Änderungen zu vollziehen. die gebraucht wurde.und DELETE-Befehlen kann die Gesamtlaufzeit aber beträchtlich größer sein. im Prinzip die Zeit. dass er so oder so eine Diskseite lesen muss. Multiplizieren Sie diese Ausführungszeit mit der loops-Angabe. Sie enthält nicht die Zeit zum Parsen. zusätzliche Seiten zu lesen. dass die Ergebnisse von EXPLAIN nicht auf andere Situationen übertragen werden sollten. Das wird gemacht. Es sollte auch erwähnt werden. die gebraucht wurde.

(Die negative Form wird verwendet."Sp Railroad ". da es nicht jede Zeile der Tabelle liest. das nicht Teil eines VACUUM-Befehls ist. aber ein besseres gibt's zur Zeit nicht. wo alle Werte unterschiedlich sind und die Zahl der verschiedenen Werte genauso groß ist wie die Zahl der Zeilen. Die Einträge in pg_statistic werden von den Befehlen ANALYZE und VACUUM ANALYZE aktualisiert und sind auch direkt nach der Aktualisierung immer Annäherungswerte. Aus Effizienzgründen werden reltuples und relpages nicht laufend aktualisiert. Aktualisiert werden sie von bestimmten Befehlen.37. die es in pg_stats gibt."I. dass die Tabelle tenk1 10000 Zeilen enthält.880 Ramp".) Zum Beispiel bedeutet -1 eine Spalte.37.580 ". wenn die Spalte eine feste Zahl von möglichen Werten zu haben scheint.580 Ramp". Die meisten Anfragen lesen nur einen Teil der Zeilen in einer Tabelle aus. Die Sicht pg_stats zeigt nur Zeilen über Tabellen. weil WHERE-Klauseln die Menge der Zeilen einschränken. ist es besser. most_common_vals FROM pg_stats WHERE tablename = 'road'. Name tablename attname null_frac avg_width n_distinct Datentyp name name real Beschreibung Name der Tabelle."I. die geschätzte Zahl der voneinander verschiedenen Werte in der Spalte.71). 10). die die einzelnen Bedingungen in der WHERE-Klausel erfüllen.467008 | {"I. die von dieser Zeile beschrieben wird. sodass sie normalerweise nur annähernde Werte enthalten (was für den Planer ausreichend ist). Wenn eine Tabelle erzeugt wird.880 "} thepath | 20 | {"[(-122. Tabelle 13. sind in der Systemtabelle pg_statistic abgelegt. n_distinct. Name der Spalte. SELECT attname. attname | n_distinct | most_common_vals ---------+------------+---------------------------------------------------------name | -0. die der aktuelle Benutzer lesen kann. Der Planer muss daher eine Schätzung der Selektivität einer WHERE-Klausel abgeben.(-122.) Wir könnten zum Beispiel Folgendes machen: Dieses Beispiel ist viel zu breit. pg_stats wurde entworfen.1 zeigt die Spalten."I. dass die Zahl der verschiedenen Werte wahrscheinlich mit der Tabelle wächst.80 Ramp". er muss den Bruchteil der Zeilen schätzen."5th St "."I. erzeugt einen annähernden Wert für reltuples. ANALYZE und CREATE INDEX. Wenn kleiner als null. Die Informationen. Aber die Indexe sind (nicht überraschend) viel kleiner als die Tabelle. dass nichtprivilegierte Benutzer durch die Statistiken etwas über den Inhalt der Tabellen anderer Benutzer erfahren."14th St ".0886. dass heißt. Außerdem ist pg_stats von allen lesbar. wohingegen pg_statistic nur von einem Superuser lesbar ist. die NULL sind. Ein alleinstehendes ANALYZE. werden sie mit willkürlichen Vorgabewerten gefüllt (gegenwärtig 1000 bzw. real Wenn größer als null. Wenn man die Statistiken selbst untersuchen will. die Sicht pg_stats statt pg_statistic direkt anzuschauen.089. die für diese Aufgabe verwendet werden.1: Spalten von pg_stats 214 . genauso wie ihre Indexe."Mission Blvd". wenn ANALYZE glaubt. in die die Spalte gehört. um leichter lesbar zu sein.Kapitel 13 Hier sehen wir.711)]"} (2 rows) Tabelle 13.680 Ramp"."I. Anteil der Spalteneinträge. das Negative der Zahl der verschiedenen Werte geteilt durch die Zahl der Zeilen. die positive Form wird verwendet. integer Durchschnittliche Breite (Größe) in Bytes der Spalteneinträge. gegenwärtig VACUUM. (Dadurch wird verhindert.

1: Spalten von pg_stats (Forts. (Diese Spalte wird nicht gefüllt. besonders wenn die Daten sehr ungleichmäßig verteilt sind. wenn keine Werte häufiger als andere zu sein scheinen.id = b. Der Preis dafür wäre. (Alle Verbunde im PostgreSQLPostgreSQL-Executor geschehen zwischen zwei Eingabetabellen. da in dem Fall das volle Kreuzprodukt aus A und C errechnet werden müsste. Die Vorgabe ist gegenwärtig 10. als wenn er nahe null ist. also muss das Ergebnis auf eine dieser Arten aufgebaut werden.h. Reicht von -1 bis +1. müssen wir erst etwas Hintergrundwissen besprechen.) Die statistische Korrelation zwischen der physikalischen Reihenfolge der Zeilen und der logischen Reihenfolge der Spaltenwerte. kann der Planer die angegebenen Tabellen in beliebiger Reihenfolge verbinden. aber enorm unterschiedliche Ausführungskosten haben können. Er könnte zum Beispiel einen Anfrageplan erstellen. aber das wäre ineffizient.) Eine Liste der Häufigkeiten der häufigsten Werte.) Die Höchstzahl der Einträge in den Arrays most_common_vals und histogram_bounds kann mit dem Befehl ALTER TABLE SET STATISTICS für jede Spalte individuell eingestellt werden. weil es keine passende WHERE-Bedingung gibt. die Zahl der Vorkommen geteilt durch die Zahl der Zeilen. d. (Fällt weg. Oder er könnte A und C verbinden und dann das Ergebnis mit B. kann der Planer unter Umständen genauere Schätzungen erstellen. Umgekehrt könnte eine niedrigere Grenze für Spalten mit einfacher Datenverteilung angebracht sein. warum das wichtig sein kann. dann wird eine Indexsuche durch die Spalte als billiger eingeschätzt.id.) correlation real Tabelle 13. Eine Liste von Werten.id verbindet und dann das Ergebnis unter Verwendung der anderen WHERE-Bedingung mit C verbindet. um den Verbund optimieren zu können.) Es ist wichtig anzumerken. b. Wenn Sie die Grenze erhöhen. Die Werte in most_common_vals.Tipps zur Leistungsverbesserung Name most_common_vals most_common_freq s histogram_bounds Datentyp text[] real[] text[] Beschreibung Eine Liste der häufigsten Werte in der Spalte. falls vorhanden. Wenn der Wert nahe -1 oder +1 ist. den Anfrageplaner in einem gewissen Maß durch die Verwendung des expliziten JOINSyntax zu kontrollieren. werden von dieser Histogrammberechnung ausgeschlossen. (Diese Spalte wird nicht gefüllt.3 Den Planer mit expliziten JOIN-Klauseln kontrollieren Es ist möglich. weil die Verteilung der Festplattenzugriffe im ersten Fall weniger zufällig ist. In einer einfachen Verbundanfrage wie SELECT * FROM a.id = b.ref = c. dass diese unterschiedlichen Verbundmöglichkeiten alle semantisch äquivalente Ergebnisse liefern. dass etwas mehr Platz in pg_statistic gebraucht würde und das Berechnen der Schätzungen etwas länger dauern würde. Um zu sehen. Daher untersucht der Planer sie alle um den effizientesten Plan zu finden. wenn der Datentyp der Spalte keinen Operator < hat oder wenn die Liste in most_common_vals schon alle Spaltenwerte abdeckt. der A und B unter Verwendung der WHERE-Bedingung a.id AND b. c WHERE a. 13. 215 . die die Spaltenwerte in etwa gleich große Gruppen unterteilen (Histogrammgrenzen). Oder er könnte B und C verbinden und dann das Ergebnis mit A. wenn der Datentyp der Spalte keinen Operator < hat.

findet aber nicht unbedingt den bestmöglichen Plan. die keine passende Reihe im Verbund von B und C hat.id)) ON (a.id AND b.ref = c.id = b.ref = c. Hier muss der Verbund mit D der letzte Schritt im Anfrageplan sein.Kapitel 13 Wenn eine Anfrage nur zwei oder drei Tabellen verwendet.id AND b. zum Beispiel: SELECT * FROM d LEFT JOIN (SELECT * FROM a.. Das heißt natürlich.id = b. inneren Verbunden. wechselt PostgreSQL von der erschöpfenden Suche zu einer genetischen Suche auf Wahrscheinlichkeitsbasis durch eine begrenzte Zahl von Möglichkeiten. Dieser Effekt ist bei nur drei Tabellen nicht weiter beachtenswert.id). kann aber bei Anfragen mit vielen Tabellen ein Lebensretter sein. Wenn zu viele Tabellen angegeben wurden. c WHERE a.id)) ON (a.. Dementsprechend dauert das Planen dieser Anfrage auch kürzer als bei der vorigen Anfrage. Das Beschränken der Suche des Planers auf diese Art ist eine nützliche Technik. Jenseits von rund zehn Tabellen ist es nicht mehr praktikabel.) Die genetische Suche braucht weniger Zeit. Wenn die Anfrage einen äußeren Verbund enthält.id. Der PostgreSQL-Anfrageplaner behandelt alle ausdrücklichen JOIN-Syntaxen so.) AS ss ON (. (Die Schwelle für diesen Wechsel wird durch den Konfigurationsparameter geqo_threshold eingestellt. alle Möglichkeiten zu durchsuchen und auch bei sechs oder sieben Tabellen kann das Planen lästig lange dauern. Mit der JOIN-Syntax können Sie das nicht direkt machen.ref = c. weil für jede Zeile von A. Alle folgenden Anfragen ergeben daher das gleiche Ergebnis: SELECT * FROM a. SELECT * FROM a JOIN (b JOIN c ON (b.).id. Wenn Sie in einer komplexen Anfrage eine Mischung aus inneren und äußeren Verbunden haben.id = b. SELECT * FROM a CROSS JOIN b CROSS JOIN c WHERE a. d. bevor sie mit anderen Tabellen verbunden werden. Das zwingt den Planer. B und C in Betracht ziehen. Betrachten wir zum Beispiel SELECT * FROM a LEFT JOIN (b JOIN c ON (b.. Daher hat der Planer hier keine Wahl bezüglich der Verbundreihenfolge: Er muss B und C verbinden und dann A mit dem Ergebnis. eine Ergebniszeile erzeugt werden muss. b.ref = c. dass durch sie die Verbundreihenfolge festgelegt wird. A und B zu verbinden.id = b. Dadurch wird in diesem Beispiel die Zahl der möglichen Verbundreihenfolgen um den Faktor 5 reduziert. um die es sich zu kümmern gilt. c. c WHERE . um die Planzeit zu reduzieren auch auch den Planer zu einem guten Anfrageplan zu führen. wenn Sie eine bessere Reihenfolge kennen. Zum Beispiel: SELECT * FROM a CROSS JOIN b. aber der Planer kann alle möglichen Verbundreihenfolgen zwischen A. aber Sie können diese syntaktische Beschränkung mit Unteranfragen umgehen. e WHERE . Aber die Zahl der möglichen Verbundreihenfolgen steigt exponentiell mit der Zahl der Tabellen. schränkt die Wahlmöglichkeiten aber nicht anderweitig ein. können Sie eine bessere Reihenfolge mit der JOIN-Syntax erzwingen. aber die zweite und dritte kann schneller als die erste geplant werden. Ausprobieren wird empfohlen. Sie können nämlich JOIN-Operatoren in einer normalen FROM-Liste verwenden.. wollen Sie vielleicht die Suche des Planers nach einer guten Reihenfolge für die inneren Verbunde innerhalb der äußeren Verbunde nicht einschränken. Sie müssen die Verbundreihenfolge nicht vollständig einschränken um die Suchzeit zu verkürzen. ist doch die Bedeutung unterschiedlich. Wenn der Planer in der Standardeinstellung eine schlechte Verbundreihenfolge wählt. obwohl dies bei inneren Verbunden mathematisch nicht notwendig wäre. 216 ..id). b.. gibt es nicht viele Verbundreihenfolgen. Obwohl die Bedingungen in dieser Anfrage oberflächlich gesehen dem vorangegangenen Beispiel ähnlich sind.. dann hat der Planer viel weniger Freiheit als bei einfachen.

Hier sind einige Tipps und Techniken. nicht durchgeführt wird. ist es der schnellste Weg. 13.4. Manche Clientbibliotheken machen das vielleicht automatisch hinter Ihrem Rücken. was zu schlechter Leistung bei Anfragen. Dadurch wird die Zeit zum Parsen. Es ist schneller. dass der Planer aktuelle Statistiken über die Tabelle hat. Das stellt sicher. die Daten laden und den Index erneut erzeugen.3 Indexe entfernen Wenn Sie Daten in eine frisch erzeugte Tabelle laden. dass wenn das Einfügen einer Zeile fehlschlagen sollte. ist. Man sollte sich das Entfernen eines Unique Index auch genau überlegen. können Sie den Index entfernen.) Wenn Sie es zulassen. da die Fehlerprüfung. wenn man alle Einfügeoperationen in einer Transaktion ausführt. als ihn schrittweise mit jeder neuen Zeile aufzubauen. dann müssen Sie schauen. ANALYZE oder VACUUM ANALYZE immer dann auszuführen. dass nach jeder Einfügeoperation eine Transaktion abgeschlossen wird. dann alle bis dahin eingefügten Zeilen zurückgerollt werden und Sie nicht mit teilweise geladenen Daten sitzen bleiben. nachdem man die Tabelle anfänglich mit Daten gefüllt hat. um das so effizient wie möglich zu machen. Wenn Sie eine bestehende Tabelle um viele Daten erweitern wollen. 13. die Daten mit COPY zu laden und dann die benötigten Indexe zu erzeugen. die die Tabelle verwenden. 13. sehr verringert. dann hat PostgreSQL bei jeder neuen Zeile eine Menge Arbeit. dass die Bibliothek es macht.1 Autocommit ausschalten Schalten Sie Autocommit. Wenn Sie das tun. Ohne Statistiken oder mit veralteten Statistiken könnte der Planer schlechte Anfragepläne auswählen.4 Eine Datenbank füllen Wenn Sie eine Datenbank am Anfang mit Daten füllen. Ein zusätzlicher Vorteil.2 COPY FROM verwenden Verwenden Sie COPY FROM STDIN. Während der Index fehlt.4. kann dadurch natürlich die Datenbankleistung für andere Benutzer negativ beeinflusst werden. 13. wenn Sie es wollen. um alle Zeilen mit einem Befehl zu laden. weil es sowieso nur ein Befehl ist. Planen usw. die durch einen solchen Index geboten wird. führt. wenn man viele Daten eingefügt oder aktualisiert hat. müssen Sie Autocommit nicht ausschalten. also das automatische Abschließen einer Transaktion nach jedem Befehl. indem Sie ein BEGIN am Anfang und ein COMMIT am Ende ausführen. (Im normalen SQL machen Sie das. müssen Sie möglicherweise eine große Zahl von Einfügeoperationen vornehmen. einschließlich. einen Index für schon bestehende Daten zu erzeugen.4. aus und führen Sie nur ein COMMIT am Ende aus. die Tabelle zu erzeugen. 217 .4.Tipps zur Leistungsverbesserung 13. wenn der Index fehlt.4 Danach ANALYZE ausführen Es ist empfehlenswert. anstatt eine Reihe von INSERT-Befehlen zu verwenden.

.

Zusätzliche Informationen können in Teil I und in Teil II gefunden werden. ihre Erkundungen mit diesem Teil beginnen können. sollten in Teil VI nachschauen. sei es für den persönlichen Gebrauch oder besonders im Produktionsbetrieb. wenn gewünscht einzeln gelesen werden. sollte mit den in diesem Teil behandelten Themen vertraut sein. die Verwaltung von Benutzern und Datenbanken sowie Wartungsaufgaben. dass sie ohne Vorkenntnisse verstanden werden können. Das beinhaltet die Installation der Software. in der ein neuer Anwender sie lesen sollte. dass der Leser mit der allgemeinen Verwendung des PostgreSQL-Datenbanksystems vertraut ist. der einen PostgreSQL-Server betreibt.3 Teil III Server-Administration Dieser Teil behandelt Themen. 219 . Jeder. Die Kapitel sind aber selbstständig und können. Der restlichen Kapitel dieses Teils. die für Administratoren von PostgreSQL-Datenbanken von Interesse sind. die eine vollständige Beschreibung eines bestimmten Befehls suchen. gehen davon aus. Die Informationen in diesem Teil sind in etwa in der Reihenfolge angeordnet. die ihren eigenen Server einrichten müssen. damit neue Anwender. die von der Feinabstimmung und der Wartung handeln. Die ersten paar Kapitel sind so geschrieben. das Einrichten und Konfigurieren des Servers. In diesem Teil sind die Informationen erzählerisch in Themenbereichen aufbereitet. Leser.

VAKAT VAKAT .

14. Die Plattformen. 14.2 Voraussetzungen Generell sollte PostgreSQL auf allen modernen Unix-kompatiblen Plattformen laufen können./configure gmake su gmake install adduser postgres mkdir /usr/local/pgsql/data chown postgres /usr/local/pgsql/data su .14 14 Installationsanweisungen Dieses Dokument Kapitel beschreibt die Installation von PostgreSQL von der Quellcodedistribution.postgres /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data /usr/local/pgsql/bin/postmaster -D /usr/local/pgsql/data >logfile 2>&1 & /usr/local/pgsql/bin/createdb test /usr/local/pgsql/bin/psql test Die lange Version ist der Rest dieses Dokuments. wenn es Probleme gibt. 221 .1 Kurzversion . Im Unterverzeichnis doc in der Distribution gibt es mehrere plattformspezifische FAQ-Dokumente. auf denen zum Zeitpunkt der Veröffentlichung getestet wurde.7 aufgezählt. Kapitels. in denen Sie nachschauen sollten. sind unten in Abschnitt 14.

muss libpython auf den meisten Plattformen auch eine dynamische Bibliothek sein. Refer to *** the documentation for details. Da PL/Python eine dynamische Bibliothek sein wird.) ❏ Um den Quellcode auf Windows NT oder Windows 2000 zu übersetzen. um diese dynamische Bibliothek zur Verfügung zu stellen. Refer to *** the documentation for details. *** You might have to rebuild your Perl installation. benötigen Sie eine volle Perl-Installation.1 zu verwenden.) Um zu überprüfen. Neuere Versionen von GCC sind empfehlenswert. ❏ Um die Serverprogrammiersprache PL/Perl zu bauen. einschließlich der Headerdateien. ❏ gzip wird benötigt. (Wenn Sie die Ausgaben auf dem Bildschirm nicht verfolgen. Wenn Sie sie nicht benutzen wollen. Dies ist bei einer Standardinstallation von Python nicht der Fall. werden Sie nur feststellen. dann müssen Sie die Option --withoutreadline angeben. benötigen Sie eine Python-Installation.) Wenn Sie dies sehen. ob Sie GNU make haben. wie unten erklärt wird. geben Sie ein: gmake --version Es wird empfohlen. dann ist alles in Ordnung. dass Sie Ihre Python-Installation (oder einen Teil davon) neu bauen müssen. ❏ Die GNU Readline-Bibliothek (zur bequemen Bearbeitung von Eingabezeilen) wird in der Voreinstellung verwendet. (Auf NetBSD ist die Bibliothek libedit mit Readline kompatibel und wird verwendet. Einzelheiten finden Sie in der Datei doc/FAQ_MSWIN. aber eine brauchen. Wenn Sie nach dem Übersetzen und Installieren eine Datei namens plpython. *** You might have to rebuild your Python installation. wenn bestimmte Optionen eingeschaltet werden. Die folgenden Pakete können wahlweise verwendet werden. Da PL/Perl eine dynamische Bibliothek sein wird. muss libperl auf den meisten Plattformen auch eine dynamische Bibliothek sein. Das scheint in den neueren Perl-Versionen die Voreinstellung zu sein. und generell ist es die Wahl desjenigen. wenn libreadline gefunden wird. taucht wahrscheinlich während des Übersetzungsprozesses eine Meldung wie die Folgende auf. um Sie darauf hinzuweisen: *** Cannot build PL/Perl because libperl is not a shared library. dieses Dokument wird diesen Namen durchweg verwenden. aber es war nicht so in früheren Versionen. dass das Bibliotheksobjekt für PL/Perl. Während des Konfigurationsvorgangs von Perl verlangen Sie dann eine dynamische Bibliothek (shared library). aber PostgreSQL kann mit vielen Compilern von verschiedenen Herstellern übersetzt werden. aber Sie sind nötig. 222 . Ansonsten sollten Sie eine Hinweismeldung ähnlich dieser vorbeilaufen gesehen haben: *** Cannot build PL/Python because libpython is not a shared library. nicht installiert sein wird. um PostgreSQL zu bauen: ❏ GNU make ist erforderlich. der Perl bei Ihnen installiert hat. (Auf einigen Systemen ist GNU make das Standardwerkzeug mit dem Namen make. einschließlich der libperl-Bibliothek und der Headerdateien.76. mindestens Version 3. benötigen Sie die Pakete Cygwin und cygipc. um PL/Perl bauen zu können. Sie sind in der Standardeinstellung nicht erforderlich.so (möglicherweise eine andere Erweiterung) haben. andere make-Programme funktionieren nicht. Wenn Sie die dynamische Bibliothek nicht haben. um die Distribution zu entpacken. ❏ Um die Python-Schnittstelle oder die Serverprogrammiersprache PL/Python bauen zu können. wenn Sie configure ausführen. Das bedeutet. GNU make ist oft unter dem Namen gmake installiert. ❏ Sie benötigen einen ISO/ANSI-C-Compiler.Kapitel 14 Die folgenden Softwarepakete sind erforderlich. plperl.so oder ähnlich. müssen Sie Perl neu übersetzen und installieren.

Wenn Sie mehrere Java-Compiler installiert haben. Ant ist ein spezielles Werkzeug für das Bauen von Java-basierenden Paketen. das heißt.B.3 JAVACMD=$JAVA_HOME/bin/java Anmerkung Versuchen Sie nicht.30. Wenn Sie ein GNU-Paket benötigen. Sie brauchen etwa 65 MB im Quellbaum während der Übersetzung und etwa 15 MB im Installationsverzeichnis. Ein leerer Datenbankcluster belegt etwa 25 MB. um den Festplattenplatz zu überprüfen.50 verwenden. wie eine einfache Textdatei mit denselben Daten belegen würde. ❏ Um Native Language Support (NLS). NetBSD. Wenn Sie die Regressionstests durchführen wollen. Schauen Sie sich die Makefile im Verzeichnis src/pl/plpython wegen Einzelheiten an. Andere Lex-Programme funktionieren definitiv nicht. welcher verwendet wird.5 oder höher und ein JDK. ❏ Wenn Sie Tcl. dass sie ausreichend Platz auf der Festplatte haben. 223 . wenn Sie Authentifizierung mit diesen Diensten unterstützen wollen. benötigen Sie außerdem die folgenden Pakete: ❏ Flex und Bison werden benötigt. Wenn Sie mit einem CVS-Baum anstatt der veröffentlichten Quellpakete arbeiten oder selbst Entwicklungen tätigen wollen. Sie können es von der Ant-Website herunterladen. Auf einigen Betriebssystemen müssen Sie eigentlich keine dynamische Bibliothek bauen. Datenbanken belegen etwa fünfmal so viel Platz. Wenn Sie die Gettext-Implementierung aus der GNU C-Bibliothek verwenden.antrc im Home-Verzeichnis des aktuellen Benutzers lesen. ❏ Kerberos. um einen CVS-Checkout zu bauen oder wenn Sie die eigentlichen Definitionsdateien von Scanner und Parser verändert haben. benötigen Sie natürlich eine Tcl-Installation. Einige Betriebssysteme haben dies eingebaut (z.5. könnte dies hier funktionieren: JAVA_HOME=/usr/local/sun-jdk1. die Fähigkeit. Verwenden Sie den Befehl df. dass die Python-Distribution oder die Python-Entwickler dafür keine direkte Möglichkeit vorgesehen haben. Um zum Beispiel eine andere JDK als die voreingestellte zu verwenden. benötigen Sie eine Implementierung der GettextSchnittstelle. können Sie es auf Ihrer örtlichen GNU Mirrorsite (siehe für eine Liste) oder auf finden. benötigen Sie Ant 1. zu aktivieren. OpenSSL oder PAM. hängt es von der Ant-Konfiguration ab. Das beste.4 und mindestens Bison 1. Solaris). aber dann müssen Sie das Buildsystem von PostgreSQL davon überzeugen. Vorkompilierte Ant-Distributionen sind typischerweise so eingerichtet. Andere Yacc-Programme können manchmal verwendet werden. sind die Informationen in Python FAQ 3.Installationsanweisungen Der Haken ist. dann werden Sie vorübergehen weitere 90 MB benötigen. Führen Sie gmake normal wie unten beschrieben aus. dass sie eine Datei . Bei den anderen Implementierungen brauchen Sie es nicht. aber das erfordert zusätzliche Anstrengungen und ist nicht zu empfehlen. Das wird nicht funktionieren. um Konfigurationseinstellungen vorzunehmen. was wir Ihnen anbieten können. dann sollten Sie mindestens Flex 2. Wenn Sie sie benötigen. Linux.oder Tk-Komponenten (Clients oder die PL/Tcl-Sprache) bauen wollen. den Treiber direkt durch das Aufrufen von ant oder gar javac zu bauen. für andere Systeme können Sie sich hier ein Zusatzpaket herunterladen: . benötigen Sie außerdem das Paket GNU Gettext für einige Hilfsprogramme. Überprüfen Sie auch. ❏ Um den JDBC-Treiber zu bauen. die Programmmitteilungen in einer anderen Sprache als Englisch anzuzeigen.

Wechseln Sie für den Rest des Installationsvorgangs in dieses Verzeichnis.4 nach. spätestens bevor Sie die neuen Dateien installieren. müssen Sie die Option -o von pg_dumpall verwenden. einen Mirror. aktualisieren wollen. pg_dumpall sichert keine Large Objects. wenn nötig. die PostgreSQL beim Booten starten. geben Sie ein: pg_dumpall > ausgabedatei Wenn Sie die OIDs erhalten müssen (wenn Sie sie zum Beispiel als Fremdschlüssel verwenden). Schauen Sie in der Dokumentation in Abschnitt 22. Um Ihre Datenbankinstallation zu sichern.4 Wenn Sie eine alte Version aktualisieren Das interne Datenformat ändert sich bei jeder Hauptversion von PostgreSQL. herunter: kill -INT `cat /usr/local/pgsql/data/postmaster. pg_dumpall von PostgreSQL zu verwenden. 14. die auch dazu verwendet werden kann.conf (oder das Äquivalent) um allen außer Ihnen den Zugriff zu verbieten.pid nicht. Für die Datensicherung können Sie den pg_dumpall-Befehl von der Version nehmen. Bearbeiten Sie. Verwenden Sie.3 Die Quellen erhalten Die Quellen für PostgreSQL kann man durch anonymes FTP von erhalten.gz tar xf postgresql-. Versichern Sie sich. Dadurch senken Sie auch die Ausfallzeit. Wenn Sie die neue Version am gleichen Platz wie die alte installieren. dass Ihre Datenbank während oder nach dem Sicherungsvorgang nicht verändert wird. Auf einem Red-Hat-Linux-System könnte zum Beispiel 224 .tar Dadurch wird ein Verzeichnis postgresql. die Sie aktuell verwenden.unter dem aktuellen Verzeichnis erzeugt. In dem Fall können Sie die Installation normal durchführen und die Daten später übertragen. die Zugriffskontrolldatei /usr/ local/pgsql/data/pg_hba. Diese Anweisungen gehen davon aus.x” hat. dann fahren Sie den alten Server. welches die PostgreSQL-Quellen enthält. ist er aber zu empfehlen. Die Integrität der gesicherten Daten wird dadurch nicht beeinträchtigt. 1. Obwohl dieser Rat eigenartig zu sein scheint. Wenn Sie daher eine bestehende Installation.0 haben diese Datei postmaster. entpacken Sie sie: gunzip postgresql-. 2. die nicht die Versionsnummer “. wenn Sie die neue Version parallel zur alten installieren wollen.Kapitel 14 14. wenn möglich. Ersetzen Sie Ihre Pfade entsprechend. müssen Sie die Prozess-ID des Servers selbst herausfinden. gibt es wahrscheinlich eine Startdatei. Für die besten Ergebnisse sollten Sie aber versuchen. müssen Sie Ihre Daten wie hier gezeigt sichern und wiederherstellen. 3.1. Auf Systemen.tar. aber die veränderten Daten würden natürlich nicht enthalten sein. da diese Version Berichtigungen und Verbesserungen gegenüber älteren Versionen enthält.pid` Versionen vor 7. Wenn Sie die Datei erhalten haben. Wenn Sie so eine Version verwenden. wenn Sie das tun müssen. weil Sie die neue Version ja noch nicht installiert haben. zum Beispiel indem Sie ps ax | grep postmaster eingeben und sie an den Befehl kill übergeben. dass Ihre bestehende Installation unter dem Verzeichnis /usr/local/pgsql ist und das Datenverzeichnis /usr/local/ pgsql/data ist.

Alle Dateien werden in der Voreinstellung unter /usr/local/pgsql installiert. 4. Verwenden Sie einen Befehl wie diesen: mv /usr/local/pgsql /usr/local/pgsql. keine Datei wird jemals direkt im Verzeichnis PRÄFIX installiert. während Sie mit dem speziellen Datenbankbenutzerzugang angemeldet sind (den Sie schon haben.3 in weiteren Einzelheiten besprochen.und Installationsprozess anpassen. Die eigentlichen Dateien werden in verschiedene Unterverzeichnisse installiert. Dieses Skript führt eine Reihe von Tests aus.d/postgresql stop funktionieren. die nur einen C-Compiler erfordern. um aufzuzeichnen.5 Installationsvorgang 1. Sie können den Build. Dazu führen Sie das Skript configure aus. und erzeugt abschließend einige Dateien unter dem aktuellen Verzeichnis. Konfiguration Der erste Schritt des Installationsvorgangs ist es. um Werte für verschiedene systemabhängige Variablen zu erraten und einige Macken Ihres Betriebssystems zu entdecken./configure ein. was es gefunden hat.d/init. dass Sie diese Befehle ausführen müssen. Wenn Sie auf dem gleichen Platz wie die alte Version installieren. /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data /usr/local/pgsql/bin/postmaster -D /usr/local/pgsql/data Schließlich stellen Sie Ihre Daten wieder her. Denken Sie daran. ist es auch zu empfehlen. 14. falls Sie Probleme haben und die Installation rückgängig machen müssen. indem Sie eine oder mehrere der folgenden Kommandozeilenoptionen für configure angeben: --prefix=PRÄFIX Installiert alle Dateien unter dem Verzeichnis PRÄFIX anstelle von /usr/local/pgsql. (Sie können configure auch in einem Verzeichnis außerhalb des Quellbaums ausführen. wenn Sie bereits eine Installation haben).) Die voreingestellte Konfiguration baut den Server und Hilfsprogramme sowie alle Clientanwendungen und -schnittstellen. um das Buildverzeichnis getrennt zu halten. Um eine Installation mit allen Vorgabeeinstellungen durchzuführen.old Nachdem Sie PostgreSQL installiert haben. Diese Themen werden in der Dokumentation in Abschnitt 22. den Quellbaum für Ihr System zu konfigurieren und die gewünschten Optionen auszuwählen. indem Sie Folgendes ausführen: /usr/local/pgsql/bin/psql -d template1 -f ausgabedatei Verwenden Sie dazu das neue psql. erzeugen Sie ein neues Datenbankverzeichnis und starten den Server. geben Sie . die alte Installation aus dem Weg zu verschieben. 225 . Eine andere Möglichkeit ist pg_ctl stop.Installationsanweisungen /etc/rc.

um architekturunabhängige Dateien zwischen mehreren Maschinen zu teilen. hinzugefügt werden. die der Liste. installiert. dass dies nichts damit zu tun hat. Zum Beispiel. Die Voreinstellung ist PRÄFIX/share. --datadir=VERZEICHNIS Setzt das Verzeichnis für nur lesbare Datendateien. sysconfdir und docdir angehängt. aber wenn der Präfix /opt/postgres ist. --docdir=VERZEICHNIS Dokumentationsdateien. ohne den Namensraum des restlichen Systems zu stören. Die internen Headerdateien und die Server-Headerdateien werde in private Verzeichnisse unter includedir installiert. Die öffentlichen C-Headerdateien der Clientschnittstellen werden in includedir installiert und respektieren den Namensraum des Systems. dass PostgreSQL in geteilte Installationsverzeichnisse (wie /usr/local/ include) installiert werden kann.Kapitel 14 Wenn Sie besondere Anforderungen haben. was normalerweise /usr/local/pgsql/bin bedeutet. durch Doppelpunkte getrennt. werden unter diesem Verzeichnis. --bindir=VERZEICHNIS Gibt das Verzeichnis für ausführbare Programme an. --mandir=VERZEICHNIS Die man-Seiten. --includedir=VERZEICHNIS Das Verzeichnis für die Installation von Headerdateien für C und C++. In der Anleitung zu jeder Schnittstelle finden Sie Informationen. Beachten Sie. Die Voreinstellung ist PREFIX/man. Die Voreinstellung ist PRÄFIX/doc. Die Voreinstellung ist PRÄFIX/include. Die Voreinstellung ist EXEC-PRÄFIX/lib. in ihre entsprechenden manx-Unterverzeichnisse. können Sie auch die einzelnen Unterverzeichnisse mit den folgenden Optionen anpassen. wo die Datenbankdateien abgelegt werden sollen. was Sie wollen. wenn der voll ausgewertete Verzeichnisname nicht schon die Zeichenkette “postgres” oder “pgsql” enthält. wie Sie die jeweils benötigten Headerdateien finden. werden in dieses Verzeichnis installiert. wird sie in /opt/ postgres/doc installiert. Wenn Sie diese Option weglassen. wenn Sie /usr/local als Präfix wählen. Das kann nützlich sein. Erstens wird die Zeichenkette “/postgresql” automatisch an datadir. ein privates Unterverzeichnis unter libdir für dynamisch ladbare Module erzeugt. was wahrscheinlich das ist. --with-includes=VERZEICHNISSE VERZEICHNISSE ist eine Liste von Verzeichnissen. --exec-prefix=EXEC-PRÄFIX Sie können die architekturabhängigen Dateien unter einem anderen Präfix. Anmerkung Es wurde Sorge getragen. die der Compiler nach Headerdateien durchsucht. außer “man”-Seiten. wird die Dokumentation in /usr/ local/doc/postgresql installiert. Schließlich wird auch. um Bibliotheken und dynamisch ladbare Module zu installieren. --libdir=VERZEICHNIS Der Platz. Wenn Sie optio226 . die mit PostgreSQL geliefert werden. in der Voreinstellung PRÄFIX/etc. installieren als PRÄFIX. Die Voreinstellung ist EXEC-PRÄFIX/ bin. EXEC-PRÄFIX. --sysconfdir=VERZEICHNIS Das Verzeichnis für diverse Konfigurationsdateien. wird EXEC-PRÄFIX gleich mit PRÄFIX gesetzt und architekturabhängige und unabhängige Dateien werden unter demselben Baum installiert. die von den installierten Programmen verwendet werden. wenn angebracht.

Der Port kann immer noch später geändert werden. --enable-recode Schaltet Einzelbyte-Zeichensatzrekodierungs-Unterstützung ein. Um diese Option zu verwenden. --without-tk Wenn Sie --with-tcl und diese Option angeben. das Tk benötigt (pgtksh). Beispiel: --with-libraries=/opt/gnu/lib:/usr/sup/lib. 227 . Siehe aber unten über --without-tk. das heißt libpgtcl.) Wenn Sie keine Liste angeben. wenn Sie Pakete an nicht standardisierten Orten installiert haben. --with-libraries=VERZEICHNISSE VERZEICHNISSE ist eine Liste von Verzeichnissen. aber wenn Sie ihn hier angeben. --with-tcl Baut Komponenten.3. werden Server und Clients die gleiche Voreinstellung eingebaut bekommen. müssen Sie diese Option verwenden. siehe oben. --with-python Baut das Python-Schnittstellenmodul und die serverseitige Sprache PL/Python. --enable-nls[=SPRACHEN] Schaltet Native Language Support (NLS) ein. --with-pgport=NUMMER Bestimmt NUMMER als die voreingestellte Portnummer für Server und Clients. die die nach Bibliotheken durchsucht werden sollen. die Sie unterstützt haben wollen. für die Sprachen. wird das Programm. was sehr praktisch sein kann. um das Python-Modul an seinem normalen Platz (/usr/lib/ pythonx. dass eine allgemeinere Form von Zeichensatzkonvertierung in der Standardkonfiguration verfügbar ist. durch Doppelpunkte getrennt. ist normalerweise. Sie werden diese Option (und die entsprechenden Option mit --with-includes) wahrscheinlich verwenden müssen. die Tcl/Tk erfordern. Sie müssen root-Zugang haben. (Die Schnittmenge zwischen Ihrer Liste und den tatsächlich vorhandenen Übersetzungen wird automatisch berechnet.y) installieren zu können. pgtksh und PL/ Tcl. die Fähigkeit. durch Leerzeichen getrennt. die Programmmitteilungen in einer anderen Sprache als Englisch anzuzeigen. --with-perl Baut die serverseitige Sprache PL/Perl. und wahrscheinlich auch die entsprechende Option mit --withlibraries. nicht mit installiert. Beachten Sie. werden alle vorhandenen Übersetzungen installiert. benötigen Sie eine Implementierung der Gettext API.Installationsanweisungen nale Pakete (wie GNU Readline) an nicht standardisierten Orten installiert haben. dieses Feature ist obsolet. wenn Sie mehrere PostgreSQL-Server auf einer Maschine laufen haben wollen. um einen anderen Wert als den Standard zu wählen. Beispiel: --with-includes=/opt/gnu/include:/usr/sup/include. Der einzige gute Grund. Weitere Informationen über diese Fähigkeit finden Sie in der Dokumentationin Abschnitt 20. pgtclsh. SPRACHEN ist eine Liste von Kürzeln. das heißt. zum Beispiel -enable-nls='de fr'. Die Standardeinstellung ist 5432.

die benötigt werden. können Sie das Argument weglassen. Das Argument VERZEICHNIS gibt das Wurzelverzeichnis der Kerberos-Installation an.oder Tk-Module zu bauen. der automatisch durchsucht wird (z. Es gibt wahrscheinlich keinen Grund. Das bedeutet. Wenn andererseits die erforderlichen Dateien an einem Ort liegen. --with-tkconfig=VERZEICHNIS Tcl/Tk installiert die Dateien tclConfig. 228 . Das vergrößert die installierten Dateien beträchtlich. Wenn die relevanten Headerdateien und Bibliotheken nicht unter einem gemeinsamen Verzeichnis installiert sind. Aber wenn Sie Betaversionen verwenden oder selbst Entwicklungsarbeit tun. --with-java Baut den JDBC-Treiber und zugehörige Java-Pakete. Das Argument VERZEICHNIS gibt das Wurzelverzeichnis der OpenSSL-Installation an. /usr/lib). dass Ihre OpenSSL-Installation ausreichend ist. wo sie zu finden sind. --with-pam Baut mit Unterstützung für PAM (Pluggable Authentication Modules). müssen Sie zusätzlich zu dieser Option die Optionen --with-includes und --withlibraries verwenden. postgres ist der Standard. Das schaltet Kommandozeilenbearbeitung und -geschichte in psql ab. dann sollten Sie sie immer an haben. --without-readline Verhindert die Verwendung der Readline-Bibliothek. um Tcl. der Standardwert ist /usr/local/ssl. können Sie die Verzeichnisse angeben. --enable-debug Kompiliert alle Programme und Bibliotheken mit Debugsymbolen. dass Ihre Kerberos-Installation ausreichend ist. und bei Compilern außer GCC schaltet es gewöhnlich die Optimierung ab und verlangsamt dadurch die Ausführung. das zu ändern. --with-krb-srvnam=NAME Der Name des Service-Principals für Kerberos. um etwaige Probleme zu behandeln. aber nicht beide. Das schaltet Komprimierungsunterstützung in pg_dump ab. um sicherzustellen. Gegenwärtig wird diese Option für Produktionsinstallationen nur empfohlen. /usr/athena ist die Voreinstellung. configure prüft die erforderlichen Headerdateien und Bibliotheken. um Probleme zu analysieren. Die Debugsymbole sind allerdings äußerst hilfreich.Kapitel 14 --with-tclconfig=VERZEICHNIS. dass Sie Ihre Programme durch einen Debugger schicken können. wenn Sie GCC verwenden. um sicherzustellen. Diese Dateien werden normalerweise automatisch an den bekannten Orten gefunden. configure überprüft die erforderlichen Headerdateien und Bibliotheken. welche Konfigurationsinformationen enthalten.B. --with-krb4[=VERZEICHNIS] --with-krb5[=VERZEICHNIS] Baut mit Unterstützung für Authentifizierung mit Kerberos. ist also nicht zu empfehlen.sh. --with-openssl[=VERZEICHNIS] Baut mit Unterstützung für (verschlüsselte) SSL-Verbindungen.sh und tkConfig. Dafür muss das Paket OpenSSL installiert sein. Sie können Kerberos Version 4 oder 5 verwenden. Diese Option ist nur für jene seltenen Systeme gedacht. aber wenn Sie eine andere Version von Tcl oder Tk verwenden wollen. wo diese Bibliothek nicht verfügbar ist. --without-zlib Verhindert die Verwendung der Zlib-Bibliothek.

(Das funktioniert nicht als root. wie die Entwickler es beabsichtigt hatten. Wenn nichts anderes angegeben wird. Sie können Umgebungsvariablen auf der Kommandozeile von configure angeben. Ähnlich können Sie die Compileroptionen mit der Variable CFLAGS setzen. GNU make zu verwenden. Die Regressionstests sind eine Testsammlung. Mit dieser Option werden die Makefiles so eingerichtet. Die letzte ausgegebene Zeile sollte sein: All of PostgreSQL is successfully made. Gegenwärtig ist diese Option nicht für Produktionsanwendungen empfohlen. wenn Sie nur einmal kompilieren und installieren wollen. wie man die Testergebnisse zu verstehen hat. die eigentlich nicht auftreten können sollten. aber Sie sollten sie an haben. Durch die Tests wird auch die Stabilität des Servers nicht unbedingt verbessert! Die Tests sind nicht nach Schwere kategorisiert. 229 . können Sie die Umgebungsvariable CC auf das Programm Ihrer Wahl setzen./configure CC=/opt/bin/gcc CFLAGS='-O2 -pipe' 2. (Denken Sie daran. welche Bedingungen testen. Sie können diesen Test auch später mit dem gleichen Befehl wiederholen. außer wenn das für die Plattform unpassend ist. aber die Tests verlangsamen alles ein wenig.) Der Vorgang kann zwischen 5 Minuten und einer halben Stunde dauern. also werden selbst relativ harmlose Fehler einen Serverneustart verursachen. aber nur unnötiger Ballast. den configure auswählt. 3. dass alle betroffenen Objektdateien neu kompiliert werden. wählt configure gcc. Die Dateien installieren Um PostgreSQL zu installieren. dass einige Tests wegen unterschiedlichem Wortlaut von Fehlermeldungen oder Problemen mit Fließkommaberechnungen nicht erfolgreich sind. ob PostgreSQL auf Ihrer Maschine so funktioniert. wenn eine Assertion-Prüfung fehlschlägt. bevorzugen. die überprüfen. --enable-depend Schaltet die automatische Verfolgung von Dateiabhängigkeiten ein. geben Sie gmake install ein. Regressionstests Wenn Sie den neu gebauten Server vor der Installation testen möchten. wenn Sie selbst entwickeln oder eine Betaversion verwenden. Das ist unschätzbar bei der Codeentwicklung. machen Sie es als unprivilegierter Benutzer. wenn eine Headerdatei geändert wird. Wenn Sie einen anderen C-Compiler als den. Ready to install. geben Sie gmake ein. Geben Sie gmake check ein. abhängig von Ihrer Hardware. Die Datei src/test/regress/README und die Dokumentation enthalten Kapitel 26 enthält detaillierte Informationen. können Sie an diesem Punkt die Regressionstests ausführen.Installationsanweisungen --enable-cassert Schaltet Assertion-Prüfungen im Server ein. 4. Übersetzung Um die Übersetzung des Quelltextes zu starten.) Es kann vorkommen. Zurzeit funktioniert diese Option nur mit GCC. zum Beispiel: . Das ist bei der Entwicklungsarbeit nützlich.

Kapitel 14 Anmerkung Wenn Sie eine bestehende Installation aktualisieren und die neuen Dateien über die alten installieren. aber wie das zu tun ist. entfernt das Strippen faktisch die Debugunterstützung. ein vernünftiges Maß an Platz zu sparen. um die Programmdateien und Bibliotheken zu “strippen”. 230 . wenn Sie Serversoftware bauen. Alternativ könnten Sie die Zielverzeichnisse vorher erzeugen und die passenden Rechte dafür erteilen. indem Sie die gebauten Dateien aus dem Quellbaum mit dem Befehl gmake clean entfernen. Dadurch behalten Sie die von configure erzeugten Dateien. Wenn Sie mit Debugunterstützung kompiliert haben. wenn Sie nicht den Quellcodebaum behalten wollen. Wenn Sie für mehrere Plattformen vom selben Quellbaum aus bauen wollen. Das vergrößert die Installation um ein oder zwei Megabyte und ist nur sinnvoll. um jedes unnötige Byte aus einer Datei zu entfernen. dann sind Sie auf sich allein gestellt: Sie können die benötigten Dateien in anderen Verzeichnissen ablegen. dass Sie entsprechende Zugriffsrechte haben. In diesem Fall sollten Sie sich als root anmelden und dann gmake -C src/interfaces/python install ausführen. Wenn Sie die Python-Schnittstelle gebaut haben und Sie nicht der root-Benutzer waren.4 beschrieben. dann müssen Sie von Hand nacharbeiten. Deinstallation: Sie können die Installation mit dem Befehl gmake Dadurch werden jedoch keine Verzeichnisse entfernt. sollten Sie spätestens jetzt Ihre Daten gesichert und den alten Server heruntergefahren haben. Die Standardinstallation enthält nur die Headerdateien für die Entwicklung von Clientanwendungen. Wenn Sie also so viel Festplattenplatz wie möglich sparen wollen.) Clientinstallation: Wenn Sie nur die Clientanwendungen und Schnittstellenbibliotheken installieren wollen. ist der Teil der Installation wahrscheinlich fehlgeschlagen. Sie können gmake install-strip anstelle von gmake install verwenden. Dadurch werden die Dateien in die in Schritt 1. in dem Sie ihn erhalten hatten. während sie installiert werden. geben Sie gmake install-all-headers ein. (Wenn ja. wie oben in Abschnitt 14. müssen Sie das für jede Plattform tun und neu konfigurieren. können Sie einfach die Headerdateien aus dem Quellbaum nehmen. ist als Hausaufgabe belassen. Achten Sie darauf. Säubern: Nach der Installation können Sie Platz schaffen. Um den Quellbaum in den Zustand zurückzusetzen. aber es hat nicht das perfekte Wissen. Wenn Sie serverseitige Programmentwicklung planen (wie zum Beispiel eigene in C geschriebene Funktionen oder Datentypen). verwenden Sie gmake distclean. Wenn Sie keinen root-Zugang haben. Das spart etwas Platz. um in diesen Bereich zu schreiben. können Sie diese Befehle verwenden: gmake gmake gmake gmake -C -C -C -C src/bin install src/include install src/interfaces install doc install uninstall rückgängig machen. als Sie den obigen Befehl ausgeführt haben. wenn das Debuggen nicht mehr benötigt wird. möchten Sie vielleicht komplett alle PostgreSQL-Headerdateien in das Zielverzeichnis installieren. sollte also nur durchgeführt werden. angegebenen Verzeichnisse installiert. Normalerweise müssen Sie diesen Schritt als root machen. install-strip versucht. Um das zu tun. sodass Sie später alles mit gmake neu bauen können. wo Python sie finden kann.

so oder rld könnten von besonderem Interesse sein). wie es die neu installierten dynamischen Bibliotheken finden kann. IRIX. um den Suchpfad für dynamische Bibliotheken zu setzen. Linux oder SunOS 4 sind und root-Zugang haben. FreeBSD. Wenn Sie auf BSD/OS. NetBSD.dll-Dateien in das bin-Verzeichnis. Sie sollten diese Befehle in eine Shell-Startdatei eintragen.Installationsanweisungen Wenn Sie einen Build durchgeführt haben und feststellen. Wenn Sie sich nicht sicher sind. Tru64 UNIX (ehemals Digital UNIX) und Solaris.6 Einrichtung nach der Installation 14. 14. Wenn Sie später eine Mitteilung sehen wie psql: error in loading shared libraries libpq. (Die Manualseiten von ld. bash. Auf folgenden Systemen ist dies nicht notwendig: BSD/OS. die Umgebungsvariable LD_LIBRARY_PATH so zu setzen: in Bourne-Shells (sh. ksh. Auf Cygwin stellen Sie das Bibliotheksverzeichnis in den Pfad (PATH) oder verschieben die . Einige gute Informationen über mögliche Vorbehalte gegenüber dieser Methode können in gefunden werden. unterscheiden sich von Plattform zu Plattform. auf das Sie --libdir in Schritt 1.bash_profile. oder wenn Sie etwas geändert haben. vor der Neukonfiguration gmake distclean auszuführen und dann neu zu bauen. Auf einigen Systemen mag es besser sein. dass die configure-Optionen falsch waren. die Umgebungsvariable LD_RUN_PATH vor der Compilierung zu setzen. das von configure untersucht wird (zum Beispiel neue Software).so. Linux. Auf FreeBSD. um dem Laufzeitlinker das schnellere Finden der dynamischen Bibliotheken zu ermöglichen. aber die am häufigsten brauchbare Methode ist es. die dynamische Bibliotheken haben (was die meisten Systeme tun). zsh) LD_LIBRARY_PATH=/usr/local/pgsql/lib export LD_LIBRARY_PATH oder in csh oder tcsh setenv LD_LIBRARY_PATH /usr/local/pgsql/lib Ersetzen Sie /usr/local/pgsql/lib mit dem. Die Methoden. NetBSD und OpenBSD ist der Befehl stattdessen 231 . dann schauen Sie sich die Anleitung Ihres Systems an. Erledigen Sie ihn dann einfach später.1 Dynamische Bibliotheken Auf einigen Systemen. Ansonsten kann es sein. gesetzt haben. müssen Sie Ihrem System mitteilen. wie zum Beispiel /etc/profile oder ~/ .2. OpenBSD. dann ist es zu empfehlen. HP-UX. dann können Sie /sbin/ldconfig /usr/local/pgsql/lib (oder entsprechendes Verzeichnis) nach der Installation ausführen. dass Ihre Änderungen bei den Konfigurationsoptionen nicht überall ankommen.6.1: cannot open shared object file: No such file or directory war dieser Schritt notwendig. Weitere Informationen finden Sie in der Anleitung zu ldconfig.

Eine unterstützte Plattform bedeutet dabei in der Regel. 14. wenn es auf alle Benutzer Auswirkung haben soll). müssen Sie Zeilen wie die folgenden in eine Shell-Startdatei einfügen.org oder pgsql-ports@postgresql. Streng genommen ist das nicht notwendig. der normalerweise nicht nach Programmen durchsucht wird. wie ~/. schreiben Sie bitte an pgsql-bugs@postgresql. MANPATH=/usr/local/pgsql/man:$MANPATH export MANPATH Die Umgebungsvariablen PGHOST und PGPORT geben Clientanwendungen den Host und Port des Datenbankservers an und übergehen damit die eingebauten Vorgaben. Das ist nicht erforderlich. müssen Sie die Einstellungen mit Kommandozeilenoptionen oder Ähnlichem vornehmen. wenn jeder Benutzer. 232 . PGHOST setzt.7 Unterstützte Plattformen PostgreSQL wurde von der Entwicklergemeinde auf den unten gelisteten Plattformen auf korrektes Funktionieren überprüft. dann sollten Sie /usr/local/pgsql/bin (oder auf was Sie --bindir in Schritt 1. 14. Fügen Sie also Folgendes in eine Ihrer Shell-Startdateien. aber wenn Sie es nicht tun. dass PostgreSQL entsprechend dieser Anleitung gebaut und installiert werden kann und dass die Regressionstests erfolgreich waren. Wenn Sie Clientanwendungen auf entfernten Hosts laufen lassen wollen. ein: PATH=/usr/local/pgsql/bin:$PATH export PATH Wenn Sie csh oder tcsh verwenden.bash_profile (oder /etc/profile.Kapitel 14 /sbin/ldconfig -m /usr/local/pgsql/lib Auf anderen Systemen ist ein entsprechender Befehl nicht bekannt. nehmen Sie diesen Befehl: set path = ( /usr/local/pgsql/bin $path ) Um Ihrem System zu ermöglichen. ist es praktisch. der die Datenbank verwenden will.6. nicht an die hier aufgelisteten Leute. aber es macht die Verwendung von PostgreSQL viel bequemer. Anmerkung Wenn Sie Probleme mit der Installation auf unterstützten Plattformen haben. der in der Standardeinstellung schon durchsucht wird.org. gesetzt haben) in Ihren Suchpfad (PATH) einfügen. außer wenn Sie an einem Ort installiert haben.2 Umgebungsvariablen Wenn Sie in /usr/local/pgsql installiert haben oder an einem anderen Ort. die Dokumentation im man-Format zu finden.

3 7. siehe auch doc/FAQ_Solaris 233 .net) 2002-10-28.1 7.11.uk) 2002-11-19.1 Magnus Naeslund ( mag@fbab.pgh.3 2002-10-26.3 7.1.uk ).20 Tom Lane ( tgl@sss.org) 2002-10-26. 10.uk) 2002-11-17.au) 2002-11-14.3 Irix64 Komma 6.at 2002-10-25. Tom Lane ( tgl@sss.4.us ).3 1.org ). Sean Chittenden ( sean@chittenden. entferne slock_t typedef Linux Linux Linux Linux MacOS X PPC74xx 7. Permaine Cheung pcheung@redhat.2. Nigel J. Magnus Naeslund ( mag@fbab. Larry Rosenman ( ler@lerctr.0.3. 3. 5.pa.com.uchile. 10. Permaine Cheung pcheung@redhat.uk) 2002-11-14.us ).6 1. 3.us) 2002-11-13.3 5. Patrick Welche ( prlw1@newn.ac.net ). 3. Patrick Welche ( prlw1@newn.cam. siehe auch doc/FAQ_HPUX IRIX Linux Linux MIPS Alpha PlayStati on 2 7.cl) 2002-10-28.cam. Chris Kings-Lynne ( chriskl@familyhealth.com.com) Bemerkungen siehe auch doc/FAQ_AIX 4. 4.net) 2002-11-19.com) 2002-10-26. Shibashish Satpathy ( shib@postmark. Adam Witney ( awitney@sghms.3 7. Christopher Kings-Lynne ( chriskl@familyhealth.3 7. Bruce Momjian ( pgman@candle. 10. Andreas Zeugswetter ( ZeugswetterA@spardat.1.18.pgh.3.2. 11. gcc.pgh.ac.info) 2. Andrews ( nandrews@investsystems.org) 2002-10-28.19-pre6 #undef HAS_TEST_AND_SET.4 NetBSD NetBSD OpenBSD OpenBSD arm32 x86 Sparc x86 7.0.0 2. Andrew Sullivan ( andrew@libertyrms.pa. Giles Lean ( giles@nemeton. Alvaro Herrera ( alvherre@dcc.3 7.2 HP-UX PA-RISC 7. Apple G3 s390 und s390x (32 und 64 Bits) 3.2 SCO OpenServer 5 Solaris x86 Sparc 7.3 7. siehe auch doc/FAQ_SCO Solaris 7 und 8.3 2002-11-12.au) 2002-12-11.5 2.3 7.pa.pha.4.com.us) 2002-11-22. Doug McNaught ( doug@mcnaught.00.3 7. 11.6 3. 32 und 64 Bits.ac.Installationsanweisungen Betriebssystem AIX BSD/OS FreeBSD FreeBSD Prozessor Version Bericht RS6000 x86 Alpha x86 7. Tom Lane ( tgl@sss.com.3 7.7.au) 2002-10-29.3 7.net 2002-10-28.3 gcc und cc.co. Ian Barwick ( barwick@gmx.pa.3 S/390 Sparc x86 PPC 7.2 Christopher Kings-Lynne ( chriskl@familyhealth.au 2002-10-27.3 7.

0.2.x Linux MIPS 7. Wir erwähnen sie hier. Betriebssystem Prozessor Version Bericht BeOS x86 7.8. dass diese Plattformen unterstützt werden könnten.fr ) 1998-03-01. Cyril Velter ( cyril.3 armv4l 7.velter@libertysurf.1 braucht neue OSVersion? 1. 7.Kapitel 14 Betriebssystem Solaris Tru64 UNIX UnixWare Prozessor Version Bericht x86 Alpha x86 7.5.co. Mark Knox ( segfault@hardline.jp ) 2001-04-03. wenn sie etwas Aufmerksamkeit erfahren würden.nasa.2 (8.1 und 7.edu ) 2001-12-10.3 234 .3 7. Hotz ( hotz@jpl.co.org ).com ) 2000-04-10.jp ) 2001-11-20. Warwick Hunter ( whunter@agile.co. erhalten. Thomas Thai ( tom@minnesota.or. Jason Tishler ( jason@tishler.gov ) 2002-06-13.tv ) Bemerkungen benötigt neuen Semaphorcode keine neueren Berichte DG/UX 5. Dave Page ( dpage@vale-housing.fr) 2002-10-29.3 nativ nur clientseitig.1 1. Tatsuo Ishii ( t-ishii@sra.0 NetBSD Alpha 7.2 2.0 Mac 8xx NetBSD MIPS 7.uk ). siehe Dokumentation siehe Kapitel 15 Nicht unterstützte Plattformen: Die folgenden Plattformen funktionieren entweder dem letzten Kenntnisstand nach nicht.2 2.1.1.com) 2002-11-01. Alessio Bragadini ( alessio@albourne. 7. als diese Liste zusammengestellt wurde. Martin Renters ( martin@datafax. siehe doc/ FAQ_MSWIN Windows x86 7.3 mit Cygwin.11 Linux m88k 6.1.5W MkLinux DR1 PPC750 7. Henry B.4R4.0.3 7.net) 2002-11-05. Dave Page ( dpage@vale-housing.org ) 2001-11-15. Cobalt Qube2 7.com) 2002-11-05. Hisao Shibuya ( shibuya@alpha. siehe auch doc/ FAQ_Solaris siehe auch doc/FAQ_SCO Windows x86 7.2 2001-11-29.uk) Bemerkungen 5.3 2002-11-20.0) Olivier Prenant ( ohp@pyrenet. Brian E Gallew ( geek+@cmu. um Ihnen zu zeigen. oder sie funktionierten in einer früheren Version einmal und wir haben keine ausdrückliche Bestätigung eines erfolgreichen Tests mit Version zum Zeitpunkt.x.3 Larry Rosenman ( ler@lerctr.2.2 NetBSD m68k 7.

co. Tatsuo Ishii ( t-ishii@sra.Kovalenko@motorola.com. aber zu spät für 7.au ) 2001-03-30.2 2001-11-28.com ) 2001-12-04.com ) 1998-10-28. Bernd Tegge ( tegge@repas-aeg. Frank Ridderbusch ( ridderbusch. siehe auch doc/FAQ_QNX4 Patches im Archiv verfügbar.2.Installationsanweisungen Betriebssystem Prozessor Version Bericht NetBSD PPC 7.x TAS-Spinlockcode wird nicht entdeckt 235 . Igor Kovalenko ( Igor.1 6.jp ) 1998-03-01.de ) 2001-11-20. Matthew Green ( mrg@eterna.x Bitrot vermutet QNX 4 RTOS x86 7.1 1. Helbekkmo ( tih@kpnQwest.no ) 1998-03-01. Doug Winterburn ( dlw@seavme.xroads.pad@sni.de ) 2001-12-10.2 benötigt neuen Semaphorcode.2 QNX RTOS v6 x86 7.4 Ultrix Ultrix MIPS VAX 7. Bill Studenmund ( wrstuden@netbsd.1 benötigt neuen TASSpinlockcode keine neueren Berichte System V R4 MIPS 6. David Wetzel ( dave@turbocat. Tom I.2 32 und 64 Bits NetBSD VAX 7.5 NeXTSTEP x86 6.5 NetBSD Sparc 7.2 System V R4 m88k 6.de ) 2001-03-26 1998-03-01 Bemerkungen 1.2 SunOS 4 Sparc 7.org ) 2001-12-03.

Kapitel 14 236 .

lib Statische Version der Clientbibliothek bin\psql\Release\psql.dll. 237 .dll Die dynamisch linkbare Clientbibliothek interfaces\libpq\Release\libpqdll. um Ihre Programme mit libpq. Wenn diese Datei mit einem Setup-Programm installiert wird.dll linken zu können interfaces\libpq\Release\libpq. Die make-Steuerdateien in der Quellendistribution sind für Microsoft Visual C++ gedacht und funktionieren wahrscheinlich nicht mit anderen Systemen. Diese Datei sollte in den meisten Fällen im Verzeichnis WINNT\SYSTEM32 (oder WINDOWS\SYSTEM auf Windows 95/98/ME) abgelegt werden. wechseln Sie in das Verzeichnis src und geben Sie diesen Befehl ein: nmake /f win32. ist die Bibliothek libpq.exe Das interaktive Terminal von PostgreSQL Die einzige Datei.mak Hierbei wird davon ausgegangen.15 15 Installation auf Windows Trotzdem PostgreSQL für Unix-ähnliche Betriebssystem geschrieben wurde. die wirklich installiert werden muss. Tipp Wenn Sie Windows 98 oder neuer verwenden. was auf Windows möglich ist. zu bauen. Die folgenden Dateien werden gebaut werden: interfaces\libpq\Release\libpq. In diesem Fall finden Sie die Installationsanweisungen in Kapitel 14. dass Visual C++ in Ihrem Pfad zu finden ist. in anderen Fällen die Anwendungen von Hand zu kompilieren. Um alles. Es sollte aber möglich sein. dann sollte sie mit Versionsprüfung über die in der Datei enthaltene Ressource VERSIONINFO installiert werden.lib Importbibliothek. können die C-Clientbibliothek (libpq) und das interaktive Terminal (psql) als Windows-Anwendungen kompiliert werden. wenn Sie zuerst das Cygwin-Toolkit installieren. dann können Sie das gesamte PostgreSQL-Paket auf “Unix-Art” kompilieren und anwenden. damit eine neuere Version der Bibliothek nicht überschrieben wird.

Um die Bibliothek zu verwenden. müssen Sie die Verzeichnisse src\include und src\interfaces\libpq im Quellbaum zum Suchpfad für Headerdateien Ihres Compilers hinzufügen. (In Visual C++ rechtsklicken Sie einfach auf das Projekt und wählen Sie den Menüpunkt zum Hinzufügen aus.Kapitel 15 Wenn Sie Anwendung mit libpq auf diesem Rechner entwickeln wollen. müssen Sie die Datei libpqdll.lib Ihrem Projekt hinzufügen.) 238 .

Es gibt keine Voreinstellung.) Im Dateisystem ist ein Datenbankcluster ein einzelnes Verzeichnis. was passiert. 16. Um einen Datenbankcluster zu initialisie- 239 . aber es besteht dahingehend keinerlei Notwendigkeit. unter dem alle Daten gespeichert werden.1 Der PostgreSQL-Benutzerzugang Wie bei jedem Serverprogramm. Wir nennen das das Datenverzeichnis oder den Datenbereich. das mit der Welt verbunden ist. aber Stellen wie /usr/local/pgsql/ data oder /var/lib/pgsql/data werden häufig verwendet. weil ein kompromittiertes System dann seine eigenen Programmdateien verändern könnte. (SQL verwendet anstelle dessen den Begriff Katalogcluster. ist es auch bei PostgreSQL empfehlenswert.) Es ist nicht zu empfehlen. Es ist vollkommen Ihnen überlassen. auf die über einen einzigen laufenden Server zugegriffen werden kann.16 16 Laufzeitverhalten des Servers Dieses Kapitel bespricht. (Die Verwendung des Benutzers nobody wäre zum Beispiel keine gute Idee. Um einen Unix-Benutzerzugang in Ihrem System zu erzeugen. und welche Wechselwirkungen mit dem Betriebssystem dadurch entstehen.) Ein Datenbankcluster ist eine Sammlung von Datenbanken. die Programmdateien unter diesem Benutzerzugang zu installieren. wenn er läuft. (Informationen über die Erzeugung von Datenbanken finden Sie in Kapitel 18. sie sollte nicht für die eigentliche Arbeit verwendet werden. schauen Sie. Der Benutzername postgres wird oft verwendet. Nach der Initialisierung enthält ein Datenbankcluster eine Datenbank namens template1. Dieser Benutzerzugang sollte nur die vom Server verwalteten Daten besitzen und sollte nicht mit anderen Daemons geteilt werden. den Server unter einem getrennten Benutzerzugang laufen zu lassen. 16. müssen Sie einen Bereich zur Speicherung der Datenbank auf der Festplatte initialisieren. wo Sie Ihre Daten speichern. ob Sie einen Befehl useradd oder adduser haben. wie der Datenbankserver eingerichtet wird. Diese Datenbank wird als Vorlage (englisch template) für später erzeugte Datenbanken verwendet.2 Einen Datenbankcluster erzeugen Bevor Sie irgendetwas tun können. Wir nennen das einen Datenbankcluster.

um dem Datenbank-Superuser ein Passwort zuzuweisen. erlaubt die Voreinstellung der Clientauthentifizierung jedoch. This locale setting will prevent the use of indexes for pattern matching operations. Die in einem bestimmten Datenbankcluster verwendete Sortierreihenfolge wird von initdb festgesetzt und kann später nicht mehr verändert werden. dass jeder lokale Benutzer mit der Datenbank verbinden kann und sogar ein Superuser werden kann. Da das Datenverzeichnis alle in der Datenbank gespeicherten Daten enthält. (Weitere Möglichkeiten. initdb entzieht daher jedem. Dazu wird es wahrscheinlich nicht die Rechte haben (wenn Sie unserem Rat gefolgt sind und einen unprivilegierten Benutzer geschaffen haben).Kapitel 16 ren.1. wenn es so aussieht. empfehlen wir Ihnen. als wäre das Datenverzeichnis schon initialisiert worden. sind die Verwendung der Methode ident oder die Verwendung der Dateisystemzugriffsrechte. 240 . verwenden Sie den Befehl initdb. wird initdb versuchen. For more information see the Administrator's Guide. weitere Informationen dazu finden Sie in Abschnitt 20. es zu erzeugen. Wenn Sie Ihren lokalen Benutzern nicht vertrauen. die Zugriffsrechte für dieses Verzeichnis. ist es von äußerster Wichtigkeit. jetzt die richtige Wahl zu treffen.B. Während der Verzeichnisinhalt sicher ist. Siehe Kapitel 19 für weitere Informationen. Normalerweise nimmt es einfach die Locale-Ein- stellung aus der Umgebung und wendet Sie auf die initialisierte Datenbank an. Es ist auch möglich. dass es vor unerlaubtem Zugriff geschützt wird. So könnte man das anstellen: root# mkdir /usr/local/pgsql/data root# chown postgres /usr/local/pgsql/data root# su postgres postgres$ initdb -D /usr/local/pgsql/data initdb wird abbrechen. Verändern Sie nach initdb die Datei pg_hba. rerun initdb with the collation order set to "C". wenn Sie diesen Befehl ausführen. Eine kleine Überraschung während der Ausführung von initdb könnte eine Meldung wie diese sein: The database cluster will be initialized with locale de_DE. mit initdb --lc-collate=C. außer wenn Sie alle Daten sichern (mit pg_dump). Wenn Sie für solche Suchen eine guten Leistung haben wollen. Das gewünschte Verzeichnis für Ihr Datenbanksystem wird mit der Option -D angegeben. dass Sie die Option -W oder -pwprompt in initdb verwenden.) initdb stellt auch die Locale des Datenbankclusters ein. dass Sie mit dem im vorigen Abschnitt beschriebenen PostgreSQL-Benutzer angemeldet sein müssen. dann sollten Sie die aktuelle Locale auf C setzen und initdb noch einmal ausführen. Es ist also wichtig. z. Das soll Sie darauf hinweisen. initdb nochmal ausführen. If that is a concern. und dann alle Daten wiederherstellen. Wenn das von Ihnen angegebene Verzeichnis noch nicht existiert. außer dem PostgreSQL-Benutzer. In diesem Fall sollten Sie das Verzeichnis selbst erstellen (als root) und dann den PostgreSQL-Benutzer zum Eigentümer machen. dass die aktuell eingestellte Locale Indexe so sortiert. dass sie nicht für Suchen mit LIKE oder regulären Ausdrücken verwendet werden können. um Verbindungen zu beschränken. Tipp Als Alternative zu der Option -D können Sie die Umgebungsvariable PGDATA setzen.conf und stellen Sie die Authentifizierungsmethode auf md5 oder password anstelle von trust. welcher mit PostgreSQL installiert wird. zum Beispiel $ initdb -D /usr/local/pgsql/data Beachten Sie. eine andere Locale für die Datenbank anzugeben. bevor Sie den Server das erste Mal starten.

hängt stark vom Betriebssystem ab. Daher gibt es das Wrapperprogramm pg_ctl. die Option -i verwenden. Das wird mit der Option -D getan. wenn der Server TCP/IP-Verbindungen akzeptieren soll (anstatt nur Unix-Domain-Socket-Verbindungen). Viele Systeme haben eine Datei /etc/rc. Das Datenbankserverprogramm heißt postmaster. root-Zugang wird wahrscheinlich vonnöten sein. Verschiedene Systeme haben verschiedene Methoden. Die Shell-Syntax kann schnell ziemlich umständlich werden. die Umgebungsvariable PGDATA zu verwenden.3. wenn der Computer bootet.local oder /etc/rc. ❏ Für OpenBSD fügen Sie folgende Zeilen der Datei /etc/rc. den Server zu starten. Andere haben rc.3 Den Datenbankserver starten Bevor jemand auf die Datenbank zugreifen kann. (Eine gründlichere Besprechung der Verwaltung von Logdateien finden Sie in Abschnitt 21. Wenn die Option -D nicht angegeben wurde. Wenn das auch nicht funktioniert. das einige Aufgaben vereinfachen kann.Laufzeitverhalten des Servers 16. Zum Beispiel: su -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog' postgres Hier sind ein paar konkretere Vorschläge für verschiedene Betriebssysteme. Mit pg_ctl kann man den Server auch wieder anhalten. (Ersetzen Sie immer die richtigen Installationsverzeichnisse und Benutzernamen. Was auch immer Sie machen. ist also: $ postmaster -D /usr/local/pgsql/data Dadurch bleibt der Server im Vordergrund. then 241 .d/rc. verwenden Sie die übliche Shell-Syntax: $ postmaster -D /usr/local/pgsql/data > logdatei 2>&1 & Es ist wichtig. dann wird der Server versuchen. Daher sollten Ihre Befehle wahrscheinlich so etwas wie su -c '.' postgres enthalten.) Der postmaster hat auch eine Reihe von Kommandozeilenoptionen.local.4. Zum Beispiel: pg_ctl start -l logdatei Das startet den Server im Hintergrund und leitet die Ausgabe in die angegebene Logdatei um. die er verwenden soll.local an: if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postmaster ]. wo er die Daten finden soll. wird der Server nicht starten. Der postmaster muss wissen. Weitere Informationen darüber finden Sie auf der Referenzseite und unten in Abschnitt 16. Die Option -D hat hier die gleiche Bedeutung wie bei postmaster. müssen Sie den Datenbankserver starten. während Sie mit dem PostgreSQL-Benutzerzugang angemeldet sind. um Daemons beim Booten zu starten.. Das hilft bei der Kontrolle der Serveraktivität und um Probleme zu analysieren. Wie das gemacht wird. Um den postmaster im Hintergrund zu starten. Normalerweise wollen Sie es sicher so einrichten. Einige Autostartskripts finden Sie in der PostgreSQL-Distribution im Verzeichnis contrib/start-scripts.) ❏ Für FreeBSD schauen Sie in die Datei contrib/start-scripts/freebsd in der PostgreSQL-Distribution.d-Verzeichnisse. der Server muss vom PostgreSQL-Benutzerzugang gestartet werden und nicht als root oder ein anderer Benutzer. Die einfachste Art. sowohl stdout als auch stderr vom Server irgendwo hinzuleiten.. Diesen Befehl müssen Sie ausführen. wie hier gezeigt. Insbesondere müssen Sie. dass der Datenbankserver gestartet wird.

Wenn die Fehlermeldung des Kernels jedoch nicht Address already in use oder etwas Ähnliches ist. um den postmaster zu beenden. dass die Kernelgrenze für Shared Memory kleiner ist als der Pufferbereich. je nach Geschmack.d/postgresql mit der folgenden Zeile: su . Während der postmaster läuft. Eine Meldung wie IpcMemoryCreate: shmget(key=5440001. ❏ Für Solaris erzeugen Sie eine Datei namens /etc/init. wait a few seconds an retry.1 Fehler beim Starten des Servers Es gibt einige häufige Gründe. könnte man Folgendes sehen: $ postmaster -i -p 666 FATAL: StreamServerPort: bind() failed: Permission denied Is another postmaster already running on port 666? If not. 01600) failed: Invalid argument FATAL 1: ShmemCreate: cannot create region bedeutet wahrscheinlich. Das bedeutet in der Regel genau das.d/rc. ❏ Für NetBSD verwenden Sie entweder das Startskript von FreeBSD oder das von Linux.pid im Datenverzeichnis gespeichert. um zu verhindern. warum der Server einmal nicht starten könnte. dass Ihr Kernel System-V Shared Memory gar nicht unterstützt.local ein oder schauen Sie in die Datei contrib/start-scripts/linux in der PostgreSQL-Distribution. könnte es ein anderes Problem sein. wo schon einer läuft. dass mehrere postmaster-Prozesse im selben Datenverzeichnis laufen. Als vorübergehenden Ausweg können Sie den Server mit 242 .3.-c '/usr/local/pgsql/bin/pg_ctl start -l /var/postgresql/log -s' postgres echo -n ' postgresql' fi ❏ Für Linux-Systeme fügen Sie entweder /usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data in /etc/rc. Unten gehen wir auf einige der häufigsten Fehlermeldungen etwas genauer ein. 16. Oder es kann andeuten. was es aussagt: Sie haben versucht. Diese Datei wird verwendet. Prüfen Sie die Serverlogdatei oder starten Sie ihn von Hand (ohne die Ausgabeströme umzuleiten) und sehen Sie. welche Fehlermeldungen ausgegeben werden. Wenn man zum Beispiel den postmaster an einer reservierten Portnummer laufen lassen will.Kapitel 16 su . den PostgreSQL anlegen wollte (in diesem Beispiel 83918612 Bytes). ist seine PID in der Datei postmaster. size=83918612.postgres -c "/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/ pgsql/data" ❏ Dann erzeugen Sie in /etc/rc3.d einen symbolischen Link dahin als S99postgresql. und kann auch dazu verwendet werden. FATAL: StreamServerPort: bind() failed: Address already in use Is another postmaster already running on port 5432? If not. einen postmaster an einem Port zu starten. wait a few seconds an retry.

die PostgreSQL erzeugen will.s. zu vergessen. Sie könnten diese Mitteilung auch sehen. 243 .4 gezeigt wird.1. dass Connection refused in diesem Zusammenhang nicht bedeutet. Einzelheiten über die Konfiguration von System V IPC finden Sie in Abschnitt 16. dann ist es wahrscheinlich so. Früher oder später werden Sie Ihren Kernel aber umkonfigurieren müssen. wie in Abschnitt 19. psql: could not connect to server: Connection refused Is the server running on host server. Fehlerumstände außer den hier gezeigten werden bei der entsprechenden Anwendung beschrieben. Wenn da wirklich kein Server läuft. In diesem Fall ist es Ihre einzige Möglichkeit. dass Sie keinen Platz mehr auf der Festplatte haben. aber früher oder später sollten Sie Ihren Kernel umkonfigurieren.5. 01600) failed: No space left on device bedeutet nicht. indem Sie die den Server mit einer verkleinerten Anzahl an erlaubten Verbindungen (Option -N) starten.” So wie hier sieht es aus.2 Probleme bei Client-Verbindungen Obwohl die möglichen Fehler auf der Clientseite sehr verschieden sind und von der Anwendung abhängen. den Kernel umzukonfigurieren und diese Einrichtungen einzuschalten.3. wenn eine TCP/IP-Verbindung versucht wurde. wenn Sie mehrere Server auf derselben Maschine starten und diese zusammen die Kernelbeschränkungen ausreizen. wie gezeigt.2.Laufzeitverhalten des Servers weniger Puffern als normal starten (Option -B). die besagt: “Ich konnte keinen Server finden. Ein häufiger Fehler ist es. dann würden Sie dies sehen: psql: could not connect to server: Connection refused Is the server running locally and accepting connections on Unix domain socket "/tmp/. wie zum Beispiel das Fehlen einer Netzwerkverbindung.5432"? Die letzte Zeile ist nützlich. um zu überprüfen. Ein Fehler wie IpcSemaphoreCreate: semget(key=5440026. wird die Fehlermeldung des Kernels entweder Connection refused oder No such file or directory sein.) Andere Fehlermeldungen wie Connection timed out zeigen womöglich grundlegendere Probleme an. num=16. dass er TCP/IP-Verbindungen annehmen kann. 16. In dem Fall sieht die Fehlermeldung anders aus. den Server so zu konfigurieren. ob der Client auch mit der richtigen Stelle verbinden will.PGSQL. (Wichtig ist. dass der Server Ihre Verbindungsanfrage erhalten hat und sie abgelehnt hat. wie der Server gestartet wurde.joe. Er bedeutet.com and accepting TCP/IP connections on port 5432? Das ist die allgemeine Fehlermeldung. dass Ihr Kernel Shared Memory oder Semaphore gar nicht unterstützt. um die Shared-Memory-Größe zu erhöhen. stehen einige davon doch direkt damit in Verbindung. dass die Kernelgrenze für die Anzahl von System-V-Semaphoren kleiner ist als die Zahl. Wenn Sie eine Verbindung zu einem lokalen Server über Unix-Domain-Sockets versuchen. Wenn die Fehlermeldung illegal system call erwähnt. Wie oben können Sie dieses Problem eventuell umgehen.

log_connections = yes syslog = 2 search_path = '$user. Einige Optionen können in einzelnen SQL-Sitzungen mit dem Befehl SET geändert werden. Die Konfigurationsdatei wird neu gelesen. Benutzerspezifische Einstellungen haben wiederum noch höheren Vorrang. Parameterwerte. Kommentare können an jeder Stelle mit # anfangen. ALTER USER werden verwendet. Leerzeichen können frei verwendet werden und leere Zeilen werden ignoriert. Alternativ können Sie das Signal auch direkt an einen einzelnen Serverprozess schicken. zum Beispiel: postmaster -c log_connections=yes -c syslog=2 Kommandozeilenoptionen heben etwaige widersprüchliche Einstellungen in postgresql. diese Konfigurationsparameter zu setzen. die feststehen. Manchmal kann es auch nützlich sein. (Ein Beispieldatei mit Voreinstellungen wird dort installiert. um diese Einstellungen vorzunehmen. die sich auf das Verhalten des Datenbanksystems auswirken. dass das nicht für Optionen funktioniert. wenn der postmaster-Prozess das Signal SIGHUP erhält (was man am einfachsten mit pg_ctl reload auslösen kann). (Die Groß-/Kleinschreibung ist egal. Solche datenbankspezifischen Einstellungen haben Vorrang vor Einstellungen von der postmaster-Kommandozeile und der Konfigurationsdatei. Jeder Parameter hat einen der folgenden Datentypen: Boolean (an/aus). Dazu kann die Umgebungsvariable PGOPTIONS auf der Clientseite verwendet werden: env PGOPTIONS='-c geqo=off' psql (Das funktioniert bei jeder Clientanwendung auf libpq-Basis. Immer wenn eine Sitzung gestartet wird. steht eine Option pro Zeile. und die folgenden Unterabschnitte beschreiben jeden Parameter im Einzelnen. FALSE.Kapitel 16 16. wie sie gesetzt werden. damit alle aktiven Sitzungen den neuen Wert erhalten. YES. 1 für “an” sowie OFF. Boolean-Werte sind ON. sollten zwischen Apostrophen stehen. nicht nur bei psql. wie zum Beispiel die Portnummer. Einzelheiten zur Syntax finden Sie in der SQL-Befehlsreferenz. ganze Zahl. Optionseinstellungen für einzelne Benutzer oder Datenbanken zu machen.) Eine Möglichkeit. diese Optionen zu setzen. 0 für “aus” oder ein eindeutiger Präfix von einem dieser Werte. 244 . Fließkommazahl oder Zeichenkette. wenn der Server gestartet wird.4 Laufzeit-Konfiguration Es gibt eine ganze Reihe von Konfigurationsparametern. Das Gleichheitszeichen zwischen Name und Wert kann weggelassen werden.und Kleinschreibung keine Rolle. eine Kommandozeilenoption nur für eine bestimmte Sitzung zu verwenden. Die zweite Möglichkeit.conf im Datenverzeichnis zu bearbeiten.) Ein einfaches Beispiel einer solchen Datei wäre: # Das ist ein Kommentar. die keine einfachen Bezeichner sind. zum Beispiel: SET enable_seqscan TO off. Bei den Namen der Parameter spielt die Groß. werden die Voreinstellungen für den betroffenen Benutzer und die Datenbank geladen. ist die Datei postgresql. ist. Die Befehle ALTER DATABASE bzw.conf auf. Hier beschreiben wir. public' Wie Sie sehen.) Beachten Sie aber. sie als Kommandozeilenoptionen beim Aufruf von postmaster anzugeben. TRUE. Der postmaster-Prozess schickt dieses Signal dann auch an alle Serverkindprozesse weiter. Außerdem ist es möglich. NO.

Größere Werte führen dazu. Ein UPDATE in pg_settings ist gleichbedeutend mit der Ausführung des Befehls SET für den benannten Parameter.4. Name name setting Datentyp text text Beschreibung der Name des Konfigurationsparameters der aktuelle Wert des Konfigurationsparameters Tabelle 16. Sie enthält eine Zeile für jeden Parameter und die in Tabelle 16. Die Voreinstellung ist an. EFFECTIVE_CACHE_SIZE (Fließkommazahl) Setzt die Annahme des Planers über die effektive Größe des Diskcaches (das heißt des Teils des Diskcaches vom Kernel.1 Planer. Diese Option kann zum Debuggen des Anfrageplaners verwendet werden. Wenn die umgebende Transaktion erfolgreich abgeschlossen wird.oder SET-Befehl die Einstellung wieder ändert. CPU_TUPLE_COST (Fließkommazahl) Setzt den vom Anfrageplaner geschätzten Aufwand. Wenn ein UPDATE in einer Transaktion ausgeführt wird. dass ANALYZE länger dauert. CPU_OPERATOR_COST (Fließkommazahl) Setzt den vom Anfrageplaner geschätzten Aufwand. Die Voreinstellung ist an. bei denen das Statistikziel nicht mit ALTER TABLE SET STATISTICS geändert wurde. Diese Form ermöglicht es Ihnen. welche normalerweise 8 kB groß sind. Das wird relativ zum Aufwand eines sequenziellen Zeilenlesevorgangs gemessen. Diese Option kann zum Debuggen des Anfrageplaners verwendet werden.und Optimierereinstellungen CPU_INDEX_TUPLE_COST (Fließkommazahl) Setzt den vom Anfrageplaner geschätzten Aufwand. um einen Operator in einer WHERE-Klausel zu verarbeiten. um ein Tupel während einer Anfrage zu verarbeiten. Die Voreinstellung ist an. außer wenn ein weiterer UPDATE. DEFAULT_STATISTICS_TARGET (ganze Zahl) Setzt das voreingestellte Statistikziel für Tabellenspalten.1 gezeigten Spalten. Das wird relativ zum Aufwand eines sequenziellen Zeilenlesevorgangs gemessen. die Konfigurationsdaten mit anderen Tabellen zu verbinden und Auswahlkriterien anzuwenden.Laufzeitverhalten des Servers Die virtuelle Tabelle pg_settings ermöglicht das Anzeigen und Aktualisieren von Konfigurationsparametern. ENABLE_HASHJOIN (Boolean) Schaltet die Verwendung des Plantyps Hash-Verbund im Planer an oder aus. ENABLE_INDEXSCAN (Boolean) Schaltet die Verwendung des Indexscan-Plantyps im Planer ein oder aus. dann bleiben die Auswirkungen bis zum Ende der Sitzung bestehen. 245 . wird die Einstellung zurückgenommen. Das wird relativ zum Aufwand eines sequenziellen Zeilenlesevorgangs gemessen. um ein Indextupel während eines Indexscans zu verarbeiten. ENABLE_MERGEJOIN (Boolean) Schaltet die Verwendung des Plantyps Merge-Verbund im Planer an oder aus. der für die Datendateien von PostgreSQL verwendet wird). die später zurückgerollt wird. wenn die Tranaktion zurückgerollt wird. Die Veränderung gilt nur für die aktuelle Sitzung. Diese Option kann zum Debuggen des Anfrageplaners verwendet werden. Das wird in Diskseiten gemessen. aber können auch zu besseren Planerschätzungen beitragen.1: pg_settings Spalten 16.

ein Algorithmus. GEQO_THRESHOLD (ganze Zahl) GEQO_POOL_SIZE ist die Anzahl der Individien in der Bevölkerung. ENABLE_SORT (Boolean) Schaltet die Verwendung von ausdrücklichen Sortierschritten im Planer an oder aus. Wenn es 0 ist (Voreinstellung). Letzterer ist die Voreinstellung. wenn andere Methoden zur Verfügung stehen.) Die Voreinstellung ist 11. GEQO_RANDOM_SEED kann gesetzt werden. GEQO (Boolean) Schaltet genetische Anfrageoptimierung (genetic query optimization). deterministischen Planer zu verwenden. Man kann Nested-Loop-Verbunde nicht vollständig unterdrücken. Gültige Werte sind zwischen 1 und 80. GEQO_GENERATIONS ist die Anzahl der Iterationen des Algorithmus. Die Voreinstellung ist an. Siehe auch bei den verschiedenen anderen GEQO_-Einstellungen. Diese Option kann zum Debuggen des Anfrageplaners verwendet werden. GEQO_SELECTION_BIAS (Fließkommazahl) Verschiedene Einstellungen für den genetischen Anfrageoptimierungsalgorithmus: 128 und 1024. einen zu verwenden. dann wird Effort * Log2(PoolSize) verwendet. wenn eine Anfrage mindestens so viele Elemente in der FROM-Liste hat. dann hält das den Planer davon ab. wobei 40 die Voreinstellung ist. wobei QS die Anzahl der FROM-Elemente in der Anfrage ist. ENABLE_TIDSCAN (Boolean) Schaltet die Verwendung des TID-Scan-Plantyps im Planer an oder aus. einen zu verwenden. aber wenn man diese Variable ausschaltet. (Eine JOIN-Konstruktion zählt als nur ein Element. aber wenn man diese Variable ausschaltet.00 gehen. aber wenn man diese Variable ausschaltet. den normalen. Diese Option kann zum Debuggen des Anfrageplaners verwendet werden. GEQO_RANDOM_SEED (ganze Zahl). Die Voreinstellung ist an. um vom Algorithmus wiederholbare Ergebnisse zu erhalten.Kapitel 16 ENABLE_NESTLOOP (Boolean) Schaltet die Verwendung des Plantyps Nested-Loop-Verbund im Planer an oder aus. GEQO_EFFORT (ganze Zahl). wie sehr der Optimierer versuchen wird. Man kann ausdrückliche Sortierschritte nicht vollständig unterdrücken. Die Zahl muss eine positive ganze Zahl sein.50 bis 2. an oder aus. ENABLE_SEQSCAN (Boolean) Schaltet die Verwendung von sequenziellen Scans im Planer ein oder aus. wenn andere Methoden zur Verfügung stehen. GEQO_POOL_SIZE (ganze Zahl). dann wird 2QS+1 verwendet. FROM-Elemente mit Unteranfragen mit der übergeordneten Anfrage zusammenzuführen. dann verhält sich der Algorithmus nicht deterministisch. Für einfachere Anfragen ist es normalerweise besser. wenn andere Methoden zur Verfügung stehen. hält das den Planer davon ab. Die Voreinstellung ist an. Die Voreinstellung ist an. Dieser Parameter kontrolliert auch. Man kann sequenzielle Scans nicht vollständig unterdrücken. GEQO_EFFORT wird verwendet. um für GEQO_GENERATIONS einen Vorgabewert zu errechnen. 246 . GEQO_SELECTION_BIAS ist der Auswahldruck in der Bevölkerung. der versucht. Diese Option kann zum Debuggen des Anfrageplaners verwendet werden. einen zu verwenden. Gültige Werte sind zwischen Gibt an. dass genetische Anfrageoptimierung verwendet werden soll. Die Laufzeit des Algorithmus ist in etwa proportional zur Summe von GEQO_POOL_SIZE und GEQO_GENERATIONS. Diese Option kann zum Debuggen des Anfrageplaners verwendet werden. Anfragen ohne erschöpfende Suchen zu planen. Wenn der Wert -1 ist. Werte können von 1. Die Voreinstellung ist an. Wenn 0 angeben wird. GEQO_GENERATIONS (ganze Zahl). hält das den Planer davon ab.

Beachten Sie. Das ist eine Debug-Hilfe. das Ergebnis des Umschreibers oder der Ausführungsplan ausgegeben. 247 . Diese Option kann nur beim Start des Servers gesetzt werden. dass LOG hier anders eingeordnet ist als bei SERVER_MIN_MESSAGES. welche Meldungstypen an den Client geschickt werden.conf eingestellt werden. DEBUG4. Die Voreinstellung ist NOTICE. Anmerkung Leider gibt es für die Familie der eben beschriebenen COST-Variablen keine richtig gute Methode. Um diese Option benutzen zu können. Für jede ausgeführte Anfrage wird entweder der resultierende Parsebaum. DEBUG_PRETTY_PRINT (Boolean) Diese Optionen sorgen dafür. ist aber wahrscheinlich sehr nützlich. DEBUG_ASSERTIONS (Boolean) Schaltet diverse Assertion-Prüfungen ein. Jeder Typ schließt alle ihm folgenden Typen mit ein. NOTICE. um besser lesbar. wie Ihr DNS eingerichtet ist. dass. Wir ermutigen Sie. Diese Option kann nur beim Start des Servers oder in der Datei postgresql. um ideale Werte zu ermitteln. aber je nachdem. Wenn sonderbare Probleme auftreten oder der Server abstürzt.und Debug-Ausgabe CLIENT_MIN_MESSAGES (Zeichenkette) Kontrolliert. DEBUG2.Laufzeitverhalten des Servers RANDOM_PAGE_COST (Fließkommazahl) Setzt den vom Anfrageplaner geschätzten Aufwand. um eine Diskseite außer der Reihe von der Festplatte zu lesen. Wenn Sie den Hostnamen auch anzeigen wollen.2 Log. Das wird relativ zum Aufwand eines sequenziellen Zeilenlesevorgangs gemessen. WARNING und ERROR. Beachten Sie. dass bestimmte Debug-Ausgaben an den Serverlog geschickt werden. Das ist in der Voreinstellung aus. LOG. können Sie diese Option anschalten. ob EXPLAIN VERBOSE das eingerückte oder das nicht eingerückte Format zur Ausgabe der Anfragebäume verwendet. EXPLAIN_PRETTY_PRINT (Boolean) Bestimmt. DEBUG_PRINT_PARSE (Boolean). LOG_CONNECTIONS (Boolean) Schreibt für jede erfolgreiche Verbindung eine Zeile mit Einzelheiten in den Serverlog. Sehen Sie auch dort nach. wenn PostgreSQL damit kompiliert wurde. weil dadurch Programmierfehler entlarvt werden könnten. muss das Makro USE_ASSERT_CHECKING bei der Compilierung definiert sein (am besten durch configure -enable-cassert erreicht). Durch DEBUG_PRETTY_PRINT wird die Ausgabe eingerückt. DEBUG_PRINT_PLAN (Boolean). 16. desto weniger Meldungen werden gesendet werden. aber auch wesentlich länger zu sein. HOSTNAME_LOOKUP (Boolean) In der Voreinstellung zeigen die Verbindungslogs nur die IP-Adressen der Clienthosts. diese Option in der Voreinstellung an ist. DEBUG3. DEBUG_PRINT_REWRITTEN (Boolean). DEBUG1. dann können Sie diese Option anschalten. um eine Beschreibung der verschiedenen Werte zu erhalten. zu experimentieren und Ihre Ergebnisse mit anderen zu teilen. Je weiter hinten der Typ steht. Gültige Werte sind DEBUG5. kann das die Leistung nicht unerheblich beeinträchtigen.4.

Kapitel 16 LOG_DURATION (Boolean) Wenn an. WARNING. LOG_PID (Boolean) Schreibt vor jede Meldung im Serverlog die Prozess-ID des Serverprozesses.B. da dort die Prozess-ID immer enthalten ist. NOTICE. der diese Meldung verursacht hat. INFO Enthält Informationen. Gültige Werte sind DEBUG5. dann wird die Dauer jedes abgeschlossenen Befehls geloggt. dann werden alle SQL-Befehle.B. LOG_PID anzuschalten. Wir empfehlen Ihnen außerdem. LOG Enthält Informationen für Administratoren. DEBUG4. FATAL oder PANIC erzeugen.B. desto weniger Meldungen werden in den Log geschrieben werden. Wenn Sie die Option zum Beispiel auf ERROR setzen. DEBUG2. Das ist nützlich. SERVER_MIN_MESSAGES (Zeichenkette) Kontrolliert. ERROR Berichtet einen Fehler. LOG. die mit Syslog geloggt werden. LOG_MIN_ERROR_STATEMENT (Zeichenkette) Kontrolliert. DEBUG1. z. Wenn Sie diese Option verwenden. DEBUG1. 248 . z. Die Voreinstellung ist NOTICE. im Serverlog aufgezeichnet wird. der den Abbruch der aktuellen Transaktion verursachte. Die Voreinstellung ist aus.B bei VACUUM VERBOSE. das Abschneiden langer Namen oder die Erzeugung eines Indexes als Teil eines Primärschlüssels. DEBUG3. Jeder Typ schließt alle ihm folgenden Typen mit ein. sollten Sie auch LOG_STATEMENT und LOG_PID anschalten. Dieser Parameter hat keine Auswirkung auf Meldungen. WARNING Enthält Warnhinweise für den Benutzer. die eine Meldung des gesetzten Typs oder höher verursachen. LOG_TIMESTAMP (Boolean) Schreibt vor jede Serverlogmeldung die aktuelle Zeit. werden geloggt. geloggt. dass LOG hier anders eingeordnet ist als bei CLIENT_MIN_MESSAGES. NOTICE. LOG_STATEMENT (Boolean) Schreibt jeden SQL-Befehl in den Serverlog. welche Meldungstypen in den Serverlog geschrieben werden. Hier ist eine Liste der verschiedenen Meldungstypen: DEBUG[1-5] Enthält Informationen für Entwickler. damit Sie den fehlerhaften Befehl und die Fehlermeldung leichter in Verbindung bringen können. FATAL und PANIC. welche Meldungen zu welcher Verbindung gehören. damit Sie die Befehle und die Dauer über die Prozess-ID in Verbindung setzen können. die Meldungen der Typen ERROR. FATAL und PANIC. Die Voreinstellung ist PANIC (wodurch diese Funktion im Prinzip ausgeschaltet wird). INFO. Gültige Werte sind DEBUG5. für welche Meldungstypen der SQL-Befehl. WARNING. Alle Befehle. DEBUG3. COMMIT außerhalb eines Transaktionsblocks. DEBUG2. die implizit vom Benutzer angefordert wurden. Beachten Sie. Je weiter hinten der Typ steht. INFO. Die Voreinstellung ist aus. die für Benutzer hilfreich sein könnten. um herauszufinden. NOTICE Enthält Informationen. ERROR. z. z. DEBUG4. ERROR. über Checkpoint-Aktivität.

SHOW_STATEMENT_STATS (Boolean). Wenn diese Option 1 ist. kann aber ausgeschaltet werden. Sie könnten diese Portnummer zurückverfolgen. werden die Statistiken nach einem Neustart weitergezählt. werden die gesammelten Statistiken zurückgesetzt.) Die Voreinstellung ist 0. Ansonsten ist diese Option ziemlich nutzlos und daher in der Voreinstellung aus. Die Voreinstellung ist aus. wenn mit Syslog geloggt wird. Die Einstellung 2 schickt die Ausgabe nur an Syslog. um herauszufinden. SYSLOG_FACILITY (Zeichenkette) Diese Option bestimmt die Syslog-“Facility”. In der Voreinstellung sind alle aus. womit Syslog aus ist. Diese Option kann nur beim Start des Servers eingestellt werden. Diese Option kann nur beim Start des Servers eingestellt werden. 249 . ob der Server den Statistikkollektor-Subprozess starten soll. kostet sie pro Anfrage ein wenig Zeit. STATS_COMMAND_STRING (Boolean). SHOW_SOURCE_PORT (Boolean) Zeigt die Nummer des ausgehenden Ports auf dem verbundenen Client in den Verbindungslogmeldungen. LOCAL3. PANIC Berichtet einen Fehler. die verwendet wird. LOCAL1. STATS_START_COLLECTOR (Boolean) Kontrolliert. Statistiken über Aktivitäten auf Blockebene oder Statistiken über Aktivitäten auf Zeilenebene. wenn Sie kein Interesse an Statistiken haben. sie ist aber unschätzbar zum Debuggen und um Feinabstimmungen zur Leistungsverbesserung vornehmen zu können. LOCAL5. Eine Erklärung dazu finden Sie in der Anleitung von Syslog auf Ihrem System. LOCAL2. SYSLOG (ganze Zahl) PostgreSQL kann Syslog zum Loggen verwenden. STATS_BLOCK_LEVEL (Boolean). welcher Benutzer die Verbindung eingeleitet hat. Diese Option kann nur beim Start des Servers eingestellt werden. Wenn die Sammlung der Statistiken eingeschaltet ist. Diese Option kann nur beim Start des Servers eingestellt werden. LOCAL7. wenn der Server neu gestartet wird. LOCAL4. STATS_RESET_ON_SERVER_START (Boolean) Wenn an. Zus Auswahl stehen LOCAL0. SHOW_PLANNER_STATS (Boolean). SHOW_PARSER_STATS (Boolean). LOCAL6. SHOW_EXECUTOR_STATS (Boolean) Schreibt für jede Anfrage Leistungsstatistiken des entsprechenden Moduls in den Serverlog. die Voreinstellung ist LOCAL0. welche Informationen an den Statistikkollektor gesendet werden: aktueller Befehl.Laufzeitverhalten des Servers FATAL Berichtet einen Fehler. der den Abbruch der aktuellen Sitzung verursachte. Das ist in der Voreinstellung angeschaltet. der den Abbruch aller Sitzungen verursachte. Das ist ein grobes Profiling-Instrument. (Einige Meldungen gehen aber trotzdem an die Standardausgabe oder die Standardfehlerausgabe. gehen Meldungen an Syslog und die Standardausgabe. STATS_ROW_LEVEL (Boolean) Diese Optionen bestimmen. Wenn aus.

sie laufen in ihren eigenen Transaktionen. Das verhindert. DATESTYLE (Zeichenkette) Setzt das Ausgabeformat für Datums.oder RESET-Befehle sind Teil des Transaktionsblocks. bestimmt diese Option den Programmnamen. den Zeichensatz der Datenbank zu verwenden. Einzelheiten finden Sie in Abschnitt 8. Wenn ein potenzieller Client die Authentifizierung nicht in dieser Zeit abgeschlossen hat. SHOW. CLIENT_ENCODING (Zeichenkette) Setzt den auf dem Client verwendeten Zeichensatz. Anmerkung Selbst wenn autocommit falsch ist. testen Sie sorgfältig. Es ist ein neues Feature. um PostgreSQL-Meldungen in den Syslog-Meldungen zu identifizieren. Die Voreinstellung ist. Die Voreinstellung ist wahr. US. dass festgefahrene Clients eine Verbindung endlos besetzen können. der nicht in einem ausdrücklichen Transaktionsblock ist (das heißt. SHOW oder RESET am Anfang eines Transaktionsblocks auszuführen. automatisch ein COMMIT ausführen. verwenden Sie zuerst BEGIN. wenn ein Befehl empfangen wird. der verwendet wird. Man kann sich diesen Modus auch so vorstellen. das noch nicht von allen Clientanwendungen und -bibliotheken unterstützt wird. wird durch SET. setzen Sie die Option auf falsch. Diese Option kann nur beim Start des Servers oder in der Datei postgresql. Die Voreinstellung ist falsch. Bevor Sie es in Ihrer Installation zur Voreinstellung machen. um mit dem bisherigen Verhalten von PostgreSQL kompatibel zu sein. EST und SAT als australische Zeitzonen anstatt amerikanische Zeitzonen bzw. Wenn erst ein anderer Befehl ausgeführt wird.3 wird autocommit auf falsch zu setzen noch nicht sehr gut unterstützt. wird PostgreSQL nach jedem erfolgreichen Befehl.und Zeitangaben sowie die Regeln um zweideutige Datumseingaben zu interpretieren. Um jedoch zu sehr wie möglich mit dem SQL-Standard kompatibel zu sein. der nicht schon in einem Transaktionsblock ist. 16. dann werden ACST. “Samstag” interpretiert. Die Voreinstellung ist postgres. AUSTRALIAN_TIMEZONES (Boolean) Wenn wahr.Kapitel 16 SYSLOG_IDENT (Zeichenkette) Wenn Loggen mit Syslog an ist. bricht der Server die Verbindung ab. das heißt.4. dass implizit ein BEGIN ausgeführt wird. dann schließt PostgreSQL Transaktionen nur dann ab. 250 . fängt ein Transaktionsblock an und etwaige folgende SET-. um die Clientauthentifizierung abzuschließen. sie könnten eventuell zurückgerollt werden. Die Voreinstellung ist ISO. in Sekunden. SHOW und RESET kein neuer Transaktionsblock gestartet.3 Allgemeine Operation AUTOCOMMIT (Boolean) Wenn auf wahr gesetzt. wenn ein COMMIT ausdrücklich ausgeführt wird. Wenn auf falsch gesetzt. ein BEGIN ohne zugehöriges COMMIT wurde ausgeführt). wenn folgende Befehle Fehler verursachen. CST. Anmerkung In PostgreSQL 7. AUTHENTICATION_TIMEOUT (ganze Zahl) Maximale Zeit.conf eingestellt werden.5. TRACE_NOTIFY (Boolean) Erzeugt eine Menge Debug-Ausgaben für die Befehle LISTEN und NOTIFY. Um SET.

251 . Anmerkung Dieses Feature ist als vorübergehende Maßnahme gedacht. Das @ wird entfernt. dann werden Sie den Benutzernamen in Anführungszeichen stellen müssen. sein. ehe die wartende Sitzung auf Verklemmung prüft. Wenn ein verbindender Client benutzername übergibt. Wenn der Wert eine leere Zeichenkette ist. In diesem Verzeichnis sind die in der PostgreSQL-Distribution enthaltenen ladbaren Module installiert. bis eine komplette Lösung gefunden wird.Laufzeitverhalten des Servers DB_USER_NAMESPACE (Boolean) Hierdurch werden datenbank-lokale Benutzernamen ermöglicht. wenn Sie den Benutzernamen im Client angeben. DEFAULT_TRANSACTION_ISOLATION (Zeichenkette) Jede SQL-Transaktion hat einen Isolationsgrad. sollten Sie Ihre Benutzer als benutzername@dbname erzeugen. durchführen. wird die automatische Pfadsuche abgestellt. Diese Option wird dann entfernt werden. wird @ und der Datenbankname angehängt und dieser datenbankspezifische Benutzername vom Server verwendet. Die Voreinstellung ist read committed. Hängen Sie einfach @ an den Namen an. den man in der Praxis verwenden sollte. Beachten Sie: Wenn Sie in der SQL-Umgebung Benutzernamen mit @ erzeugen. der entweder read committed oder serializable ist. DYNAMIC_LIBRARY_PATH (Zeichenkette) Wenn ein dynamisch ladbares Modul geöffnet werden muss und der angegebene Name keine Verzeichniskomponente hat (das heißt er enthält keinen Schrägstrich). Dieser Parameter kontrolliert den Isolationsgrad. sucht das System im DYNAMIC_LIBRARY_PATH-Pfad nach der angegebenen Datei. der in CREATE FUNCTION or LOAD angegeben wurde. (Verwenden Sie pg_config --pkglibdir. und warten einfach ein bisschen auf die Sperre. ob eine Verklemmung vorliegt.) Zum Beispiel: dynamic_library_path = '/usr/local/lib/postgresql:/home/mein_projekt/ lib:$libdir' Der voreingestellte Wert für diesen Parameter ist '$libdir'. Wir nehmen (optimistischerweise?) an. Idealerweise sollte dieser Wert höher sein als die Dauer einer typischen Transaktion. um den Namen dieses Verzeichnisses auszugeben.h. Diese Option kann nur beim Start des Servers eingestellt werden. DEADLOCK_TIMEOUT (ganze Zahl) Dies ist die Zeit. Die Voreinstellung ist aus. können Sie immer noch normale globale Benutzer erzeugen. getrennt durch Doppelpunkte. Wenn diese Option an ist. und daher möchte der Server sie nicht jedes Mal. die auf eine Sperre gewartet wird. mit dem jede neue Transaktion anfängt. bevor der Server den Benutzernamen weiterverwendet. aber es dauert länger. (Der betrachtete Name ist der Name. was wahrscheinlich in etwa der niedrigste Wert ist. Wenn ein Verzeichnisname mit dem besonderen Wert $libdir anfängt. Die Voreinstellung ist 1000 (d. in Millisekunden. wird dafür der eingebaute Name des Verzeichnisses für PostgreSQL-Pakete eingesetzt. bis geprüft wird. verringert sich die Zeit. Wenn die Option an ist. damit die Chancen besser stehen.) Der Wert von DYNAMIC_LIBRARY_PATH muss eine Liste von absoluten Verzeichnisnamen. dass eine Sperre aufgegeben wird. bis eine wirkliche Verklemmung erkannt wird. dass Verklemmungen in normalen Anwendungen nicht häufig vorkommen. Weitere Informationen finden Sie in Kapitel 12 und auf Seite 776. ehe wir die Verklemmungsprüfung starten. die in nutzlosen Verklemmungsprüfungen verwendet wird. Wenn dieser Wert erhöht wird. DieÜberprüfung auf Verklemmungen ist relativ langsam. Auf einem stark belasteten Server könnten Sie eine Erhöhung in Erwägung ziehen. eine Sekunde). wenn er auf eine Sperre wartet.

diesen Parameter in der Konfigurationsdatei postgresql. wird der Wert auf eine systemabhängige Weise aus der Umgebung des Servers ermittelt. die Schreibvorgänge durch Zwischenspeichern. siehe Abschnitt 20. dass das Betriebssystem den Write-Ahead-Log auf die Festplatte zurückschreibt. siehe Abschnitt 20. Man kann die Variable trotzdem setzen. Empfohlen wird. Wenn Sie früher fsync aus Leistungsgründen ausgeschaltet haben. verwendet der PostgreSQL-Server an mehreren Stellen den Systemaufruf fsync() um sicherzustellen. Wenn 252 . LC_NUMERIC (Zeichenkette) Setzt die Locale zur Formatierung von Zahlen. zum Beispiel mit der Familie der to_charFunktionen. Wenn Sie Ihrem Betriebssystem. dass die Leistungsbeeinträchtigung durch fsync seit PostgreSQL Version 7. nur um auf der sicheren Seite zu sein. Diese Option kann nur beim Start des Servers oder in der Datei postgresql. Gültige Werte sind systemabhängig.conf eingestellt werden. LC_MESSAGES (Zeichenkette) Setzt die Sprache. aber es wird sich nichts ändern. In dem Fall sehen Sie weiterhin die englischsprachigen Meldungen. (Ein Absturz des Datenbankservers selbst hat damit nichts zu tun.) Diese Operation verlangsamt PostgreSQL jedoch. einige schalten sie nur aus. dass Änderungen physikalisch auf die Festplatte geschrieben werden. wie er mit der Option fsync verfahren will. weil es beim Abschluss einer Transaktion darauf warten muss. könnten die Ergebnisse der letzten paar abgeschlossenen Transaktionen ganz oder teilweise verloren gehen. einige lassen sie immer an. Daher sollte diese Methode nur bei der Entwicklung verwendet werden. Im schlimmsten Fall werden die Daten unwiederbringlich zerstört. In der Voreinstellung ist sie an. Wenn das System jedoch abstürzt. Umsortieren und Verzögern zu optimieren. fsync abzustellen. Ihrer Hardware und Ihrem Stromversorger (oder besser Ihrem Notstromaggregat) vertrauen. dann sollten Sie diese Wahl jetzt überdenken.conf zu setzen.Kapitel 16 Dieser Parameter kann zur Laufzeit nur von einem Superuser geändert werden.1 für weitere Informationen. Siehe Abschnitt 19. Wir sollten anmerken. Ohne fsync steht es dem Betriebssystem frei.3 wegen Einzelheiten. können Sie sich überlegen. FSYNC (Boolean) Wenn diese Option an ist. damit Sie auf der sicheren Seite sind. Es besteht außerdem die Möglichkeit. Aus den oben genannten Gründen kann jeder selbst entscheiden. dass für die gewünschte Sprache keine übersetzten Meldungen vorliegen.1 für weitere Informationen. wird der Wert auf eine systemabhängige Weise aus der Umgebung des Servers ermittelt. Gültige Werte sind systemabhängig. Das versichert.2. Einige Administratoren lassen sie immer ausgeschaltet. KRB_SERVER_KEYFILE (Zeichenkette) Setzt den Ort der Kerberos-Server-Schlüsseldatei. aber eine solche Änderung hält nur bis zum Ende der Clientverbindung.1 für weitere Informationen. Wenn der Wert eine leere Zeichenkette ist (was die Voreinstellung ist). Wenn der Wert eine leere Zeichenkette ist (was die Voreinstellung ist). wodurch die Leistung erheblich verbessert werden kann. siehe Abschnitt 20. dass ein Datenbankcluster nach einem Betriebssystem. Auf einigen Systemen gibt es diese Locale-Kategorie nicht. weil es da einen klaren Punkt zum Neuanfang gibt. wenn sie viele Daten auf einmal laden wollen. in der Mitteilungen ausgegeben werden.1 erheblich geringer ist. zum Beispiel mit der Familie der to_char-Funktionen. Gültige Werte sind systemabhängig. LC_MONETARY (Zeichenkette) Setzt die Locale zur Formatierung von Geldbeträgen. wenn etwas schief geht.oder Hardwareabsturz in einen konsistenten Zustand wiederhergestellt werden kann.

Die Voreinstellung ist für alle normalen Anfragen hoch genug.conf eingestellt werden.Laufzeitverhalten des Servers der Wert eine leere Zeichenkette ist (was die Voreinstellung ist). Die Voreinstellung ist 1000. ob das Passwort verschlüsselt werden soll. Diese Option kann nur beim Start des Servers eingestellt werden. siehe Abschnitt 20. LC_TIME (Zeichenkette) Setzt die Locale zur Formatierung von Datums. für die die Free-Space-Map den freien Platz verfolgt. Die Voreinstellung ist 1000. dass Ihr Server abstürzt. wenn viele Prozesse auf einmal alle so viele Dateien zu öffnen versuchen. MAX_FSM_PAGES (ganze Zahl) Setzt die maximale Anzahl der Diskseiten. Wenn Sie in der Konfigurationsdatei gesetzt wird. Diese Option kann nur beim Start des Servers eingestellt werden. Die Voreinstellung ist 64. versuchen Sie. riskieren Sie. 253 . müssen Sie sich um diese Einstellung daher keine Gedanken machen. Die Voreinstellung ist ja (das Passwort verschlüsseln). Wenn Sie des Öfteren Fehlermeldungen über zu viele offene Dateien sehen. Dieser Parameter kann nur beim Start des Servers eingestellt werden. (Wenn Sie sie aber zu hoch setzen.und Zeitwerten. wenn es notwendig ist. wirkt sie sich nur auf Serverprozesse aus. die danach gestartet werden. der viel größer ist. Wenn Sie aber Clients haben. wird der Wert auf eine systemabhängige Weise aus der Umgebung des Servers ermittelt. Aber auf einigen Plattformen (besonders BSD-Systemen) gibt sysconf einen Wert zurück. Die Voreinstellung ist 32 (wenn nicht bei der Compilierung des Servers verändert). PASSWORD_ENCRYPTION (Boolean) Wenn in CREATE USER oder ALTER USER ein Passwort ohne ENCRYPTED or UNENCRYPTED angegeben wird. Wenn der Wert eine leere Zeichenkette ist (was die Voreinstellung ist). als was das System in Wirklichkeit unterstützen kann. MAX_CONNECTIONS (ganze Zahl) Bestimmt die Maximalzahl gleichzeitiger Verbindungen zum Server.) Gültige Werte sind systemabhängig. aber Sie können sie erhöhen. diesen Wert zu verkleinern. die ein Serversubprozess gleichzeitig offen halten darf. MAX_FSM_RELATIONS (ganze Zahl) Setzt die maximale Anzahl der Relationen (Tabellen). Die vom Code tatsächlich verwendete Grenze ist der kleinere Wert aus dieser Einstellung und dem Ergebnis von sysconf(_SC_OPEN_MAX). wird der Wert auf eine systemabhängige Weise aus der Umgebung des Servers ermittelt. die auf der Annahme basiert. aber sie könnte in der Zukunft gebraucht werden. (Gegenwärtig macht diese Einstellung gar nichts. was sich im Verlauf der Zeit als ausreichend herausgestellt hat. weil der Stack übergelaufen ist. kann es sein. Diese Option kann nur beim Start des Servers eingestellt werden.1 für weitere Informationen. die viele verschiedene Tabellen in einer einzelnen Transaktion verwenden. Die Voreinstellung ist 10000. Diese Option kann nur beim Start des Servers oder in der Datei postgresql. MAX_LOCKS_PER_TRANSACTION (ganze Zahl) Die geteilte Sperrentabelle hat eine Große. wo sysconf vernünftige Werte liefert. dass Sie diesen Wert erhöhen müssen. bestimmt diese Option. Auf Systemen. für die die Free-Space-Map den freien Platz verfolgt. MAX_EXPR_DEPTH (ganze Zahl) Setzt die vom Parser maximal zugelassene Verschachtelungstiefe von Ausdrücken.) MAX_FILES_PER_PROCESS (ganze Zahl) Setzt die maximale Anzahl an Dateien. dass höchstens max_locks_per_transaction mal max_connections verschiedene Objekte auf einmal gesperrt werden müssen.

kann nur durch Angabe eines Namens mit Schemaqualifikation verwendet werden. Weitere Informationen über die Schemaverwaltung finden Sie in Abschnitt 5. wird der Server automatisch im Hintergrund ausgeführt und von allen kontrollierenden Terminals getrennt. Das unterstützt die gemeinsame Verwendung einer Datenbank (wo keine Benutzer private Schemas haben und alle public verwenden). wird das zuerst im Suchpfad gefundene verwendet. Diese Option kann beim Start des Servers eingestellt werden. dann wird $user ignoriert. wenn der Suchpfad leer ist. (Wenn nicht.oder Standardfehlerstrom geschrieben (gleiche Wirkung wie die Option -S von postmaster). weil es sonst unmöglich ist. Die Voreinstellung ist 64. Andere Wirkungen können erzielt werden. indem der Pfad global oder für jeden Benutzer eingestellt wird. public' (wobei der zweite Teil ignoriert wird. egal ob es im Pfad erwähnt wird oder nicht. Ein Fehler wird ausgegeben. Funktion usw. dann wird es vor allen anderen Schemas im Pfad durchsucht. ab. Es werden also keine Meldungen auf den Standardausgabe. Außerdem wird das Schema für temporäre Tabellen. wie viel Speicher interne Sortier. dann steht das für das Schema mit dem durch SESSION_USER zurückgegebenen Namen (also der Sitzungsbenutzer). STATEMENT_TIMEOUT (ganze Zahl) Bricht jeden Befehl. Datentyp. wenn ein Objekt (Tabelle. Ein Objekt. Der voreingestellte Wert für diesen Parameter ist '$user. Der Wert von search_path muss eine Liste von Schemas sein durch Kommas getrennt. auf dem der Server auf Verbindungen hört. Das ist nicht ganz dasselbe wie den Wert von search_path anzuschauen. dann wird es im ersten Schema im Suchpfad abgelegt.Kapitel 16 PORT (ganze Zahl) Der TCP-Port. Diese Option kann nur bei Start des Servers eingestellt werden. SHARED_BUFFERS (ganze Zahl) Setzt die Anzahl der vom Datenbankserver verwendeten Puffer im Shared Memory.) Das Systemkatalogschema pg_catalog wird immer durchsucht. Wenn ein Element der Liste der besondere Wert $user ist. Beachten Sie. SEARCH_PATH (Zeichenkette) Diese Variable gibt an. dass bei komplexen Anfragen mehrere Sortiervorgänge parallel ablaufen kön- 254 . wenn es kein Schema namens public gibt). Wenn es im Pfad steht. automatisch vor allen diesen Schemas durchsucht. wenn Sie kein anderes Logsystem. Der aktuelle effektive Wert des Suchpfads kann mit der SQL-Funktion current_schemas() untersucht werden. das in keinem der Schemas im Suchpfad ist. in welcher Reihenfolge Schemas durchsucht werden. pg_temp_nnn. Wenn es Objekte mit gleichen Namen in verschiedenen Schemas gibt. Die Verwendung dieser Option wird nicht empfohlen. private Schemas für jeden Benutzer und Kombinationen davon. der länger als die angegebene Anzahl an Millisekunden dauert. Wenn diese Option gesetzt ist.und Hash-Vorgänge verwenden. Wenn ein Objekt erzeugt wird. wenn es so ein Schema gibt. Fehlermeldungen zu sehen. aktiviert haben. SORT_MEM (ganze Zahl) Gibt an.) mit einfachem Namen ohne Schemateil verwendet wird: der Suchpfad. da current_schemas() zeigt. Wenn null. Jeder Puffer ist normalerweise 8192 Bytes groß. dann wird die Zeitmessung ausgeschaltet. wie zum Beispiel Syslog. SILENT_MODE (Boolean) Führt den Server im stillen Modus aus. Der Wert wird in Kilobyte angegeben und die Voreinstellung ist 1024 (also 1 MB). ohne dass ein bestimmtes Schema angegeben wird. Die Voreinstellung ist 5432. wird es an der angegebenen Position durchsucht. bevor sie auf temporäre Dateien ausweichen. wie die Elemente in search_path aufgelöst wurden.7. Wenn pg_catalog nicht im Pfad steht.

2.5. Wenn die max_connections minus Anzahl der aktiven Verbindungen superuser_reserved_connections erreicht oder überschreitet. können Sie diese Option anschalten. Es scheint jedoch. Die Voreinstellung ist aus. Der Wert muss kleiner als der Wert von max_connections sein. Wenn Anfragen also grundsätzlich falsch programmiert worden sind. SUPERUSER_RESERVED_CONNECTIONS (ganze Zahl) Bestimmt die Anzahl der möglichen Verbindungen. die für PostgreSQL-Superuser reserviert werden sollen. Die Voreinstellung ist 2. können Sie diese Option ausschalten. und ansonsten falsch. wenn das Ergebnis von ausdruck der NULL-Wert ist. Ansonsten werden nur Verbindungen über Unix-Domain-Sockets angenommen. Diese Option kann nur beim Start des Servers eingestellt werden. Der tatsächlich verwendete Speicher könnte also ein Vielfaches von SORT_MEM sein. wie dieser Wert angibt. Das korrekte Verhalten von ausdruck = NULL ist immer den NULL-Wert (für unbekannt) zurückzugeben. Wenn Sie das alte Verhalten benötigen. die zur Ausgabe und Eingabe von Datums.Laufzeitverhalten des Servers nen und dass dann jeder Einzelne so viel Speicher verwenden kann. Dieser Parameter kann nur beim Start des Servers eingestellt werden. Die Voreinstellung ist aus. Die Voreinstellung ist die im Betriebssystem eingestellte Zeitzone. um die Verwirrung zu reduzieren. Daten in temporäre Dateien auszulagern. Merge-Verbunden und CREATE INDEX durchgeführt. Daher ist diese Option in der Voreinstellung aus. TIMEZONE (Zeichenkette) Setzt die Zeitzone. sie ergeben wahr. Höchstens max_connections-Verbindungen können gleichzeitig aktiv sein. Vor Version 7. insbesondere ob Untertabellen von verschiedenen Befehlen automatisch mit einbezogen werden. um nach NULL-Werten zu suchen. Wenn Sie also diese Anwendung verwenden. Einzelheiten finden Sie in Abschnitt 8. sind sie nicht besonders nützlich und tauchen in normalen Anwendungen selten auf. kann diese Option auch nicht weiterhelfen. Weitere Informationen über verwandte Themen finden Sie in Abschnitt 9. Bitte lesen Sie Abschnitt 16. Da Ausdrücke der Form expr = NULL immer den NULL-Wert ergeben (nach der korrekten Interpretation). Sortiervorgänge werden von ORDER BY. bevor Sie dies verwenden. 255 .1 war das nicht der Fall. ist diese Option in der Voreinstellung abgeschaltet. um Untertabellen auszuschließen. bevor er anfängt. die ausdruck = NULL verwenden.7. und daher verursacht diese Option in der Praxis kaum Probleme. dass gefilterte Formulare in Microsoft Access Anfragen erzeugen. SSL (Boolean) Ermöglicht SSL-Verbindungen. Beachten Sie. SQL_INHERITANCE (Boolean) Diese Option kontrolliert das Verhalten der Tabellenvererbung. TRANSFORM_NULL_EQUALS (Boolean) Wenn an. aber auf lange Sicht sollten Sie Ihre Anwendungen ändern und das Schlüsselwort ONLY verwenden. Aber weil neue Benutzer häufig Schwierigkeiten beim Verstehen von Ausdrücken mit NULL-Werten haben. Weitere Informationen über Vererbung finden Sie in Teil II. die irgendeinem Ausdruck mit dem Vergleichsoperator mathematisch gleichgestellt sind (wie zum Beispiel IN). werden neue Verbindungen nur für Superuser angenommen. das heißt. dann nimmt der Server TCP/IP-Verbindungen entgegen. dann werden Ausdrücke der Form ausdruck = NULL (oder NULL = ausdruck) wie ausdruck IS NULL behandelt. nicht aber auf andere Vergleichsoperatoren oder auf andere Ausdrücke. um auf Ihre Datenbank zuzugreifen.und Zeitangaben verwendet wird. dass diese Option sich nur auf den Operator = auswirkt. Außerdem könnten mehrere Sitzungen Sortiervorgänge gleichzeitig ausführen. TCPIP_SOCKET (Boolean) Wenn dies wahr ist.

dass für eine Unix-Domain-Socket eigentlich nur die Schreibrechte von Bedeutung sind und das Setzen oder Entziehen der Lese. VACUUM_MEM (ganze Zahl) Gibt die maximale Speichermenge an.und Ausführrechte keinen Unterschied macht.conf eingestellt werden.conf eingestellt werden. (Beachten Sie. auf der der Server auf Clientverbindungen hören soll. Der Wert ist in Kilobytes und die Voreinstellung ist 8192. in Sekunden. um sich freizugebende Zeilen zu merken. ist immer der. Diese Option kann nur beim Start des Servers eingestellt werden. UNIX_SOCKET_GROUP (Zeichenkette) Setzt die Gruppe. die VACUUM verwenden darf.3. die Eigentümer der Unix-Domain-Socket sein soll. in Logdateisegmenten (jedes normalerweise 16 Megabyte groß). (Der Benutzer. Diese Option kann nur beim Start des Servers oder in der Datei postgresql. In der Voreinstellung wird auf allen konfigurierten Adressen (einschließlich localhost) gehört. 16. siehe auch unter UNIX_SOCKET_GROUP) und 0700 (nur Benutzer). Die Voreinstellung ist normalerweise /tmp. UNIX_SOCKET_PERMISSIONS (ganze Zahl) Setzt die Zugriffsrechte der Unix-Domain-Sokket. CHECKPOINT_SEGMENTS (ganze Zahl) Maximaler Abstand zwischen automatischen WAL-Checkpoints. Sinnvolle Alternativen sind 0770 (nur Benutzer und Gruppe. (Um das gebräuchliche Oktalformat zu verwenden. Der Wert dieser Option muss ein numerischer Wert in der von den Systemaufrufen chmod und umask verwendeten Form sein. CHECKPOINT_TIMEOUT (ganze Zahl) Maximale Zeit zwischen automatischen WAL-Checkpoints. dass mehrere Transaktionen mit nur einem fsync-Systemaufruf abgeschlossen werden 256 . was bedeutet.Kapitel 16 UNIX_SOCKET_DIRECTORY (Zeichenkette) Gibt das Verzeichnis für die Unix-Domain-Socket an. muss die Zahl mit 0 (einer Null) anfangen.4. wodurch die Standardgruppe des aktuellen Benutzers verwendet wird. der den Server gestartet hat.) Dieser Zugriffskontrollmechanismus ist unabhängig von dem in Kapitel 19 beschriebenen.) Zusammen mit UNIX_SOCKET_PERMISSIONS kann das als zusätzlicher Zugriffskontrollmechanismus für diesen Sockettyp verwendet werden.) Die Voreinstellung für die Zugriffsrechte ist 0777.4 WAL Einzelheiten zur Konfiguration von WAL finden Sie in Abschnitt 25. der Eigentümer ist. VIRTUAL_HOST (Zeichenkette) Gibt den Hostnamen oder die IP-Adresse an. Unix-Domain-Sockets verwenden die üblichen Zugriffsrechte für Unix-Dateien. auf der der Server auf Verbindungen von Clientanwendungen hören soll. kann aber beim Compilieren geändert werden. Diese Option kann nur beim Start des Servers eingestellt werden. Größere Werte können die VACUUM-Zeit bei großen Tabellen mit vielen gelöschten Zeilen verbessern. COMMIT_DELAY (ganze Zahl) Zeitverzögerung zwischen dem Schreiben eines Commit-Eintrags in den WAL-Puffer und dem Zurückschreiben des Puffers auf die Festplatte. in Mikrosekunden. Eine Verzögerung höher als null ermöglicht. Die Voreinstellung ist eine leere Zeichenkette. Diese Option kann nur beim Start des Servers oder in der Datei postgresql. dass jeder verbinden kann.

5 Kurze Optionen Der Bequemlichkeit halber gibt es für einige Parameter auch äquivalente Kommandozeilenoptionen aus einem Buchstaben. Sie sind in Tabelle 16. enable_hashjoin=off. -fm. da der Serverprozess seinen Commit-Eintrag schreibt. wenn keine weiteren Transaktion zum Abschluss bereit stehen. -fh.2: Kurze Optionen 257 . die aktiv sein müssen. enable_nestloop=off.Laufzeitverhalten des Servers können. dass genug weitere Transaktionen in der angegebenen Zeitspanne zum Ende kommen könnten. wenn die Systembelastung hoch genug ist. enable_seqscan=off.2 beschrieben. COMMIT_SIBLINGS (ganze Zahl) Anzahl gleichzeitiger Transaktionen. WAL_BUFFERS (ganze Zahl) Anzahl Diskseitenpuffer für WAL im Shared Memory. Diese Option kann nur beim Start des Servers eingestellt werden. WAL_DEBUG (ganze Zahl) Wenn verschieden von null. Mögliche Werte sind FSYNC (nach jeder Transaktion fsync() aufrufen). Daher wird die Verzögerung nur eingelegt. dass zumindest eine weitere Transaktion während der Verzögerungsspanne zum Abschluss bereit wird.conf eingestellt werden. wenn mindestens COMMIT_SIBLINGS weitere Transaktionen in dem Moment. OPEN_SYNC (WAL-Dateien mit der open()-Option O_SYNC schreiben) und OPEN_DATASYNC (WAL-Dateien mit der open()-Option O_DSYNC schreiben). Ein größerer Wert erhöht die Wahrscheinlichkeit. bevor die COMMIT_DELAY-Verzögerung eingelegt wird. 16. werden WAL-bezogenen Debuginformationen in den Serverlog geschrieben. um WAL-Änderung auf die Festplatte zu zwingen. -fs. Nicht alle diese Werte stehen auf allen Plattformen zur Verfügung. Kurze Option -B x -d x -F -h x -i -k x -l -N x -p x -fi. -fn. aktiv sind. WAL_SYNC_METHOD (Zeichenkette) Die Methode. enable_mergejoin=off.4. -fta Äquivalente Einstellung shared_buffers = x server_min_messages = DEBUGx fsync = off virtual_host = x tcpip_socket = on unix_socket_directory = x ssl = on max_connections = x port = x enable_indexscan=off. enable_tidscan=off show_statement_stats = on -s Tabelle 16. Diese Option kann nur beim Start des Servers oder in der Datei postgresql. FDATASYNC (nach jeder Transaktion fdatasync() aufrufen). Aber die Verzögerung ist Verschwendung.

) Das komplette Fehlen dieser Einrichtungen offenbart sich normalerweise durch einen Illegal-system call-Fehler.2 kB * shared_buffers + 14.5 Verwaltung von Kernelressourcen Eine große PostgreSQL-Installation kann schnell verschiedene Ressourcen des Betriebssystems ausreizen.1. die für PostgreSQL keine Relevanz haben). Ihre Maschine neu zu booten oder eventuell sogar den Kernel neu zu kompilieren. um sie einzustellen variieren jedoch sehr. die das Problem beschreibt und erklärt. Aus historischen Gründen müssen diese Optionen mit der postmaster-Option -o an die einzelnen Serverprozesse übergeben werden.) Die betroffenen Kernelparameter werden auf den verschiedenen Systemen ziemlich einheitlich bezeichnet. wenn der Server gestartet wird. dann lesen Sie weiter. um diese Einstellungen zu ändern. wenn Seiten. 16.3. Fast alle modernen Betriebssysteme bieten diese Fähigkeiten an. Tabelle 16. wird der Server sich weigern zu starten und sollte eine detaillierte Fehlermeldung ausgeben. show_planner_stats=on. dann ceil(SHMMAX/PAGE_SIZE) nur 1 Segment wird benötigt. 16. als Ihren Kernel umzukonfigurieren. dass es oft notwendig ist. dass sich nicht einmal eine wirklich “große” Installation brauchen.) a. show_executor_stats=on Tabelle 16.3 gibt einen Überblick.2: Kurze Optionen (Forts. -te Äquivalente Einstellung sort_mem = x show_parser_stats=on. aber die Voreinstellung ist viel höher wie SHMSEG plus Platz für andere Anwendungen Tabelle 16. In diesem Fall bleibt Ihnen nichts anderes übrig. (Auf einigen Systemen sind die Fabrikeinstellungen so niedrig. zum Beispiel $ postmaster -o '-S 1024 -s' oder wie oben beschrieben mit PGOPTIONS von der Clientseite. dann gleich SHMMAX. Seien Sie aber gewarnt. besonders Systeme mit BSD-Erbe.Kapitel 16 Kurze Option -S x -tpa. -tpl.2 kB * max_connections bis unendlich 1 wenn Bytes.) Wenn Sie auf ein derartiges Problem gestoßen sind. wie man es ausräumen kann. PostgreSQL kann ohne sie nicht arbeiten.1 Shared Memory und Semaphore Shared Memory und Semaphore werden zusammenfassend als “System V IPC” bezeichnet (zusammen mit Message Queues. Die Methoden.3: System V IPC-Parameter 258 . aber nicht alle haben sie in der Standardkonfiguration eingeschaltet oder groß genug eingestellt. (Für QNX und BeOS hat PostgreSQL eigene Ersatzimplementierungen dieser Schnittstellen. Vorschläge für einige Plattformen finden Sie unten. (Siehe auch Abschnitt 16. Name SHMMAX SHMMIN SHMALL SHMSEG SHMMNI Beschreibung maximale Größe eines Shared-MemorySegments (Bytes) minimale Größe eines Shared-MemorySegments (Bytes) Gesamtgröße des verfügbaren Shared Memory (Bytes oder Seiten) maximale Anzahl von Shared-MemorySegmenten pro Prozess maximale Anzahl von Shared-MemorySegmenten im ganzen System Vernünftige Werte 250 kB + 8. Wenn PostgreSQL eine der verschiedenen harten IPC-Grenzen überschreitet.5.

Wenn das Anlegen eines Segments scheitert. Wenn Sie von shmget eine Fehlermeldung ähnlich Invalid argument sehen. der an den freigegebenen Block angrenzt. kann als Ausweichlösung die Zahl der erlaubten Verbindungen heruntergesetzt werden. Ein weniger wahrscheinlicher Problemgrund ist die Minimalgröße eines Shared-Memory-Segments (SHMMIN). wenn nicht nötig. mehr dazu finden Sie in den plattformspezifischen Anweisungen unten. dann ist es möglich. obwohl Ersteres überwiegt. die Konflikte mit von anderen Anwendungen verwendeten Semaphoren verhindern soll.) Als grobe Schätzung zur Größe des erforderlichen Segments können Sie die Zahl der Puffer mit der Blockgröße (Standard 8 kB) multiplizieren und reichlich Extraplatz (mindestens ein halbes Megabyte) dazu addieren. Die Maximalzahl für Semaphore in einen System wird von SEMMNS gesetzt. Jede solche Gruppe enthält darüber hinaus einen 17.Laufzeitverhalten des Servers Name SEMMNI SEMMNS SEMMSL SEMMAP SEMVMX Beschreibung maximale Anzahl von Semaphorbezeichnern (d. in Gruppen von 16. Bei Fehlern. dass weniger Semaphore zur Verfügung stehen als eigentlich sollten. Der Parameter SEMMNI bestimmt. was folglich mindestens so hoch wie die Verbindungseinstellung sein muss plus einen zusätzlichen pro 16 erlaubte Verbindungen (siehe Formel in Tabelle 16. Der Parameter SEMMSL. Dieser Parameter bestimmt die Größe der Semaphorressourcenkarte.3: System V IPC-Parameter (Forts. welche für PostgreSQL höchstens ca. wird sie entweder zu einem bestehenden Eintrag. In manchen Fällen kann es auch notwendig sein. Die Größe des erforderlichen Segments hängt sowohl von der Zahl der gewünschten Puffer (Option -B) und der Zahl der erlaubten Verbindungen (Option -N) ab. hinzugefügt oder sie wird unter einem neuen Eintrag registriert. SEMMAP so zu erhöhen. die Maximalgröße. nicht ändern. Verschiedene Einstellungen. 256 kB sein sollte (normalerweise ist sie einfach 1).3). der bestimmt. Die Maximalzahlen für Segmente im ganzen System (SHMMNI) und pro Prozess (SHMSEG) sollten keine Probleme verursachen können. wird die Fehlermeldung auch die Größe des angeforderten Segments zur Information enthalten. in der jeder zusammenhängende Block aus freien Semaphoren einen Eintrag benötigt. sind für PostgreSQL nicht von Bedeutung. (Sie können als vorübergehende Maßnahme diese Einstellungen verringern. -gruppen) maximale Anzahl von Semaphoren im ganzen System maximale Anzahl von Semaphoren pro Gruppe Anzahl Einträge in Semaphorkarte Maximalwert eines Semaphors Vernünftige Werte mindestens ceil(max_connections / 16) ceil(max_connections / 16) * 17 plus Platz für andere Anwendungen mindestens 17 siehe Text mindestens 255 (Der Standard ist oft 32767. wie viele Semaphore in einer Gruppe sein können. um die Fehler abzuschalten. außer wenn Ihr System sie auch null gesetzt hat.) Tabelle 16. Die Fragmentierung des Semaphorraums kann also mit der Zeit dazu führen. wie viele Semaphorgruppen auf einmal im System existieren können. wie SEMMNU und SEMUME. Einige Systeme haben auch eine Grenze für die Gesamtgröße des Shared Memory in einem System. die meistens die verwirrende Formulierung No space left on device verwenden und von der Funktion semget kommen.h. eines SharedMemory-Segments. welcher eine “magische Zahl” enthält. Daher muss dieser Parameter mindestens ceil(max_connections / 16) sein. 259 . PostgreSQL verwendet einen Semaphor pro erlaubte Verbindung (Option -N). dass dieses Limit überschritten wurde. sind die freigegebenen Semaphore verloren (bis zum Reboot). die sich auf Semaphore Undo beziehen. Wenn die Karte voll ist. Wenn eine Semaphorgruppe freigegeben wird. Semaphor. dass es etwa auf Höhe von SEMMNS ist.) Der wichtigste Shared-Memory-Parameter ist SHMMAX. muss für PostgreSQL mindestens 17 sein. in Bytes.

fügen Sie Folgendes zu Ihrer Kernelkonfigurationsdatei hinzu. Ein SHMALL-Wert von 1024 ergibt 4 MB Shared Memory. was über die Hälfte des Systemvorrats von 60 ist. $ bpatch -r sysptsize 0x9 = 9 Als Nächstes fügen Sie einen fixen SYSPTSIZE-Wert in die Kernelkonfigurationsdatei ein. wie die verschiedenen Parameter gesetzt werden: options options options options options options options options SYSVSHM SHMMAXPGS=4096 SHMSEG=256 SYSVSEM SEMMNI=256 SEMMNS=512 SEMMNU=256 SEMMAP=256 (Auf NetBSD und OpenBSD ist das Schlüsselwort option in der Einzahl. Wenn Sie 1 addieren. In der Voreinstellung benötigt PostgreSQL 34 Semaphore. OpenBSD Die Optionen SYSVSHM und SYSVSEM müssen angeschaltet sein. führen Sie obige Änderungen durch. Wenn Sie frühere Versionen haben. wenn der Kernel kompiliert wird. Folgendes erhöht den maximalen Shared-Memory-Bereich auf 32 MB: options "SHMALL=8192" options "SHMMAX=\(SHMALL*PAGE_SIZE\)" Wenn Sie Version 4. zum Beispiel: options "SEMMNI=40" options "SEMMNS=240" FreeBSD. es sitzt fest im RAM. Erhöhen Sie den mit bpatch gefundenen Wert. Sie müssen eventuell die Zahl der Semaphore erhöhen. NetBSD. Setzen Sie die gewünschten Werte in Ihrer Kernelkonfigurationsdatei. In der Voreinstellung werden nur 4 MB Shared Memory unterstützt.1 oder später haben.Kapitel 16 BSD/OS Shared Memory. (In der Voreinstellung ist das der Fall. Der wird beim Booten dynamisch berechnet. Semaphore. Folgendes ist ein Beispiel. Bedenken Sie. options "SYSPTSIZE=16" sysptsize kann nicht mit sysctl geändert werden. verwenden Sie bpatch. fügen Sie jeweils 4 MB Shared Memory hinzu.) 260 . Um die vom System unterstützte Shared-Memory-Größe zu erhöhen. dass Shared Memory nicht pagebar ist.) Die Maximalgröße des Shared Memory wird von der Option SHMMAXPGS (in Seiten) bestimmt. kompilieren Sie den Kernel neu und booten Sie. um den sysptsize-Wert im aktuellen Kernel zu finden.

Auf HP-UX 10 ist die Voreinstellung von SEMMNS 128.2. schauen Sie in /usr/src/linux/include/asm-xxx/shmpara m. wenn Sie fertig sind.sysv. um diese Parameter zu kontrollieren. wenn vorhanden.shmmni kern. IPC-Parameter können im System Administration Manager (SAM) unter Kernel ConfigurationConfigurable Parameters eingestellt werden. sysctl verwenden.h und / usr/src/linux/include/linux/sem. Wählen Sie Create A New Kernel./configure SHMMAX=wert 261 . Um die Einstellung zu ändern.shmmax kern. führen Sie aus: . Alternativ können Sie. Die anderen Parameter sind für alle Anwendungen ausreichend dimensioniert. führen Sie aus: .d.sysv. Um den aktuellen Wert von SHMMAX anzuzeigen.shmall = 134217728 kernel.h.sysv. was für größere Datenbanken zu niedrig sein könnte. Suchen Sie die Datei /etc/sysctl. HP-UX Die Voreinstellungen reichen für normale Installationen. um das Shared Memory im RAM festzuhalten und zu verhindern./configure -y SHMMAX Um einen neuen Wert für SHMMAX zu setzen. dass es ausgeswappt wird. Wenn Sie selbst nachsehen wollen.shmall In der Voreinstellung werden nur 512 kB Shared Memory unterstützt. das beim Booten ausgeführt wird. aber sysctl kann auch später noch aufgerufen werden.Laufzeitverhalten des Servers Sie können auch sysctl verwenden. wechseln Sie zuerst in das Verzeichnis /etc/conf/cf. aber sie kann im proc-Dateisystem geändert werden (ohne Reboot).sysv.shmmin kern. MacOS X Bearbeiten Sie die Datei /System/Library/StartupItems/SystemTuning/SystemTuning und ändern Sie die folgenden Werte: sysctl sysctl sysctl sysctl sysctl SCO OpenServer -w -w -w -w -w kern. was etwa für -B 24 -N 12 reicht. Linux Die voreingestellte Shared-Memory-Grenze (sowohl SHMMAX als auch SHMALL) ist 32 MB in Kernels der Serie 2. Um zum Beispiel 128 MB zu erlauben: $ echo 134217728 >/proc/sys/kernel/shmall $ echo 134217728 >/proc/sys/kernel/shmmax Sie könnten diese Befehle in ein Skript stellen.shmmax = 134217728 Diese Datei wird üblicherweise beim Booten verarbeiten.conf und fügen Sie diese oder ähnliche Zeilen ein: kernel.shmseg kern.sysv.

6 ist die voreingestellte Maximalgröße eines Shared-Memory-Segments zu niedrig für PostgreSQL. Nachdem Sie SHMMAX gesetzt haben. Solaris Zumindest in Version 2. In finden Sie Informationen über Shared Memory auf Solaris. UnixWare Auf UnixWare 7 ist die Maximalgröße für Shared-Memory-Segmente in der Standardeinstellung 512 kB. bauen Sie den Kernel neu: /etc/conf/bin/idbuild -B und booten Sie neu. den minimalen und den maximalen Wert ausgibt. bauen Sie den Kernel neu: . zum Beispiel: set set set set set set set set shmsys:shminfo_shmmax=0x2000000 shmsys:shminfo_shmmin=1 shmsys:shminfo_shmmni=256 shmsys:shminfo_shmseg=256 semsys:seminfo_semmap=256 semsys:seminfo_semmni=512 semsys:seminfo_semmns=512 semsys:seminfo_semmsl=32 Um die Änderungen zu aktivieren. Jeder dieser Werte hat ein “hartes” und ein “weiches” Limit. 16. aber es kann vom Benutzer bis zum harten Limit hoch gesetzt werden.Kapitel 16 wo wert der neue Wert. führen Sie aus: /etc/conf/bin/idtune SHMMAX wert wo wert der neue Wert. den voreingestellten. den Sie verwenden wollen. müssen Sie neu booten. Besonders wichtig sind die Begrenzungen der Anzahl der Prozesse pro Benutzer. Das reicht etwa für -B 24 -N 12. Das harte Limit kann nur vom root-Benutzer verändert werden. ist (in Bytes). den Sie verwenden wollen. Um den aktuellen Wert von SHMMAX anzuzeigen. Nachdem Sie SHMMAX gesetzt haben. Das weiche Limit ist das wirklich geltende Limit. Der Systemaufruf setrlimit ist für des Setzen 262 . der Anzahl der offenen Dateien pro Prozess und des für jeden Prozess zur Verfügung stehenden Speichers. Um einen neuen Wert für SHMMAX zu setzen. führen Sie aus: /etc/conf/bin/idtune -g SHMMAX was den aktuellen. die den Betrieb Ihres PostgreSQL-Servers stören könnten.2 Ressourcenbegrenzungen Unix-ähnliche Betriebssysteme haben verschiedene Arten von Ressourcenbegrenzungen.5. ist (in Bytes)./link_unix und booten Sie neu. Die relevanten Einstellungen können in der Datei /etc/system geändert werden.

. Die Höchstgrenze für Dateien pro Prozess wird beim Compilieren des Kernels festgelegt. bis alle Serverprozesse beendet sind. Das ist normalerweise kein Problem. können Sie in PostgreSQL den Konfigurationsparameter max_files_per_process setzen. Das nennt sich Smart Shutdown. Dann wartet der Server. Sie kontrollieren die Art des Herunterfahrens.Laufzeitverhalten des Servers dieser Parameter verantwortlich. um den Verbrauch von offenen Dateien einzuschränken. Die Kehrseite der Medaille ist. Hängen Sie -max an. (-cur ist das weiche Limit. um das harte Limit zu setzen. ❏ Auf Linux bestimmt /proc/sys/fs/file-max. Wenn Ihnen das passiert und Sie das systemweite Limit nicht ändern wollen.. aber bestehenden Sitzungen. neben dem. 263 . Die relevanten Parameter sind maxproc. der es ermöglicht. Der eingebaute Shell-Befehl ulimit (Bourne-Shells) bzw.) Kernel können für einige Ressourcen auch systemweite Begrenzungen haben. Wenn Sie viele Server auf einer Maschine haben.. dass einige Systeme einzelnen Prozessen erlauben. 16. limit (csh) wird zur Kontrolle dieser Ressourcenbegrenzungen auf der Kommandozeile verwendet. ihre Arbeit normal zu beenden. und fährt dann herunter. wie viele offene Dateien der Kernel maximal unterstützen kann. openfiles und datasize. aber wenn Sie mehrere Server auf einer Maschine laufen haben.6 Den Server herunterfahren Man kann den Datenbankserver auf verschiedene Arten herunterfahren. dass viele Benutzer eine Maschine nebeneinander verwenden können. indem Sie unterschiedliche Signale an den Serverprozess senden. Die Voreinstellung für die Höchstzahl offener Dateien ist oft ein “sozialverträglicher” Wert. dann könnte es eng werden.conf die Ressourcenbegrenzungen beim Login. dann kann die systemweite Grenze leicht überschritten werden. Das nennt sich Fast Shutdown. dann wollen Sie das vielleicht so. aber bei dedizierten Servern sollten Sie die Begrenzung vielleicht erhöhen. :datasize-cur=256M:\ :maxproc-cur=256:\ :openfiles-cur=256:\ . indem man einen neuen Wert in die Datei schreibt oder in dem man einen Eintrag in der Datei /etc/sysctl. SIGTERM Nach Erhalt von SIGTERM erlaubt der Server keine neuen Verbindungen.txt.conf macht. Man kann den Wert verändern. eine große Anzahl von Dateien zu öffnen. nachdem alle Sitzungen normal beendet wurden. und wenn mehr als ein paar Prozesse das tun. Weitere Einzelheiten finden Sie in /usr/src/ linux/Documentation/proc. was dazu führt. was Sie für den Rest des Systems brauchen.. wie sie Verbindungen zulassen. ohne einen ungebührlich hohen Anteil der Systemressourcen zu verbrauchen. Auf Systemen aus der BSD-Familie kontrolliert die Datei /etc/login. Einzelheiten finden Sie in der Betriebssystemdokumentation. Er fährt erst herunter. Der PostgreSQL-Server verwendet einen Prozess pro Verbindung. also sollten Sie für mindestens so viele Prozesse Platz schaffen. dass diese die aktuelle Transaktionen abbrechen und zügig beenden. Zum Beispiel: default:\ . SIGINT Der Server erlaubt keine neuen Verbindungen und sendet an alle bestehenden Serverprozesse das Signal SIGTERM.

um die Client/Server-Kommunikation für verbesserte Sicherheit zu verschlüsseln. wird der Server um Eingabe der Passphrase bitten und erst starten. Wenn die SSL-Unterstützung vorhanden ist. wie Sie für Ihren Server einen privaten Schlüssel und Zertifikate erzeugen. Die PID des postmaster-Prozesses kann mit dem Programm ps herausgefunden oder in der Datei postmaster. Das ist nur in Notfällen zu empfehlen. dass Sie den lokalen Hostnamen als “Common Name” eingeben. das Passwort kann leer gelassen werden.pid` Das Programm pg_ctl ist ein Shell-Skript. Wenn der private Schlüssel durch eine Passphrase geschützt ist. kann der PostgreSQL-Server mit SSL-Unterstützung gestartet werden. Um zum Ausprobieren einen Einstieg zu erhalten. Wenn er im SSL-Modus gestartet wird.t und akzeptiert keine Passphrase. Einzelheiten. das Zertifikat des Servers enthalten sollten.conf auf an gesetzt wird. was man dann selbst machen müsste.Kapitel 16 SIGQUIT Dies ist der Immediate Shutdown.pid im Datenverzeichnis gefunden werden.key und server. dass das Herunterfahren des Servers vereinfacht. aus. finden Sie in der Anleitung zu OpenSSL. verwenden Sie folgenden OpenSSL-Befehl: openssl req -new -text -out server. die kürzer 264 . wie ein Server die Verwendung von SSL auf bestimmten Verbindungen erzwingen kann. ob SSL verwendet werden soll.und Serversystemen installiert ist und dass die Unterstützung in PostgreSQL beim Compilieren angeschaltet wurde (siehe Kapitel 14). Der Server wartet auf normale und auf SSL-Verbindungen auf demselben TCP-Port und verhandelt mit verbindenden Clients. Um schnell ein selbstsigniertes Zertifikat zu erzeugen. nach denen openssl fragt. Das führt beim Neustart zu einem Wiederherstellungsdurchlauf (indem der WAL-Log abgespielt wird). bevor ein Server im SSL-Modus gestartet werden kann. sucht der Server die Dateien server. Das erfordert. kann man ein einfaches selbstsigniertes Zertifikat verwenden. dass der postmaster-Prozess an alle Serverprozesse das Signal SIGQUIT sendet und sich dann selbst sofort beendet (ohne selbst ordentlich herunterzufahren). 16.req Füllen Sie die Informationen. der mit einer Passphrase geschützt is. damit der Client die Identität des Servers überprüfen kann. dass der Server Shared Memory und Semaphore freigibt. wenn sie eingegeben wurde.7 Sichere TCP/IP-Verbindungen mit SSL PostgreSQL hat eingebaute Unterstützung für SSL-Verbindungen. aber im richtigen Betrieb sollte ein von einer Certificate Authority (CA) (entweder eine der globalen CAs oder eine lokale) signiertes Zertifikat verwendet werden. Diese Dateien müssen eingerichtet werden. der daraus besteht. welche den privaten Schlüssel bzw. Achten Sie darauf. Das verhindert. Wichtig Man sollte am besten SIGKILL nicht zum Herunterfahren des Servers verwenden. Um also zum Beispiel einen Fast Shutdown zu machen: $ kill -INT `head -1 /usr/local/pgsql/data/postmaster. indem der Parameter ssl in postgresql. dass OpenSSL auf den Client.crt im Datenverzeichnis. Das Programm erzeugt einen Schlüssel. In Kapitel 19 wird beschrieben. Die Kindprozesse beenden gleichermaßen sofort nach dem Erhalt von SIGQUIT.

16. mit ssh als joe@foo. führt es zu einer ausreichend sicheren Netzwerkverbindung. Um die Passphrase zu entfernen (was Sie müssen. ist das entfernte Ende des Tunnels: die Portnummer. Geben Sie die alte Passphrase ein. Wenn Sie durch diesen Tunnel mit dem Datenbankserver verbinden wollen. 265 .com sind. wo der Server danach suchen wird. Als Erstes sorgen Sie dafür. ist die Portnummer von Ihrem Tunnelende. eine Terminalsitzung einzurichten. die der Server verwendet. Dann können Sie von der Clientmaschine mit einem Befehl wie diesem einen sicheren Tunnel erzeugen: ssh -L 3333:foo.pem aus. muss es Ihnen möglich sein. als ob Sie mit ssh versuchen würden.key um aus dem Zertifikat ein selbstsigniertes zu machen und Schlüssel und Zertifikat dorthin zu kopieren. Damit die Tunneleinrichtung erfolgreich sein kann.com Die erste Zahl im -L-Argument.pem -out server. Wenn das richtig gemacht wird. führen Sie die Befehle openssl rsa -in privkey. mit dem Sie verbinden wollen.com:5432 joe@foo.8 Sichere TCP/IP-Verbindungen mit SSH-Tunneln Man kann SSH verwenden. Tipp Es gibt auch andere Programme.Laufzeitverhalten des Servers als vier Zeichen ist. wenn Sie den Server automatisch starten lassen wollen). 3333. und er wird dann die für diesen Benutzer eingerichtete Authentifizierungsprozedur anwenden.crt chmod og-rwx server. als ob Sie in Wirklichkeit der Benutzer joe@foo.key -out server. sie kann frei gewählt werden. Jetzt machen Sie openssl req -x509 -in server. mit denen sichere Tunnel auf eine ähnliche Art und Weise wie die eben beschriebene eingerichtet werden können. Die zweite Zahl. genauso.key rm privkey. um die Netzwerkverbindung zwischen Clients und einem PostgreSQL-Server zu verschlüsseln. 5432. um den bestehenden Schlüssel zu entsperren. Der Name oder die Adresse zwischen den Portnummern ist der Host mit dem Datenbankserver.com zu verbinden.req -text -key server. dann verbinden Sie mit Port 3333 auf der lokalen Maschine: psql -h localhost -p 3333 template1 Für den Datenbankserver sieht es dann so aus. dass auf der Maschine mit dem PostgreSQL-Server ein SSH-Server läuft und dass Sie sich mit ssh als irgendein Benutzer einloggen können.

Kapitel 16 266 .

Um einen Benutzer zu erzeugen. wie man Benutzer erzeugt und verwaltet. wer auf welches Objekt Zugriff hat. Weitere Informationen über die verschiedenen Arten von Datenbankobjekten und die Auswirkungen von Privilegien können Sie in Kapitel 5 finden. die das Betriebssystem. Dieses Kapitel beschreibt. aber das ist nicht erforderlich. Es mag praktisch sein.1 Datenbankbenutzer Datenbankbenutzer sind vollständig getrennt von Betriebssystembenutzern. verwenden Sie den SQL-Befehl CREATE USER: CREATE USER name. name folgt den Namen für SQL-Bezeichner: entweder ohne Verzierung und Sonderzeichen oder in Anführungszeichen. enthält ein frisch initialisiertes System immer einen vordefinierten Benutzer. Diese Benutzer sind getrennt von den Benutzern. Um einen bestehenden Benutzer zu entfernen. Der Bequemlichkeit halber gibt es die Programme createuser und dropuser. auf dem der Server läuft. 17. Benutzer sind die Eigentümer von Datenbankobjekten (zum Beispiel Tabellen) und können anderen Benutzern Privilegien für diese Objekte zuweisen. Datenbankbenutzer gelten global in der gesamten Datenbankclusterinstallation (und nicht nur in einzelnen Datenbanken). Dieser Benutzer hat die festgelegte ID 1 und hat in der Voreinstellung (wenn nicht durch initdb geändert) den gleichen Namen wie der Betriebssystembenutzer. um zu kontrollieren. die vom Betriebssystem aus aufgerufen werden können und im Prinzip nur die entsprechenden SQL-Befehle ausführen: createuser name dropuser name Um das Datenbanksystem überhaupt starten zu können. und führt Sie in das Privilegiensystem ein.17 17 Datenbankbenutzer und Privilegien Jeder Datenbankcluster enthält Datenbankbenutzer. eine Übereinstimmung zu erhalten. verwaltet. der den 267 . verwenden Sie den analogen Befehl DROP USER: DROP USER name.

Passwort Ein Passwort ist nur von Bedeutung. Um eine solche Einstellung rückgängig zu machen. wird von dem Client. Der Benutzername. 268 .. Sie können die Einstellung auch während der Sitzung noch ändern. wird von der Konfiguration der Client-Authentifizierung bestimmt. der die Verbindungsanfrage einleitet. der für eine bestimmte Datenbankverbindung verwendet werden soll. Zum Beispiel wird beim Programm psql der Benutzer mit der Option -U angegeben. sie ist nur die Vorgabe.) Da die Benutzeridentität das Ausmaß der dem verbundenen Client zur Verfügung stehenden Privilegien bestimmt. dies in einer Mehrbenutzerumgebung richtig zu konfigurieren. genauso wie der Betriebssystemname nicht mit dem richtigen Namen einer Person übereinstimmen muss. Die Authentifizierungsmethoden password. wenn Sie verbinden (Tipp: keine gute Idee). Um weitere Benutzer zu erzeugen. ist es wichtig. dass SET enable_indexscan TO off. Datenbankpasswörter sind getrennt von Betriebssystempasswörtern. dass der Benutzer beim Verbinden zur Datenbank ein Passwort angibt. Wenn Sie zum Beispiel aus irgendeinem Grund Indexscans immer abschalten wollen.4 beschriebenen Konfigurationseinstellungen machen. Um einen solchen Benutzer zu erzeugen. Außerdem kann nur ein Superuser neue Benutzer erzeugen. 17. Superuser Ein Datenbank-Superuser umgeht alle Rechteprüfungen.2 Benutzerattribute Ein Datenbankbenutzer kann eine Anzahl von Attributen haben. wenn es eine Namensübereinstimmung zwischen diesen beiden Benutzerwelten gibt. dann können Sie folgenden Befehl verwenden: ALTER USER meinname SET enable_indexscan TO off.Kapitel 17 Datenbankcluster initialisierte. wenn die Clientauthentifizierungs-Methode verlangt. verwenden Sie CREATE USER name CREATEUSER. Um ein Passwort bei der Benutzererzeugung anzugeben. wie in Kapitel 19 beschrieben. Auf jeder Verbindung zum Datenbankserver ist genau eine Benutzeridentität aktiv. Viele Anwendungen nehmen den Namen des aktuellen Betriebssystembenutzers als Vorgabe für den Namen des gewünschten Datenbankbenutzers (einschließlich createuser und psql). md5 und crypt verwenden Passwörter. Traditionell heißt dieser Benutzer postgres. verwenden Sie CREATE USER name CREATEDB. Das speichert die Einstellung (aber aktiviert sie nicht sofort) und bei den folgenden Verbindungen wird es den Anschein haben. Daher kann es praktisch sein. Datenbanken erzeugen zu dürfen. Sehen Sie sich die Referenzseiten von CREATE USER und ALTER USER wegen Einzelheiten an. Die Attribute eines Benutzers können nach der Erzeugung mit ALTER USER geändert werden. verwenden Sie ALTER USER benutzername RESET varname. Um einen Datenbank-Superuser zu erzeugen. direkt vor Beginn der Sitzung ausgeführt wurde. die seine Privilegien bestimmen und Auswirkung auf das Clientauthentifizierungs-System haben. Welche Datenbankbenutzer ein bestimmter Client bei der Verbindung verwenden darf. ausdrücklich erteilt werden (außer bei Superusern. Ein Benutzer kann auch persönliche Voreinstellungen für die in Abschnitt 16. (Ein Client muss also nicht mit dem gleichen Namen wie dem Betriebssystembenutzernamen verbinden. da diese alle Rechteprüfungen umgehen). verwenden Sie CREATE USER name PASSWORD 'zeichenkette'. Erzeugung von Datenbanken Einem Benutzer muss die Erlaubnis. je nach Art der Anwendung angegeben. müssen Sie sich erst mit diesem Benutzer anmelden.

REFERENCES.3 Gruppen Wie in Unix können durch Gruppen Benutzer logisch zusammengefasst werden.. Um den Eigentümer einer Tabelle. eines Index. Wenn man ALL anstelle eines spezifischen Privilegs schreibt. ist immer nur das Privileg des Eigentümers. GRANT.. ALTER GROUP name DROP USER bname1. Wenn also joe ein bestehender Benutzer ist und konten eine bestehende Tabelle. EXECUTE. verwenden Sie den Befehl ALTER TABLE. Um ein Privileg einer Gruppe zu gewähren. verwenden Sie ALTER GROUP name ADD USER bname1. . verwenden Sie den Befehl REVOKE: REVOKE ALL ON konten FROM PUBLIC. müssen Privilegien gewährt werden. dass er selbst aus Versehen in die Tabelle schreibt. . Die besonderen Privilegien des Tabelleneigentümers (d. Um eine Gruppe zu erzeugen. REVOKE usw. Der spezielle “Benutzername” PUBLIC kann verwendet werden.. DELETE. werden alle Privilegien gewährt. um ein Privileg allen Benutzern im System zu gewähren. der diesen Befehl ausführt. Aber der Tabelleneigentümer kann sich seine eigenen normalen Privilegien entziehen. . INSERT. . Weitere Informationen über die verschiedenen von PostgreSQL unterstützen Privilegientypen finden Sie auf der Seite für GRANT in Teil VI.Datenbankbenutzer und Privilegien 17. USAGE und ALL PRIVILEGES. 269 . In der Voreinstellung kann nur der Eigentümer (oder ein Superuser) etwas mit dem Objekt anstellen. auszuführen) liegt immer automatisch beim Eigentümer und können nicht weitergegeben oder entzogen werden. ein Objekt zu verändern oder zu löschen. Es gibt mehrere verschiedene Privilegien: SELECT. 17. RULE. TEMPORARY. kann das Privileg. einer Sequenz oder einer Sicht zu ändern. verwenden Sie GRANT SELECT ON konten TO GROUP mitarbeiter. Um Benutzer einer Gruppe hinzuzufügen.h. um die Verwaltung von Privilegien zu vereinfachen: Privilegien können einer Gruppe als Ganzes gewährt oder entzogen werden. der den Befehl zur Erzeugung ausgeführt hat. die Tabelle aktualisieren zu dürfen (update). Um ein Privileg zu entziehen. Um Privilegien zuzuweisen wird der Befehl GRANT benutzt. um zum Beispiel zu verhindern. dann wird ihm ein Eigentümer zugewiesen. das Recht DROP.. muss Eigentümer der Tabelle sein. Das Recht. verwenden Sie CREATE GROUP name. CREATE. TRIGGER. Der Eigentümer ist der Benutzer. so gewährt werden: GRANT UPDATE ON konten TO joe. Der Benutzer. Um es anderen Benutzern zu erlauben. UPDATE.4 Privilegien Wenn ein Datenbankobjekt erzeugt wird. das Objekt zu benutzen.

laufen im Serverprozess mit den Betriebssystemzugriffsrechten des Datenbankservers. Beliebige Funktionen könnten also die internen Datenstrukturen des Servers verändern. den andere Benutzer ausführen könnten. Der einzige richtige Schutz ist eine scharfe Kontrolle darüber. 270 . Sie könnten also unter anderem die Zugriffskontrollen des Systems umgehen. ohne es zu wissen.5 Funktionen und Trigger Durch Funktionen und Trigger können Benutzer in den Server Code einfügen.Kapitel 17 17. Folglich können Benutzer auf beide Arten relativ ungestraft “Trojanische Pferde” erzeugen. die in einer Sprache außer SQL geschrieben wurden. Funktionen. Dieses Problem liegt in der Natur von C-Funktionen. wer Funktionen erzeugen darf.

aber das macht in der Praxis keinen Unterschied. Schemas sind eine rein logische Struktur.) Genauer gesagt ist eine Datenbank eine Sammlung von Schemas und diese enthalten die Tabellen. verwaltet und zerstört werden. Dieses Kapitel beschreibt die Eigenschaften von Datenbanken und wie sie erzeugt. die getrennt sind und im Großen und Ganzen die anderen nicht sehen sollen. Wenn eine PostgreSQL-Serverinstanz Projekte oder Benutzer beherbergen soll. Eine Anwendung.7. (Aber eine Anwendung hat keine Beschränkung hinsichtlich der Zahl der Verbindungen. (Es gibt aber einige Systemkataloge. Weitere Informationen über die Verwaltung von Schemas finden Sie in Abschnitt 5. Wenn die Projekte oder Benutzer zusammenhängen und die Ressourcen der anderen mitbenutzen sollen. Funktionen usw. aber möglicherweise getrennte Schemas verwenden. Generell gehört jedes Datenbankobjekt (Tabellen. Datenbanken sind daher das oberste hierarchische Niveau für die Organisation von SQL-Objekten (“Datenbankobjekten”). 18. die mit dem Datenbankserver verbindet. 271 . auf mehrere Datenbanken mit einer Verbindung zuzugreifen. Schema. die zum gesamten Cluster gehören und auf die man von jeder Datenbank des Clusters zugreifen kann. gibt in ihrem Verbindungsgesuch den Namen der Datenbank an. ihnen getrennte Datenbanken zu geben.) in genau eine Datenbank. Datenbank. zum Beispiel pg_database. auf mehrere Schemas von derselben Verbindung aus zuzugreifen. ist es daher empfehlenswert.) Es ist jedoch möglich. mit der sie verbinden will. die sie zur selben oder zu anderen Datenbanken öffnen kann. dann sollten Sie dieselbe Datenbank.1 Überblick Eine Datenbank ist eine benannte Sammlung von SQL-Objekten (“Datenbankobjekten”). Die gesamte Hierarchie ist also: Server. wo die Zugriffsrechte durch das Privilegiensystem geregelt werden.18 18 Datenbanken verwalten Jede Instanz eines laufenden PostgreSQL-Servers verwaltet eine oder mehrere Datenbanken. Datenbanken sind physikalisch getrennt und die Zugriffsrechte werden auf der Verbindungsebene geregelt. Anmerkung SQL nennt Datenbanken “Kataloge”. Funktionen usw. Tabelle (oder etwas anderes anstatt Tabelle). Es ist nicht möglich.

Der aktuelle Benutzer wird automatisch der Eigentümer der neuen Datenbank. um neuen Datenbanken zu erzeugen. Die Erzeugung von Datenbanken ist eine beschränkte Operation. 272 . Die Referenzseite zu createdb enthält Einzelheiten. auch wenn sie einen anderen Eigentümer haben).3).2. Anmerkung Kapitel 19 enthält Informationen darüber. wie man einschränken kann. (Siehe Kapitel 16. dass Sie die Templatedatenbank nicht für die eigentliche Arbeit verwenden sollten. Als zusätzliche Annehmlichkeit gibt es auch ein Programm. Datenbanken werden mit dem SQL-Befehl CREATE DATABASE erzeugt: CREATE DATABASE name. muss der PostgreSQL-Server gestartet sein und laufen (siehe Abschnitt 16. sodass er sie selbst konfigurieren und verwalten kann. aber bei vernünftiger Verwendung kann dieses Klonen ziemlich nützlich sein. wie Sie die Erlaubnis dafür erteilen können. Da man mit dem Datenbankserver verbunden sein muss.2 Eine Datenbank erzeugen Um eine Datenbank erzeugen zu können. genau wie oben beschrieben. wenn der Bereich zur Datenspeicherung initialisiert wird. Daraus folgt. Jener Benutzer sollte der Eigentümer der Datenbank werden. Informationen. was Sie vielleicht beabsichtigen oder auch nicht. Weitere Einzelheiten finden Sie in Abschnitt 18.) Diese Datenbank heißt template1. Die erste Datenbank wird immer mit dem Befehl initdb erzeugt. können Sie mit template1 verbinden. Beachten Sie. Es ist das Privileg des Eigentümers. Intern verwendet es dazu das Programm psql. verwenden Sie einen der folgenden Befehle: CREATE DATABASE dbname OWNER benutzername. bleibt die Frage. in der SQL-Umgebung oder createdb -O benutzername dbname Sie müssen ein Superuser sein. Der Name template1 ist kein Zufall (template = Vorlage): Wenn eine neue Datenbank erzeugt wird.2. createdb dbname createdb kann auch nicht zaubern. Um das zu erreichen. an alle danach erzeugten Datenbanken weitergegeben werden. um eine Datenbank für jemanden anders erzeugen zu dürfen. Manchmal wollen Sie eine Datenbank für jemanden anders erzeugen. dass createdb ohne Argumente eine Datenbank mit dem Namen des aktuellen Benutzers erzeugt. wo name den normalen Regeln für SQL-Bezeichner folgt. wie die erste Datenbank eines Clusters erzeugt werden kann.3. dass Änderungen. die Datenbank später wieder entfernen zu können (wodurch alle darin enthaltenen Objekte mit entfernt werden. finden Sie in Abschnitt 17. createdb. dann wird die Templatedatenbank im Prinzip geklont. Um also die erste “richtige” Datenbank zu erzeugen.Kapitel 18 18. Es verbindet mit der Datenbank template1 und führt den Befehl CREATE DATABASE aus. wie man es aufruft. Das bedeutet. wer mit einer bestimmten Datenbank verbinden kann. das Sie von der Shell aus ausführen können. um den Befehl CREATE DATABASE auszuführen. die Sie in template1 vornehmen.

Datenbanken verwalten

18.3 Template-Datenbanken
CREATE DATABASE funktioniert eigentlich, indem es eine bestehende Datenbank kopiert. Wenn nichts anderes angegeben wurde, kopiert es die Systemdatenbank template1. Diese Datenbank ist also das “Template” (englisch für Vorlage), aus dem neue Datenbanken erzeugt werden. Wenn Sie in template1 Objekte erzeugt haben, werden diese Objekte in anschließend erzeugte Benutzerdatenbanken kopiert. Durch dieses Verhalten können Datenbankadministratoren weitere Objekte zu den in allen Datenbanken vorhandenen Systemobjekten hinzufügen. Wenn Sie zum Beispiel die prozedurale Sprache PL/pgSQL in template1 installieren, wird sie automatisch in allen Benutzerdatenbanken verfügbar sein, ohne dass man noch etwas tun muss, wenn diese Datenbanken erzeugt werden.

Es gibt eine zweite Systemdatenbank: template0. Diese Datenbank hat am Anfang den gleichen Inhalt wie template1, das heißt nur die von Ihrer PostgreSQL-Version vordefinierten Standardobjekte. template0 sollte nach initdb nicht verändert werden. Wenn Sie CREATE DATABASE anweisen, template0 statt template1 zu kopieren, erzeugen sie quasi eine jungfräuliche Datenbank, die keine der lokalen Veränderungen in template1 enthält. Das ist besonders hilfreich, wenn Sie eine mit pg_dump erzeugte Sicherungsdatei wiederherstellen: Die gesicherte Datenbank sollte in eine unveränderte “leere” Datenbank wiederhergestellt werden, damit man nicht mit eventuellen Modifikationen in template1 Konflikte erzeugt. Um eine Datenbank durch Kopieren von template0 zu erzeugen, verwenden Sie
CREATE DATABASE dbname TEMPLATE template0;

in der SQL-Umgebung, oder
createdb -T template0 dbname

aus der Shell. Man kann auch weitere Templatedatenbanken erzeugen, und in der Tat kann man auch eine beliebige Datenbank eines Clusters kopieren, indem man ihren Namen bei CREATE DATABASE als Template angibt. Man muss allerdings unbedingt verstehen, dass das (noch) keine generell anwendbare Methode zum Kopieren von Datenbanken ist. Insbesondere ist es unerlässlich, dass die Quelldatenbank während des gesamten Kopiervorgangs unbenutzt ist (keine datenverändernden Transaktionen aktiv). CREATE DATABASE prüft, ob am Anfang des Vorgangs keine andere Sitzung (außer die eigene) mit der Quelldatenbank verbunden ist, aber das kann nicht ausschließen, dass während des Kopiervorgangs irgendwelche Änderungen getätigt werden, wodurch die kopierte Datenbank inkonsistent würde. Daher empfehlen wir, dass die Datenbanken, die als Template verwendet werden sollen, als nicht beschreibbar behandelt werden. Es gibt für jede Datenbank zwei nützliche Einstellmöglichkeiten in pg_database: die Spalten datistemplate und datallowconn. datistemplate können gesetzt werden, um anzuzeigen, dass diese Datenbank als Template für CREATE DATABASE vorgesehen ist. Wenn es gesetzt ist, dann kann die Datenbank von jedem Benutzer mit CREATEDB-Privileg geklont werden; wenn nicht, können nur Superuser und der Datenbankeigentümer die Datenbank klonen. Wenn datallowconn falsch ist, werden keine neuen Verbindungen zu dieser Datenbank erlaubt (aber bestehende Sitzungen werden durch das einfache Ändern der Spalte nicht angebrochen). Bei der Datenbank template0 ist normalerweise datallowconn = false, um zu verhindern, dass sie verändert wird. Bei sowohl template0 als auch template1 sollte immer datistemplate = true sein. Nachdem Sie eine Templatedatenbank vorbereitet haben oder nachdem Sie eine verändert haben, ist es empfehlenswert, VACUUM FREEZE oder VACUUM FULL FREEZE in dieser Datenbank auszuführen. Wenn Sie dies tun, während es keine weiteren offenen Transaktionen in der selben Datenbank gibt, wird garantiert, dass alle Zeilen in der Datenbank “eingefroren” sind und keine Probleme mit dem Überlauf von Transaktionsnummern haben werden. Dies ist besonders wichtig in Datenbanken, bei denen Sie datallowconn auf falsch setzen wollen, da es dann unmöglich sein wird, die Routinewartung mit VACUUM in dieser Datenbank durchzuführen. Siehe Abschnitt 21.1.3 für weitere Informationen.

273

Kapitel 18

Anmerkung
template1 und template0 haben keinen Sonderstatus im System, außer dass der Name template1 der voreingestellte Quelldatenbankname für CREATE DATABASE und bei einigen Programmen, wie createdb, die voreingestellte Datenbank zum Verbinden ist. Man könnte zum Beispiel template1 ohne Probleme löschen und aus template0 neu erzeugen. Das kann in der Tat ratsam sein, wenn man zu sorglos war und einen Haufen Unsinn in template1 erzeugt hat.

18.4 Datenbankkonfiguration
In Abschnitt 16.4 haben wir beschrieben, dass der PostgreSQL-Server eine große Zahl von Konfigurationsparametern bietet. Sie können für viele dieser Parameter datenbankspezifische Vorgabewerte setzen. Wenn Sie zum Beispiel aus irgendwelchen Gründen in einer bestimmten Datenbank den GEQO-Optimierer abschalten wollen, müssten Sie ihn entweder für alle Datenbanken abschalten oder Sorge tragen, dass jeder verbundene Client SET geqo TO off; ausführt. Um diese Voreinstellung zu machen, können Sie folgenden Befehl ausführen:
ALTER DATABASE meinedb SET geqo TO off;

Das speichert die Einstellung (aber aktiviert sie nicht sofort), und bei den folgenden Verbindungen wird es den Anschein haben, dass SET geqo TO off; direkt vor Beginn der Sitzung ausgeführt wurde. Beachten Sie, dass die Benutzer diese Einstellung während der Sitzung ändern können; sie ist nur die Vorgabe. Um eine solche Einstellung rückgängig zu machen, verwenden Sie ALTER DATABASE dbname RESET varname;.

18.5 Alternativer Speicherplatz
Man kann eine Datenbank an einer anderen Stelle auf der Festplatte als der von der Installation vorgegebenen erzeugen. Bedenken Sie aber, dass alle Datenbankzugriffe durch den Server gehen und jeder Speicherplatz also vom Server erreichbar sein muss. Alternative Speicherplätze werden durch eine Umgebungsvariable, die den absoluten Pfad der gewünschten Stelle enthält, angegeben. Diese Umgebungsvariable muss in der Umgebung des Servers stehen, muss also gesetzt gewesen sein, als der Server gestartet wurde. (Die Menge der verfügbaren alternativen Plätze steht damit unter der Kontrolle des Administrators und kann von einfachen Benutzern nicht verändert werden.) Jede beliebige Umgebungsvariable kann verwendet werden, um alternative Speicherplätze zu bezeichnen, aber der Verwendung von Variablennamen mit dem Präfix PGDATA wird empfohlen, um Verwirrung und Konflikte mit anderen Variablen zu vermeiden. Um eine Variable in der Umgebung des Serverprozesses zu erzeugen, müssen Sie erst den Server herunterfahren, die Variable definieren, den Datenbereich initialisieren und schließlich den Server neu starten. (Siehe auch Abschnitt 16.6 und Abschnitt 16.3.) Um eine Umgebungsvariable zu setzen, geben Sie ein
PGDATA2=/home/postgres/data export PGDATA2

in Bourne-Shells oder
setenv PGDATA2 /home/postgres/data

274

Datenbanken verwalten

in csh oder tcsh. Sie müssen sicherstellen, dass diese Umgebungsvariable immer in der Serverumgebung definiert ist, ansonsten werden Sie auf die Datenbank nicht zugreifen können. Daher sollten Sie sie vielleicht in einer Startdatei der Shell oder dem Startskript des Servers setzen. Um den Datenbereich in PGDATA2 zu erzeugen, achten Sie darauf, dass das übergeordnete Verzeichnis (hier /home/postgres) existiert und von dem Benutzerzugang, unter dem der Server läuft (siehe Abschnitt 16.1), beschreibbar ist. Dann geben Sie auf der Kommandozeile ein:
initlocation PGDATA2

(nicht initlocation $PGDATA2). Danach können Sie der Server neu starten. Um eine Datenbank an dem neuen Speicherplatz zu erzeugen, verwenden Sie den Befehl
CREATE DATABASE name WITH LOCATION 'platz';

wo platz die verwendete Umgebungsvariable, in diesem Beispiel PGDATA2, ist. Der Befehl createdb hat zu diesem Zweck die Option -D. Datenbanken an alternativen Speicherplätzen können wie andere Datenbanken verwendet und entfernt werden.

Anmerkung
Es kann auch ermöglicht werden, absolute Pfade direkt in CREATE DATABASE anzugeben, ohne Umgebungsvariablen definieren zu müssen. Das ist in der Voreinstellung verboten, weil es eine Sicherheitslücke wäre. Um es zu erlauben, müssen Sie, wenn Sie PostgreSQL compilieren, das C-Präprozessormakro ALLOW_ABSOLUTE_DBPATHS definieren. Ein Möglichkeit, dies zu tun, ist, den Compilierungsschritt so auszuführen:
gmake CPPFLAGS=-DALLOW_ABSOLUTE_DBPATHS all

18.6

Eine Datenbank zerstören

Datenbanken werden mit dem Befehl DROP DATABASE zerstört:
DROP DATABASE name;

Nur der Eigentümer einer Datenbank (d.h. der Benutzer, der sie erzeugt hat) oder ein Superuser kann eine Datenbank löschen. Das Löschen einer Datenbank entfernt alle Objekte, die in der Datenbank enthalten waren. Die Zerstörung einer Datenbank kann nicht rückgängig gemacht werden. Sie können DROP DATABASE nicht ausführen, während Sie mit der Opferdatenbank verbunden sind. Sie können jedoch mit einer beliebigen anderen Datenbank, einschließlich template1, verbunden sein. template1 wäre die einzige Wahl, um die letzte Benutzerdatenbank eines Clusters zu löschen. Der Bequemlichkeit halber gibt es auch ein Programm, das Sie in der Shell ausführen können, um Datenbanken zu entfernen:
dropdb dbname

(Im Gegensatz zu createdb entfernt dropdb nicht als Vorgabe die Datenbank mit den Namen des aktuellen Benutzers.)

275

19

19

Clientauthentifizierung

Wenn sich eine Clientanwendung mit dem Datenbankserver verbindet, gibt sie an, unter welchem PostgreSQL-Benutzernamen sie verbinden will, ähnlich wie man sich in einem Unix-Computer als ein bestimmter Benutzer anmeldet. Innerhalb der SQL-Umgebung bestimmt der aktive Datenbankbenutzername die Zugriffsprivilegien für Datenbankobjekte; siehe Kapitel 17 für weitere Informationen. Daher ist es wichtig, die Menge der Benutzer, die verbinden können, einzuschränken. Authentifizierung ist der Vorgang, in dem der Datenbankserver die Identität des Clients feststellt und im erweiterten Sinne bestimmt, ob die Clientanwendung (oder der Benutzer, der sie ausführt) unter dem angegebenen Benutzernamen verbinden darf. PostgreSQL bietet eine Reihe verschiedener Clientauthentifizierungs-Methoden. Die Methode, die zur Authentifizierung einer bestimmten Clientverbindung verwendet wird, kann auf Basis der Hostadresse des Clients, der Datenbank und des Benutzernamens ausgewählt werden. PostgreSQL-Benutzernamen sind von den Benutzernamen des Betriebssystems, auf dem der Server läuft, logisch getrennt. Wenn alle Benutzer eines bestimmten Servers auch Zugänge auf der Servermaschine haben, macht es Sinn, die Datenbankbenutzernamen so zu wählen, dass sie mit den Betriebssystembenutzernamen übereinstimmen. Ein Server, der Verbindungen von anderen Maschinen akzeptiert, kann allerdings viele Datenbankbenutzer haben, die keinen Betriebssystemzugang auf dem Server haben, und dann muss keine Verbindung zwischen den Benutzernamen auf Datenbank- und auf Betriebssystemebene bestehen.

19.1 Die Datei pg_hba.conf
Clientauthentifizierung wird durch die Datei pg_hba.conf im Datenverzeichnis, z.B. /usr/local/ pgsql/data/pg_hba.conf, kontrolliert. (HBA steht für host-based authentication, also Authentifizierung auf Host-Basis.) Eine voreingestellte pg_hba.conf-Datei wird von initdb im Datenverzeichnis eingerichtet, wenn der Datenbereich initialisiert wird. Generell besteht die Datei pg_hba.conf aus einer Reihe von Datensätzen, einem pro Zeile. Leere Zeilen werden ignoriert, genauso wie gesamte Text nach dem Kommentarzeichen #. Ein Datensatz besteht aus einer Anzahl von Feldern, die durch Leerzeichen oder Tabs getrennt sind. Felder können Leerzeichen enthalten, wenn der Wert in Anführungszeichen steht. Ein Datensatz kann sich nicht über mehrere Zeilen erstrecken. Jeder Satz besteht aus einem Verbindungstyp, einem IP-Adressbereich für Clients (falls für den Verbindungstyp von Bedeutung), einem Datenbanknamen, einem Benutzernamen und einer Authentifizierungs-

277

Kapitel 19

methode, die für Verbindungen, die mit diesen Parametern übereinstimmen, verwendet wird. Der erste Satz, bei dem der Verbindungstyp, die Clientadresse, die gewünschte Datenbank und der Benutzername übereinstimmen, wird für die Authentifizierung angewendet. Wenn ein Satz ausgewählt wurde und die Authentifizierung nicht erfolgreich ist, werden die folgenden Sätze trotzdem nicht mehr in Erwägung gezogen. Wenn kein Datensatz mit den Verbindungsparametern übereinstimmt, wird der Zugriff verweigert. Ein Datensatz kann eines dieser drei Formate haben:
local datenbank benutzer authentifizierungs-methode [authentifizierungs-option] host datenbank benutzer IP-adresse IP-maske authentifizierungs-methode [authentifizierungs-option] hostssl datenbank benutzer IP-adresse IP-maske authentifizierungs-methode [authentifizierungs-option]

Die Bedeutung der Felder ist wie folgt:
local

Dieser Satz gilt für Verbindungsversuche über Unix-Domain-Sockets. Ohne Sätze dieses Typs werden keine Verbindungen über Unix-Domain-Sockets zugelassen.
host

Dieser Satz gilt für Verbindungsversuche über TCP/IP-Netzwerke. Beachten Sie, dass TCP/IPVerbindungen nur möglich sind, wenn der Server mit der Option -i gestartet wurde oder der Konfigurationsparameter tcpip_socket in postgresql.conf eingeschaltet ist.
hostssl

Dieser Satz gilt für Verbindungen mit SSL über TCP/IP. host-Sätze gelten für SSL- und NichtSSL-Verbindungen, aber hostssl erfordert eine SSL-Verbindung. Um diese Option verwenden zu können, muss der Server mit SSL-Unterstützung kompiliert worden sein. Außerdem muss SSL mit der Option ssl in postgresql.conf angeschaltet sein (siehe Abschnitt 16.4).
datenbank

Gibt an, für welche Datenbank der Satz gilt. Der Wert all passt auf alle Datenbanken. Der Wert sameuser gibt an, dass der Satz gilt, wenn die gewünschte Datenbank den gleichen Namen hat wie der gewünschte Benutzer. Der Wert samegroup gibt an, dass der gewünschte Benutzer ein Mitglied der Gruppe mit dem gleichen Namen wie die gewünschte Datenbank sein muss. Ansonsten ist dies der Name einer bestimmten PostgreSQL-Datenbank. Man kann mehrere Datenbanknamen angeben, indem man sie durch Kommas trennt. Eine Datei mit Namen von Datenbanken kann angegeben werden, indem vor den Dateinamen ein @ gestellt wird. Die Datei muss im gleichen Verzeichnis wie pg_hba.conf liegen.
benutzer

Gibt an, für welche PostgreSQL-Benutzer der Eintrag gilt. Der Wert all passt auf alle Benutzer. Ansonsten ist dies der Name eines bestimmten PostgreSQL-Benutzers. Man kann mehrere Benutzernamen angeben, indem man sie durch Kommas trennt. Gruppennamen können angegeben werden, indem man vor den Namen ein + stellt. Eine Datei mit Namen von Benutzern kann angegeben werden, indem vor den Dateinamen ein @ gestellt wird. Die Datei muss im gleichen Verzeichnis wie pg_hba.conf liegen.
IP-adresse IP-maske

Diese zwei Felder enthalten IP-Adressen und -Masken in der normalen Schreibweise aus Dezimalzahlen und Punkten. (IP-Adressen können nur numerisch angegeben werden, nicht als Domain-

278

Clientauthentifizierung

oder Hostnamen.) In Kombination geben sie an, für welche Client-IP-Adressen dieser Satz gilt. Genau gesagt ist es so, dass
(tatsächliche-IP-adresse xor IP-adresse-feld) and IP-maske-feld

null sein muss, damit der Satz gilt. (Natürlich kann man IP-Adressen verfälschen, aber das liegt nicht im Einflussbereich von PostgreSQL.) Diese Felder können nur in host- und hostssl-Sätzen verwendet werden.
authentifizierungs-methode

Gibt an, welche Authentifizierungsmethode verwendet werden soll, wenn dieser Satz auf die Verbindungsparameter passt. Die Wahlmöglichkeiten sind hier kurz zusammengefasst; Einzelheiten finden Sie in Abschnitt 19.2.
trust

Die Verbindung wird bedingungslos zugelassen. Diese Methode erlaubt jedem, der mit dem PostgreSQL-Datenbankserver verbinden kann, sich mit jedem beliebigen PostgreSQL-Benutzernamen anzumelden, ohne ein Passwort zu benötigen. Einzelheiten stehen in Abschnitt 19.2.1.
reject

Die Verbindung wird bedingungslos angelehnt. Das ist nützlich, um bestimmte Hosts aus einer Gruppe “herauszufiltern”.
md5

Verlangt, dass der Client zur Authentifizierung ein mit MD5 verschlüsseltes Passwort schickt. Dies ist die einzige Methode, die verschlüsselte Passwörter in pg_shadow ermöglicht. Einzelheiten stehen in Abschnitt 19.2.2.
crypt

Wie die md5-Methode, aber verwendet die ältere Verschlüsselung mit crypt(), welche für Clients vor Version 7.2 benötigt wird. md5 sollte für Clients aus Version 7.2 und später bevorzugt werden. Einzelheiten stehen in Abschnitt 19.2.2.
password

Wie md5, aber das Passwort wird unverschlüsselt über das Netzwerk geschickt. Dies sollte in unvertraulichen Netzwerken nicht verwendet werden. Einzelheiten stehen in Abschnitt 19.2.2.
krb4

Verwendet Kerberos V4, um den Benutzer zu authentifizieren. Dies ist nur bei TCP/IPVerbindungen möglich. Einzelheiten stehen in Abschnitt 19.2.3,
krb5

Verwendet Kerberos V5, um den Benutzer zu authentifizieren. Dies ist nur bei TCP/IPVerbindungen möglich. Einzelheiten stehen in Abschnitt 19.2.3.
ident

Ermittelt den Betriebssystembenutzernamen des Clients (bei TCP/IP-Verbindungen, indem der Ident-Server auf dem Client kontaktiert wird, bei lokalen Verbindungen vom Betriebssystem selbst) und prüft, ob der Benutzer unter dem gewünschten Datenbankbenutzernamen verbinden darf. Dazu wird die hinter dem Schlüsselwort ident angegebene Map verwendet.

279

Kapitel 19

Wenn Sie den Map-Namen sameuser verwenden, müssen die Benutzernamen gleich sein. Wenn nicht, wird der Map-Name in der Datei pg_ident.conf im selben Verzeichnis wie pg_hba.conf gesucht. Die Verbindung wird akzeptiert, wenn diese Datei einen Eintrag für den Map-Namen enthält, der den Betriebssystembenutzernamen und den gewünschten PostgreSQL-Benutzernamen verbindet. Bei lokalen Verbindungen funktioniert dies nur auf Maschinen, die für Unix-DomainSockets Credentials unterstützen (gegenwärtig Linux, FreeBSD, NetBSD und BSD/OS). Einzelheiten stehen in Abschnitt 19.2.4.
pam

Verwendet den vom Betriebssystem angebotenen PAM-Dienst (Pluggable Authentication Modules) zur Authentifizierung. Einzelheiten stehen in Abschnitt 19.2.5.
authentifizierungs-option

Die Bedeutung dieses Felds hängt von der gewählten Authentifizierungsmethode ab und wird im nächsten Abschnitt beschrieben. Da die Datensätze in pg_hba.conf bei jedem Verbindungsversuch hintereinander geprüft werden, ist die Reihenfolge der Sätze von Bedeutung. Normalerweise haben die oberen Einträge enger gefasste Verbindungsparameter und schwächere Authentifizierungsmethoden, während unteren die Einträge weiter gefasste Verbindungsparameter und strengere Authentifizierungsmethoden verwenden. Man könnte zum Beispiel für lokale TCP/IP-Verbindungen trust verwenden, aber für andere TCP/IP-Verbindungen Passwörter verlangen. In dem Fall würde der Eintrag, der trust für Verbindungen von 127.0.0.1 angibt, vor dem Eintrag, der Passwortauthentifizierung für einen größeren Bereich von IP-Adressen wählt, stehen.

Wichtig
Verhindern Sie nicht, dass der Superuser auf die Datenbank template1 zugreifen kann. Diverse Hilfsprogramme benötigen den Zugriff auf template1. Die Datei pg_hba.conf wird beim Start des Servers und wenn der Hauptserverprozess (postmaster) das Signal SIGHUP erhält gelesen. Wenn Sie die Datei in einem aktiven System bearbeiten, müssen Sie das dem postmaster-Prozess signalisieren (mit pg_ctl reload oder kill -HUP), damit er die Datei neu liest. Ein Beispiel für eine pg_hba.conf-Datei wird in Beispiel 19.1 gezeigt. Einzelheiten über die verschiedenen Authentifizierungsmethoden finden Sie im nächsten Abschnitt.

Beispiel 19.1: Ein Beispiel für pg_hba.conf
# Erlaube jedem Benutzer auf dem lokalen System, über # Unix-Domain-Sockets (Standard für lokale Verbindungen) mit jeder # Datenbank unter jedem Benutzernamen zu verbinden. # # TYP DATENBANK BENUTZER IP-ADRESSE IP-MASKE local all all # Das gleiche für lokale Verbindungen über TCP/IP-Loopback. # # TYP DATENBANK BENUTZER IP-ADRESSE IP-MASKE host all all 127.0.0.1 255.255.255.255

METHODE trust

METHODE trust

# Erlaube jedem Benutzer von einem Host mit IP-Adresse 192.168.93.x mit

280

Clientauthentifizierung

# der Datenbank "template1" unter dem Benutzernamen, den Ident für die # Verbindung ermittelt hat (normalerweise der Unix-Benutzername), zu # verbinden. # # TYP DATENBANK BENUTZER IP-ADRESSE IP-MASKE METHODE host template1 all 192.168.93.0 255.255.255.0 ident sameuser # Erlaube einem Benutzer von Host 192.168.12.10 mit der Datenbank # "template1" zu verbinden, wenn das richtige Passwort angegeben wird. # # TYP DATENBANK BENUTZER IP-ADRESSE IP-MASKE METHODE host template1 all 192.168.12.10 255.255.255.255 md5 # Ohne die vorangegangenen "host"-Zeilen, verhindern diese beiden Zeilen # alle Verbindungen von 192.168.54.1 (da dieser Eintrag zuerst kommt), # aber erlauben Kerberos-V-Verbindungen vom Rest des Internets. Die # Nullmaske bedeutet, dass keine Bits der Host-IP-Adresse betrachtet # werden, so dass sie auf alle Hosts passt. # # TYP DATENBANK BENUTZER IP-ADRESSE IP-MASKE METHODE host all all 192.168.54.1 255.255.255.255 reject host all all 0.0.0.0 0.0.0.0 krb5 # Erlaube Benutzern von 192.168.x.x-Hosts zu verbinden, wenn sie die # Ident-Prüfung bestehen. Wenn zum Beispiel Ident sagt, dass der # Benutzer "bryanh" ist und er als PostgreSQL-Benutzer "guest1" # verbinden will, dann wird die Verbindung erlaubt, wenn in # pg_ident.conf ein Eintrag für ein Map "omicron" ist, der sagt, dass # "bryanh" als "guest1" verbinden darf. # # TYP DATENBANK BENUTZER IP-ADRESSE IP-MASKE METHODE host all all 192.168.0.0 255.255.0.0 ident omicron # Wenn dies die einzigen drei Zeilen für lokale Verbindunge sind, dann # erlauben Sie lokalen Benutzern, nur mit ihren eigenen Datenbanken # (Datenbanken mit den gleichen Namen wie der Benutzername) zu # verbinden, außer Administratoren und Mitglieder der Gruppe # "support", die mit allen Datenbanken verbinden dürfen. Die Datei # $PGDATA/admins enthält eine Liste mit Benutzernamen. In allen # Fällen werden Passwörter verlangt. # # TYP DATENBANK BENUTZER IP-ADRESSE IP-MASKE METHODE local sameuser all md5 local all @admins md5 local all +support md5

281

Kapitel 19

# Die letzten zwei Zeilen können zu einer einzigen Zeile # zusammengefasst werden: local all @admins,+support

md5

# Die Datenbankspalte kann auch Listen und Dateinamen enthalten, aber # keine Gruppen: local db1,db2,@demodbs all md5

19.2 Authentifizierungsmethoden
Im Folgenden werden die Authentifizierungsmethoden im Einzelnen beschrieben.

19.2.1 Freier Zugang
Wenn trust-Authentifizierung angegeben ist, dann nimmt PostgreSQL an, dass jeder, der mit dem Server verbinden kann, als jeder beliebiger Benutzer auf die Datenbank zugreifen darf (einschließlich als Datenbank-Superuser). Diese Methode sollte nur verwendet werden, wenn Verbindungen zum Server auf Betriebssystemebene ausreichend geschützt werden.
trust-Authentifizierung ist für lokale Verbindungen auf Einzelbenutzerarbeitsplätzen angebracht und bequem. Für Mehrbenutzermaschinen ist sie alleine in der Regel nicht angebracht. Sie können jedoch trust auch auf einer Mehrbenutzermaschine verwenden, wenn Sie den Zugang zur Unix-DomainSocket-Datei des Servers auf Dateisystemebene einschränken. Um das zu tun, setzen Sie den Parameter unix_socket_permissions (und eventuell unix_socket_group) in postgresql.conf, wie in Abschnitt 16.4.3 beschrieben. Oder Sie könnten unix_socket_directory verändern, um die Socketdatei in ein entsprechend beschränktes Verzeichnis zu verlegen.

Die Dateisystemzugriffsrechte helfen nur bei Verbindungen über Unix-Domain-Sockets. Auf lokale TCP/ IP-Verbindungen haben Sie keine Auswirkung. Wenn Sie also die Dateisystemzugriffsrechte verwenden wollen, um lokale Verbindungen zu kontrollieren, müssen Sie die Zeile host ... 127.0.0.1 ... aus pg_hba.conf entfernen oder das trust in eine andere Methode ändern.
trust-Authentifizierung ist für TCP/IP-Verbindungen nur sinnvoll, wenn Sie allen Benutzern auf allen Maschinen, die mit dem Server über trust-Zeilen in pg_hba.conf verbinden können, vertrauen. Es ist selten vernünftig, trust für TCP/IP-Verbindungen außer denen von localhost (127.0.0.1) zu verwenden.

19.2.2 Passwort-Authentifizierung
Die Authentifizierungsmethoden mit Passwörtern sind md5, crypt und password. Die Methoden funktionieren ganz ähnlich, unterscheiden sich aber durch die Art, wie das Passwort über die Verbindung geschickt wird. Wenn Sie sich Sorgen um Passwort-“Sniffing” machen, sollten Sie md5 verwenden, wobei crypt die zweite Wahl wäre, wenn sie Clients aus Versionen vor 7.2 unterstützen müssen. Die Methode password sollte insbesondere bei Verbindungen über das offene Internet vermieden werden (es sei denn, Sie verwenden SSL, SSH oder andere Vorrichtungen um die Verbindung zu sichern). PostgreSQL-Datenbankpasswörter sind getrennt von den Passwörtern im Betriebssystem. Das Passwort jedes Datenbankbenutzers wird in der Systemtabelle pg_shadow gespeichert. Passwörter können mit den SQL-Befehlen CREATE USER und ALTER USER verwaltet werden, zum Beispiel CREATE USER foo WITH PASSWORD 'geheim';. In der Voreinstellung, das heißt, wenn kein Passwort eingerichtet wurde, ist das gespeicherte Passwort der NULL-Wert, wodurch die Passwortauthentifizierung für den Benutzer nie erfolgreich sein kann.

282

Clientauthentifizierung

Um zu beschränken, welche Benutzer mit bestimmten Datenbanken verbinden können, können Sie die Benutzer in der Spalte benutzer in der Datei pg_hba.conf wie im vorigen Abschnitt beschrieben aufführen.

19.2.3 Kerberos-Authentifizierung
Kerberos ist ein etabliertes, sicheres Authentifizierungssystem für verteilte Dienste in öffentlichen Netzwerken. Eine Beschreibung des Kerberos-Systems würde den Rahmen dieses Dokuments sprengen; das ganze System kann ziemlich komplex (aber mächtig) sein. Die Kerberos FAQ oder MIT Project Athena können als Ausgangspunkte für Erforschungen dienen. Es gibt verschiedene Quellen für Kerberos-Produkte. Um Kerberos benutzen zu können, muss die Unterstützung beim Compilieren eingeschaltet worden sein. Weitere Informationen darüber finden Sie in Kapitel 14. Kerberos 4 und 5 werden angeboten, aber nur eine Version kann von jeder Installation unterstützt werden. PostgreSQL funktioniert wie ein normaler Kerberos-Dienst. Der Name des Service-Principals ist servicename/hostname@realm, wobei servicename gleich postgres ist (außer wenn ein anderer Servicename konfiguriert wurde, mit ./configure -with-krb-srvnam=irgendwas). hostname ist der voll qualifizierte Hostname der Servermaschine. Das Realm des Service-Principals ist das bevorzugte Realm der Servermaschine. Client-Principals haben den PostgreSQL-Benutzernamen als ersten Teil, zum Beispiel pgbenutzer/ andereszeug@realm. Das Realm wird gegenwärtig von PostgreSQL nicht überprüft; wenn Sie also Cross-Realm-Authentifizierung eingeschaltet haben, werden alle Principals in allen Realms, die mit Ihrem kommunizieren können, akzeptiert. Achten Sie darauf, dass die Serverschlüsseldatei vom PostgreSQL-Server lesbar (und bevorzugt nur lesbar) ist. (Siehe auch Abschnitt 16.1.) Der Ort der Schlüsseldatei wird vom Konfigurationsparameter krb_server_keyfile bestimmt. (Siehe auch Abschnitt 16.4.) Die Voreinstellung ist /etc/srvtab für Kerberos 4 und FILE:/usr/local/pgsql/etc/krb5.keytab (je nachdem, welches Verzeichnis bei der Compilierung als sysconfdir angegeben wurde) für Kerberos 5. Um eine Keytab-Datei zu erzeugen, verwenden Sie zum Beispiel (mit Version 5):
kadmin% ank -randkey postgres/server.my.domain.org kadmin% ktadd -k krb5.keytab postgres/server.my.domain.org

Einzelheiten finden Sie in der Dokumentation zu Kerberos. Wenn Sie mit der Datenbank verbinden, müssen Sie ein Ticket haben, dass dem gewünschten Datenbankbenutzernamen entspricht. Beispiel: Für den Datenbankbenutzernamen fred können die Principals fred@EXAMPLE.COM oder fred/users.example.com@EXAMPLE.COM zur Authentifizierung mit dem Datenbankserver verwendet werden. Wenn Sie mod_auth_krb und mod_perl auf Ihrem Apache-Webserver verwenden, können Sie AuthType KerberosV5SaveCredentials mit einem mod_perl-Skript verwenden. Dadurch erhalten Sie sicheren Datenbankzugriff über das Web ohne zusätzliche Passwörter.

19.2.4 Ident-Authentifizierung
Das Ident-Authentifizierungssystem prüft den Betriebssystembenutzernamen des Clients und ermittelt dann die erlaubten Datenbankbenutzernamen, indem es eine Map-Datei verwendet, die die erlaubten Benutzernamenpaare auflistet. Der sicherheitskritische Aspekt ist die Bestimmung des Benutzernamens des Clients, und wie das funktioniert, hängt vom Verbindungstyp ab.

283

Kapitel 19

Ident-Authentifizierung über TCP/IP
Das Identification Protocol ist in RFC 1413 (siehe Literaturverzeichnis) beschrieben. Praktisch jedes Unixähnliche Betriebssystem hat einen Ident-Server, der in der Voreinstellung auf TCP-Port 113 hört. Die grundsätzliche Funktion des Ident-Servers ist es, Fragen wie diese zu beantworten: “Welcher Benutzer startete die Verbindung, die aus deinem Port X kommt und bei meinen Port Y ankommt?” Da PostgreSQL sowohl X als auch Y kennt, wenn die Verbindung physikalisch eingerichtet ist, kann es den Ident-Server auf dem Host des verbindenden Client befragen und könnte so theoretisch den Betriebssystembenutzer zu jeder beliebigen Verbindung ermitteln. Der Nachteil dieses Vorgehens ist, dass es sich auf die Integrität des Clients verlässt: Wenn die Clientmaschine nicht vertrauenswürdig ist oder kompromittiert wurde, könnte ein Angreifer so ziemlich jedes Programm an Port 113 laufen lassen und Benutzernamen nach Belieben zurückgeben. Diese Authentifizierungsmethode ist daher nur in geschlossenen Netzwerken angebracht, wo jede Clientmaschine streng kontrolliert wird und die Verwalter von Datenbank und System eng zusammenarbeiten. Anders ausgedrückt müssen Sie der Maschine mit dem Ident-Server vertrauen können. Beachten Sie die Warnung: RFC 1413 The Identification Protocol is not intended as an authorization or access control protocol.

Ident-Authentifizierung über lokale Sockets
Auf Systemen, die auf Unix-Domain-Sockets SO_PEERCRED-Anfragen unterstützen (gegenwärtig Linux, FreeBSD, NetBSD und BSD/OS), kann Ident-Authentifizierung auch bei lokalen Verbindungen angewendet werden. In diesem Fall erzeugt die Verwendung von Ident keine weiteren Sicherheitsprobleme; in der Tat ist Ident auf solchen Systemen die bevorzugte Methode für lokale Verbindungen. Auf Systemen ohne SO_PEERCRED-Anfragen steht Ident-Authentifizierung nur für TCP/IP-Verbindungen zur Verfügung. Als Ausweg kann man als Verbindungsziel die localhost-Adresse 127.0.0.1 angeben.

Ident-Maps
Wenn Ident-basierte Authentifizierung verwendet wird und der Name des Betriebssystembenutzers, der die Verbindung eingeleitet hat, ermittelt wurde, prüft PostgreSQL, ob dieser Benutzer als der Datenbankbenutzer, den er gewünscht hat, verbinden darf. Das wird durch das Ident-Map-Argument kontrolliert, das in der Datei pg_hba.conf nach dem Schlüsselwort ident steht. Es gibt eine vordefinierte Ident-Map namens sameuser, welche es jedem Betriebssystembenutzer erlaubt, als der Datenbankbenutzer mit dem gleichen Namen (falls dieser existiert) zu verbinden. Andere Maps müssen selbst erzeugt werden. Andere Ident-Maps neben sameuser werden in der Datei pg_ident.conf im Datenverzeichnis definiert, die Zeilen mit folgender allgemeinen Form hat:
map-name ident-benutzername database-benutzername

Kommentare und Leerzeichen werden auf die übliche Art behandelt. Der map-name ist ein beliebiger Name, der verwendet wird, um in pg_hba.conf auf diese Map zu verweisen. Die anderen beiden Felder geben an, welcher Betriebssystembenutzer als welcher Datenbankbenutzer verbinden darf. Der gleiche map-name kann mehrfach verwendet werden, um mehrere Benutzerpaare in einer Map zu definieren. Es gibt keine Einschränkungen darüber, wie viele Datenbankbenutzer einem Betriebssystembenutzer oder umgekehrt entsprechen dürfen. Die Datei pg_ident.conf wird beim Start des Servers und wenn der Hauptserverprozess (postmaster) das Signal SIGHUP erhält gelesen. Wenn Sie die Datei in einem aktiven System bearbeiten, müssen Sie das dem postmaster-Prozess signalisieren (mit pg_ctl reload oder kill -HUP), damit er die Datei neu liest. Eine pg_ident.conf-Datei, die zusammen mit der pg_hba.conf-Datei aus Beispiel 19.1 verwendet werden könnte, wird in Beispiel 19.2 gezeigt. In dieser Beispielkonfiguration würde jemandem aus dem

284

Clientauthentifizierung

192.168-Netzwerk nur der Zugriff gewährt, wenn er den Unix-Benutzernamen bryanh, ann oder robert hat. Darüber hinaus würde dem Unix-Benutzer robert der Zugriff nur gewährt, wenn er als PostgreSQLBenutzer bob, nicht als robert oder jemand anders, verbindet. ann dürfte nur als ann verbinden. Der Benutzer bryanh könnte entweder als bryanh selbst oder als guest1 verbinden.

Beispiel 19.2: Ein Beispiel für pg_ident.conf
# MAPNAME IDENT-BENUTZER PG-BENUTZER

omicron bryanh bryanh omicron ann ann # bob heißt auf dieser Maschine robert omicron robert bob # bryanh kann auch als guest1 verbinden omicron bryanh guest1

19.2.5 PAM-Authentifizierung
Diese Authentifizierungsmethode funktioniert ähnlich wie password, verwendet aber PAM (Pluggable Authentication Modules) als Mechanismus. Der voreingestellte PAM-Servicename ist postgresql. Wahlweise können Sie selbst einen Servicenamen nach dem Schlüsselwort pam in der Datei pg_hba.conf eingeben. Für weitere Informationen über PAM lesen Sie bitte die Linux-PAM Page und die Solaris PAM Page.

19.3 Authentifizierungsprobleme
Echte Authentifizierungsprobleme äußern sich im Allgemeinen durch Fehlermeldungen wie die folgende.
No pg_hba.conf entry for host 123.123.123.123, user andym, database testdb

Das sehen Sie am wahrscheinlichsten, wenn Sie den Server erfolgreich kontaktiert haben, aber er mit Ihnen nicht reden will. Wie die Meldung andeutet, hat der Server die Verbindung abgelehnt, weil er keinen passenden Eintrag in seiner Konfigurationsdatei pg_hba.conf gefunden hat.
Password authentication failed for user 'andym'

Meldungen wie diese zeigen an, dass Sie den Server kontaktiert haben und er mit Ihnen reden will, aber erst, wenn Sie die in der Datei pg_hba.conf angegebene Authentifizierungsmethode durchlaufen haben. Überprüfen Sie das angegebene Passwort oder prüfen Sie Ihre Kerberos- oder Ident-Software, wenn sich die Meldung auf diese Authentifizierungstypen bezieht.
FATAL 1: user "andym" does not exist

Der angegebene Benutzer wurde nicht gefunden.
FATAL 1: Database "testdb" does not exist in the system catalog.

Die Datenbank, mit der Sie zu verbinden versuchen, existiert nicht. Beachten Sie, das wenn Sie keinen Benutzernamen angeben, der Benutzername als Datenbankname verwendet wird, was Sie vielleicht nicht beabsichtigt hatten.

285

Kapitel 19

Der Serverlog kann unter Umständen mehr Informationen über einen gescheiterten Authentifizierungsversuch enthalten als das, was an den Client geschickt wird. Wenn Sie also bei Authentifizierungsproblemen verwirrt sind, prüfen Sie den Log.

286

20

20

Lokalisierung

Dieses Kapitel beschreibt die verfügbaren Features zur Lokalisierung aus Sicht des Administrators. PostgreSQL unterstützt Lokalisierung mit drei Ansätzen: ❏ mit den Locale-Fähigkeiten des Betriebssystems, um sprachspezifische Sortierreihenfolgen, Zahlenformatierung, übersetzte Meldungen und andere Aspekte anzubieten ❏ durch eine Reihe verschiedener im PostgreSQL-Server definierter Zeichensätze, einschließlich Mehrbyte-Zeichensätze, um Text in allen möglichen Sprachen abspeichern zu können, und durch Konvertierung zwischen Zeichensätzen zwischen Client und Server ❏ Zeichensatzkonvertierung zwischen Einbyte-Zeichensätzen als effizientere Lösung für Benutzer, für die das ausreicht.

20.1

Locale-Unterstützung

Locale-Unterstützung bezieht sich darauf, dass Anwendungen die von einer bestimmten Kultur bevorzugten Bräuche für das Alphabet, die Sortierreihenfolge, Zahlenformate usw. respektieren. PostgreSQL verwendet die vom Serverbetriebssystem bereitgestellten Locale-Vorrichtungen entsprechend dem ISO-Cbzw. POSIX-Standard. Weitere Informationen dazu finden Sie auch in der Dokumentation Ihres Betriebssystems.

20.1.1 Überblick
Die Locale-Unterstützung wird automatisch initialisiert, wenn ein Datenbankcluster mit initdb erzeugt wird. initdb initialisiert den Datenbankcluster mit den Locale-Einstellungen aus seiner Umgebung; wenn also Ihr System schon die Locale verwendet, die Sie in Ihrem Datenbankcluster verwenden wollen, müssen Sie nichts weiter tun. Wenn Sie eine andere Locale verwenden wollen (oder Sie sich nicht sicher sind, welche Ihr System verwendet), können Sie initdb mit der Option --locale genau sagen, welche Locale Sie verwenden wollen. Zum Beispiel:
initdb --locale=sv_SE

Dieses Beispiel setzt die Locale auf Schwedisch (sv) wie es in Schweden (SE) gesprochen wird. Weitere Beispiele sind de_DE (Deutsch, Deutschland), en_US (Englisch, USA) oder fr_CA (Französisch, Kanada). Wenn mehr als ein Zeichensatz für eine Locale verwendet werden kann, sieht die Angabe so aus: 287

Kapitel 20

cs_CZ.ISO8859-2. Welche Locales auf Ihrem System vorhanden sind, hängt davon ab, was vom Hersteller zur Verfügung gestellt und installiert wurde.

Gelegentlich kann es nützlich sein, die Regeln aus mehreren Locales zu kombinieren, zum Beispiel englische Sortierreihenfolge aber spanische Meldungen. Um das zu ermöglichen, gibt es mehrere Locale-Subkategorien, die nur bestimmte Aspekte der Locale-Regeln kontrollieren.
LC_COLLATE LC_CTYPE

Zeichenketten-Sortierreihenfolge Zeichenklassifizierung (Was ist ein Buchstabe? Was ist der entsprechende Großbuchstabe?) Sprache der Meldungen Format für Geldbeträge Format für Zahlen Format für Datum und Zeit

LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME

Aus den Kategorienamen ergeben sich die Namen von Kommandozeilenoptionen für initdb, die die Locale-Wahl für eine bestimmte Kategorie einstellen. Um zum Beispiel die Locale auf Kanada/Französisch zu setzen, aber die Regeln von USA/Englisch zur Formatierung von Geldbeträgen auszuwählen, verwenden Sie initdb --locale=fr_CA --lc-monetary=en_US. Wenn Sie wollen, dass sich Ihr System so verhält, als hätte es keine Locale-Unterstützung, dann setzen Sie die Locale auf C oder POSIX. Bei einigen Locale-Kategorien steht der Wert für die gesamte Lebensdauer des Datenbankclusters fest. Das heißt, nachdem initdb ausgeführt wurde, können Sie ihn nicht mehr verändern. Diese Kategorien sind LC_COLLATE und LC_CTYPE. Sie beeinflussen die Sortierreihenfolge der Indexe und müssen daher konstant gehalten werden oder Indexe für Textspalten werden verfälscht und ungültig werden. PostgreSQL sorgt dafür, dass die Locale-Werte konstant bleiben, indem die von initdb gesehenen Werte von LC_COLLATE und LC_CTYPE gespeichert werden. Der Server stellt diese beiden Werte dann automatisch ein, wenn er gestartet wird. Die anderen Locale-Kategorien können, während der Server läuft, immer geändert werden, indem die Konfigurationsparameter mit den gleichen Namen wie die Locale-Kategorien eingestellt werden (siehe Abschnitt 16.4 wegen Einzelheiten). Die durch initdb gewählten Voreinstellungen werden nur in die Konfigurationsdatei postgresql.conf geschrieben, wo sie als Voreinstellungen dienen, wenn der Server gestartet wird. Wenn Sie die Zuweisungen aus postgresql.conf löschen, dann übernimmt der Server die Einstellungen aus der Umgebung. Beachten Sie, dass das Locale-Verhalten des Servers von den vom Server gesehenen Umgebungsvariablen abhängt und nicht von der Umgebung irgendeines Clients. Daher müssen Sie darauf achten, dass Sie die Locale-Einstellungen tätigen, bevor Sie den Server starten. Daraus folgt auch, wenn der Server und der Client verschiedene Locales verwenden, können Meldungen in verschiedenen Sprachen erscheinen, je nachdem, woher sie stammen. Wenn wir davon reden, dass die Locale aus der Umgebung übernommen wird, bedeutet das auf den meisten Betriebssystemen Folgendes: Für eine gegebene Locale-Kategorie, sagen wir die Sortierreihenfolge, werden die folgenden Umgebungsvariablen in dieser Reihenfolge untersucht, bis eine gefunden wird, die gesetzt ist: LC_ALL, LC_COLLATE (die Variable, die der Kategorie entspricht) und LANG. Wenn keine dieser Umgebungsvariablen gesetzt ist, ist die voreingestellte Locale C. Manche Bibliotheken zur Übersetzung von Programmmeldungen betrachten auch die Umgebungsvariable LANGUAGE, welche alle anderen Locale-Einstellungen für die Sprache von Programmmeldungen übergeht. Wenn Sie sich nicht sicher sind, dann schauen Sie bitte in der Dokumentation Ihres Betriebssystems nach, insbesondere in der Anleitung zu Gettext.

288

Lokalisierung

Um Mitteilungen in der vom Benutzer bevorzugten Sprache anzeigen zu können, muss NLS beim Compilieren angeschaltet worden sein. Diese Wahl ist unabhängig von der anderen Locale-Unterstützung.

20.1.2 Nutzen
Locale-Unterstützung hat insbesondere Auswirkung auf die folgenden Aspekte: ❏ Sortierreihenfolge in Anfragen mit ORDER BY ❏ die Funktionsfamilie to_char ❏ die Operatoren LIKE und ~ für Mustervergleiche Der einzige schwerwiegende Nachteil der Locale-Unterstützung in PostgreSQL ist die Geschwindigkeit. Also verwenden Sie Locales nur, wenn Sie sie wirklich benötigen. Man sollte anmerken, dass die Auswahl einer anderen Locale außer C die Verwendung eines Index für die Operatoren LIKE und ~ verhindert, was für die Geschwindigkeit von Anfragen, die diese Operatoren verwenden, einen gewaltigen Unterschied machen kann.

20.1.3 Probleme
Wenn die Locale-Unterstützung trotz der Erklärung oben nicht funktioniert, überprüfen Sie, ob die Locale-Unterstützung in Ihrem Betriebssystem richtig läuft. Um zu sehen, welche Locales auf Ihrem System installiert sind, können Sie den Befehl locale -a verwenden, wenn Ihr Betriebssystem ihn zur Verfügung stellt. Überprüfen Sie, ob PostgreSQL tatsächlich die Locale verwendet, die Sie denken. Die Einstellungen von LC_COLLATE und LC_CTYPE werden von initdb gemacht und können später nicht geändert werden ohne initdb zu wiederholen. Die anderen Locale-Kategorien werden anfänglich von der Umgebung, in der der Server gestartet wird, bestimmt. Die Einstellungen von LC_COLLATE und LC_CTYPE können Sie mit dem Hilfsprogramm pg_controldata einsehen. Das Verzeichnis src/test/locale in der Quellendistribution enthält einige Tests für die Locale-Unterstützung in PostgreSQL. Clientanwendungen, die Serverfehler verarbeiten, indem Sie den Text der Meldung analysieren, werden natürlich Probleme haben, wenn die Meldungen des Servers in einer anderen Sprache sind. Wenn Sie so eine Anwendung entwickeln, müssen Sie einen Plan aufstellen, um mit dieser Situation fertig zu werden. Die Schnittstelle ECPG (eingebettetes SQL) ist von diesem Problem auch betroffen. Wenn ein Server mit ECPG-Anwendungen kommunizieren muss, wird gegenwärtig empfohlen, dass er so konfiguriert wird, dass er Meldungen auf Englisch schickt. Die Pflege von Katalogen mit Übersetzungen der Programmmeldungen erfordert die andauernden Bemühungen vieler Freiwilliger, die wollen, dass PostgreSQL ihre bevorzugte Sprache gut sprechen kann. Wenn die Meldungen in einer Sprache gegenwärtig nicht angeboten werden oder nicht vollständig übersetzt sind, würde Ihre Hilfe sehr geschätzt werden. Wenn Sie helfen wollen, schreiben Sie an die Entwicklermailingliste.

20.2 Zeichensatz-Unterstützung
Die Zeichensatzunterstützung in PostgreSQL ermöglicht Ihnen, Text in vielfältigen Zeichensätzen zu speichern, einschließlich Einbyte-Zeichensätze wie die ISO-8859-Serie und Mehrbyte-Zeichensätze wie EUC (Extended Unix Code), Unicode und Mule Internal Code. Alle Zeichensätze können transparent im ganzen Server verwendet werden. (Wenn Sie Erweiterungsfunktionen aus anderen Quellen verwenden, hängt es davon ab, ob die Autoren ihren Code richtig geschrieben haben.) Der Standardzeichensatz wird

289

Kapitel 20

gewählt, wenn der PostgreSQL-Datenbankcluster mit initdb initialisiert wird. Er kann übergangen werden, wenn eine Datenbank mit createdb oder dem SQL-Befehl CREATE DATABASE erzeugt wird. Sie können also mehrere Datenbanken mit jeweils einem anderen Zeichensatz haben.

20.2.1 Unterstützte Zeichensätze
Tabelle 20.1 zeigt die im Server zur Verfügung stehenden Zeichensätze. Server-Zeichensätze
Name
SQL_ASCII EUC_JP EUC_CN EUC_KR JOHAB EUC_TW UNICODE MULE_INTERNAL LATIN1 LATIN2 LATIN3 LATIN4 LATIN5 LATIN6 LATIN7 LATIN8 LATIN9 LATIN10 ISO-8859-5 ISO-8859-6 ISO-8859-7 ISO-8859-8 KOI8 WIN ALT WIN1256 TCVN WIN874

Beschreibung ASCII Japanischer EUC Chinesischer EUC Koreanischer EUC Koreanischer EUC (Basis-Hangul) Taiwanischer EUC Unicode (UTF-8) Mule Internal Code ISO 8859-1/ECMA 94 (Lateinisches Alphabet Nr.1) ISO 8859-2/ECMA 94 (Lateinisches Alphabet Nr.2) ISO 8859-3/ECMA 94 (Lateinisches Alphabet Nr.3) ISO 8859-4/ECMA 94 (Lateinisches Alphabet Nr.4) ISO 8859-9/ECMA 128 (Lateinisches Alphabet Nr.5) ISO 8859-10/ECMA 144 (Lateinisches Alphabet Nr.6) ISO 8859-13 (Lateinisches Alphabet Nr.7) ISO 8859-14 (Lateinisches Alphabet Nr.8) ISO 8859-15 (Lateinisches Alphabet Nr.9) ISO 8859-16/ASRO SR 14111 (Lateinisches Alphabet Nr.10) ISO 8859-5/ECMA 113 (Lateinisch/Kyrillisch) ISO 8859-6/ECMA 114 (Lateinisch/Arabisch) ISO 8859-7/ECMA 118 (Lateinisch/Griechisch) ISO 8859-8/ECMA 121 (Lateinisch/Hebräisch) KOI8-R(U) Windows CP1251 Windows CP866 Windows CP1256 (Arabisch) TCVN-5712/Windows CP1258 (Vietnamesisch) Windows CP874 (Thai)

Tabelle 20.1: Server-Zeichensätze

290

Lokalisierung

Wichtig
Vor PostgreSQL 7.2 stand LATIN5 fälschlicherweise für ISO 8859-5. Seit 7.2 bedeutet LATIN5 richtig ISO 8859-9. Wenn Sie eine mit Version 7.1 oder früher erzeugte Datenbank in LATIN5 haben und auf 7.2 oder später umsteigen wollen, sollten Sie auf diese Änderung achten. Nicht alle Schnittstellen unterstützen alle aufgelisteten Zeichensätze. Der JDBC-Treiber von PostgreSQL unterstützt zum Beispiel nicht MULE_INTERNAL, LATIN6, LATIN8 oder LATIN10.

20.2.2 Den Zeichensatz einstellen
initdb bestimmt den Standardzeichensatz eines PostgreSQL-Datenbankclusters. Zum Beispiel: initdb -E EUC_JP

Das setzt den Standardzeichensatz (die Kodierung) auf EUC_JP (Extenden Unix Code für Japanisch). Sie können --encoding anstatt -E verwenden, wenn Sie lieber die langen Optionen eingeben. Wenn weder -E noch --encoding angegeben wird, dann wird SQL_ASCII verwendet. Sie können eine Datenbank mit einem anderen Zeichensatz erzeugen:
createdb -E EUC_KR korean

Das erzeugt eine Datenbank namens korean, die den Zeichensatz EUC_KR verwendet. Das Gleiche kann man auch mit diesem SQL-Befehl erreichen:
CREATE DATABASE korean WITH ENCODING 'EUC_KR';

Die Kodierung der Datenbank wird im Systemkatalog pg_database gespeichert. Sie können sich diese Informationen zum Beispiel mit der Option -l oder dem Befehl \l in psql ansehen.
$ psql -l List of databases Database | Owner | Encoding ---------------+---------+--------------euc_cn | t-ishii | EUC_CN euc_jp | t-ishii | EUC_JP euc_kr | t-ishii | EUC_KR euc_tw | t-ishii | EUC_TW mule_internal | t-ishii | MULE_INTERNAL regression | t-ishii | SQL_ASCII template1 | t-ishii | EUC_JP test | t-ishii | EUC_JP unicode | t-ishii | UNICODE (9 rows)

291

UNICODE EUC_TW. Die Konvertierungsinformationen werden im Systemkatalog pg_conversion gespeichert. KOI8 ISO_8859_6. UNICODE ISO_8859_8. UNICODE WIN874. MULE_INTERNAL EUC_KR.Kapitel 20 20. UNICODE. WIN. UNICODE. UNICODE MULE_INTERNAL KOI8 WIN ALT WIN1256 TCVN WIN874 Tabelle 20. ALT. MULE_INTERNAL LATIN8. ALT. UNICODE. WIN1250 EUC_JP. MULE_INTERNAL WIN1256. MULE_INTERNAL ISO_8859_5. UHC. SJIS. UNICODE. Neuen Konversionen können Sie mit dem SQL-Befehl CREATE CONVERSION erzeugen. BIG5. UNICODE. BIG5. MULE_INTERNAL. UNICODE LATIN6. UNICODE. UNICODE EUC_JP. EUC_CN. SJIS. LATIN1 to LATIN5. WIN1250. MULE_INTERNAL LATIN4. BIG5. ISO_8859_8. EUC_CN. Server-Zeichensatz SQL_ASCII EUC_JP EUC_CN EUC_KR JOHAB EUC_TW LATIN1 LATIN2 LATIN3 LATIN4 LATIN5 LATIN6 LATIN7 LATIN8 LATIN9 LATIN10 ISO_8859_5 ISO_8859_6 ISO_8859_7 ISO_8859_8 UNICODE Verfügbare Client-Zeichensätze SQL_ASCII. EUC_TW. WIN874. WIN. KOI8 ISO_8859_5. UNICODE. UNICODE MULE_INTERNAL LATIN2. GB18030. KOI8. MULE_INTERNAL LATIN7. ALT. BIG5.2. MULE_INTERNAL ISO_8859_5. ALT. UNICODE. UNICODE. MULE_INTERNAL JOHAB. ALT. Diese sind in Tabelle 20. MULE_INTERNAL LATIN10. UNICODE. EUC_KR. JOHAB. PostgreSQL enthält einige vordefinierte Konversionen. UNICODE. WIN. ISO_8859_6.2 aufgeführt. WIN. UNICODE. WIN1256. GBK. MULE_INTERNAL LATIN5. MULE_INTERNAL LATIN3. TCVN. EUC_KR. EUC_TW. ISO_8859_5. MULE_INTERNAL EUC_CN. ISO_8859_7. WIN. WIN. LATIN1 to LATIN10. MULE_INTERNAL LATIN1. ALT.3 Automatische Zeichensatzkonvertierung zwischen Client und Server PostgreSQL unterstützt die automatische Zeichensatzkonvertierung zwischen Client und Server für bestimmte Zeichensätze. UNICODE. KOI8. UNICODE. MULE_INTERNAL EUC_JP. MULE_INTERNAL ISO_8859_5. UNICODE. SJIS. WIN1250. UNICODE TCVN. ISO_8859_5. KOI8. UNICODE. UNICODE ISO_8859_7. MULE_INTERNAL LATIN9.2: Client/Server-Zeichensatzkonversionen 292 . KOI8. UNICODE.

(Nachher kann Sie mit einer der oben genannten Methoden geändert werden. Um zum Beispiel die Kodierung auf SJIS zu setzen.Lokalisierung Um die automatische Zeichensatzkonvertierung zu ermöglichen. können einige japanische Zeichen nicht in LATIN1 übertragen werden. welchen Zeichensatz (welche Kodierung) Sie im Client verwenden wollen. wenn eine Verbindung zum Server aufgebaut wird. \encoding selbst ruft intern PQsetClientEncoding() auf. Mit \encoding können Sie die Clientkodierung jederzeit ändern.) ❏ Mit dem Konfigurationsparameter client_encoding. verwenden Sie: SHOW CLIENT_ENCODING. wird diese Clientkodierung automatisch ausgewählt. const char *encoding). Um die Nummer in einen Zeichensatznamen umzuwandeln. geben Sie ein: \encoding SJIS ❏ Mit libpq-Funktionen. Der aktuelle Zeichensatz einer Verbindung kann mit der Funktion ermittelt werden: int PQclientEncoding(const PGconn *conn). Beachten Sie. zum Beispiel (826C). müssen Sie PostgreSQL mitteilen. dies zu erreichen: ❏ Mit dem Befehl \encoding in psql. Sie wählen EUC_JP für den Server und LATIN1 für den Client. ❏ Mit PGCLIENTENCODING. nicht einen Namen wie EUC_JP. Um die aktuelle Kodierung anzuzeigen. wird diese Kodierung automatisch ausgewählt. Wenn der Parameter client_encoding in postgresql. Die Clientkodierung kann mit diesem SQL-Befehl gesetzt werden: SET CLIENT_ENCODING TO 'wert'. ansonsten -1.) Wenn die Konvertierung eines bestimmten Zeichens nicht möglich ist – nehmen wir an. Sie können dafür auch die etwas SQL-konformere Syntax SET NAMES verwenden: SET NAMES 'wert'. Wenn die Funktion den Zeichensatz erfolgreich gesetzt hat. verwenden Sie: RESET CLIENT_ENCODING. Wenn die Umgebungsvariable PGCLIENTENCODING in der Umgebung des Clients gesetzt ist. Es gibt mehrere Möglichkeiten.conf gesetzt ist. ergibt sie 0. wobei conn eine Verbindung zum Server ist und encoding der gewünschte Zeichensatz. int PQsetClientEncoding(PGconn *conn. (Nachher kann Sie mit einer der oben genannten Methoden geändert werden. können Sie diese Funktion verwenden: char *pg_encoding_to_char(int encoding_id). wenn eine Verbindung zum Server aufgebaut wird. ❏ Mit SET CLIENT_ENCODING TO. dass diese Funktion die interne Nummer des Zeichensatzes zurückgibt. 293 . Um zur Standardkodierung zurückzukehren. wird das Zeichen durch seine hexadezimalen Bytewerte in Klammern dargestellt.

wenn Sie auf einem Client mehrere Betriebssysteme booten. 192. ftp://ftp. was aber nicht ihre vollen Fähigkeiten beschreibt. Man kann damit alle Einbyte-Zeichensätze konvertieren lassen.B.100/24. HostCharset-Sätze legen die Client-Zeichensätze nach IP-Adresse fest. um über die verschiedenen Zeichensatzsysteme etwas zu erfahren. 294 .inf In Abschnitt 3.3 Einbyte-Zeichensatz-Konvertierung Dieses Feature können Sie mit der configure-Option --enable-recode einschalten. Da diese Lösung auf den IP-Adressen der Clients aufbaut. Es wird auch unbequem. Sie können eine einzelne IPAdresse. und Zeichenkonversionen werden durch ein Paar dezimaler oder hexadezimaler (mit vorgestelltem 0x) Werte auf einzelnen Zeilen dargestellt: zeichenwert konvertierter_zeichenwert Im Verzeichnis src/data/ in der Quellendistribution können Sie ein Beispiel für die Datei charset. RecodeTable-Sätze bestimmen Konvertierungstabellen zwischen Server und Client. Diese Methode verwendet eine Datei charset. Wenn diese Einschränkungen Sie aber nicht stören und Sie keine Mehrbyte-Zeichen benötigen.1. eine IP-Maske über eine Adresse oder eine Spanne von IP-Adressen verwenden (z. 127. Die Datei charset.conf im Datenverzeichnis zur Konfiguration.168.org/ Die Website des Unicode Consortium RFC 2044.conf und ein paar Konvertierungstabellen finden. Der Dateiname ist relativ zum Datenverzeichnis. gibt es offensichtlich auch einige Einschränkungen. Sie können also tippfreundliche Namen wählen. Drei Schlüsselwörter mit folgender Syntax werden erkannt: BaseCharset server_zeichensatz RecodeTable quell_zeichensatz ziel_zeichensatz dateiname HostCharset host_angabe host_zeichensatz BaseCharset definiert den Zeichensatz des Datenbankservers. Hier wird UTF-8 definiert.168.1.1.unicode. 20. Diese Option wurde früher als “Kyrillische Rekodierungs-Unterstützung” bezeichnet. Diese ist eine übliche Text-Konfigurationsdatei. Das Format der Tabellendatei ist sehr einfach.ora.Kapitel 20 20. so dass Sie einfach Ausnahmen von vorangehenden Regeln bestimmen können. EUC_CN. EUC_KR und EUC_TW.1. in der Leerzeichen und Newlines Felder und Datensätze trennen und mit # ein Kommentar anfängt. Sie können nicht auf einem Host zur gleichen Zeit mehrere Zeichensätze verwenden.0. Es gibt keine Schlüsselwörter.conf verwendet.4 Weitere Informationsquellen Hier sind ein paar gute Quellen.conf wird immer bis zum Ende verarbeitet. 192.40).168.0.2 gibt es detaillierte Beschreibungen von EUC_JP. dann ist dies eine einfache und effektive Lösung.com/pub/examples/nutshell/ujip/doc/cjk.20-192. Alle Zeichensatznamen werden nur intern in charset.2. http://www.

Dieser Abschnitt konzentriert sich auf das Erklären der allgemeinen Problematik. ist die Verwaltung der Logdateien.21 21 Routinemäßige Datenbankwartungsaufgaben Es gibt einige wenige routinemäßige Wartungsaufgaben. Einzelheiten der Befehlssyntax und so weiter finden Sie auf der VACUUM-Referenzseite. das regelmäßige Aufmerksamkeit erfordert. Noch etwas. Wenn Sie den sich stellenden Aufgaben nichtsdestoweniger die angebrachte Aufmerksamkeit widmen. haben Sie keine Chance. nach einer Katastrophe (Festplattenausfall. die durchgeführt werden müssen. um sich gegen den Verlust sehr alter Daten durch Überlauf der Transaktionsnummern zu schützen.3 besprochen.1 besprochen. die passenden Skripts einzurichten und zu überwachen. dann werden Sie dadurch Ihre Arbeit mit dem System angenehmer und produktiver gestalten. Ohne eine Sicherungskopie. 295 . Eine offensichtliche Wartungsaufgabe ist die regelmäßige Erstellung von Sicherungskopien der Daten. dass sie erfolgreich ausgeführt werden. Die andere Hauptaufgabe der Wartung ist das regelmäßige Vacuum (zu Deutsch “Staubsaugen”) der Datenbank. Dieses Thema wird in Abschnitt 21.1 Routinemäßiges Vacuum In PostgreSQL muss aus mehreren Gründen regelmäßig der Befehl VACUUM ausgeführt werden: 1. Die Häufigkeit und das Ausmaß der aus jedem dieser Gründe ausgeführten VACUUM-Operationen hängt von der individuellen Situation ab. Verglichen mit anderen Datenbankprodukten hat PostgreSQL einen geringen Wartungsaufwand. um den von aktualisierten oder gelöschten Zeilen belegten Speicherplatz wiederzugewinnen 2. Datenbankadministratoren müssen daher diese Angelegenheiten verstehen und eine passende Wartungsstrategie entwickeln. Die hier beschriebenen Aufgaben müssen regelmäßig wiederholt werden und können leicht mit normalen Unix-Werkzeugen wie cron automatisiert werden. um die vom PostgreSQL-Anfrageplaner verwendeten Datenstatistiken zu aktualisieren 3. Das wird in Abschnitt 21. Aber es liegt in der Verantwortung des Datenbankadministrators. Feuer. die auf dem letzten Stand ist. Die in PostgreSQL verfügbaren Datensicherungs.und wiederherstellungsmechanismen werden ausführlich in Kapitel 22 besprochen.) Ihre Daten wiederherstellen zu können. damit ein PostgreSQL-Server problemlos laufen kann. aus Versehen eine wichtige Tabelle gelöscht usw. 21.

aber sie versucht nicht zu sehr die Tabellendatei zu verkürzen und den Platz an das Betriebssystem zurückzugeben. Routinemäßiges Vacuum ist daher kein so großer Einschnitt in die Datenbankoperation mehr. sollten Sie in Erwägung ziehen. Wenn Sie Platz an das Betriebssystem zurückgeben wollen. wenn Sie wissen. der nur in ausgewählten Tabellen VACUUM ausführt und Tabellen. einen relativ stabilen Festplattenplatzverbrauch zu erhalten.1.1 Speicherplatz wiedergewinnen In PostgreSQL wird bei einem UPDATE oder DELETE einer Zeile die alte Zeilenversion nicht sofort entfernt. ist nicht groß genug.1. solange sie potenziell noch in anderen Transaktionen sichtbar ist. VACUUM in jeder einzelnen auszuführen. die selten verändert werden. um zu verhindern. wenn wenig Betrieb ist. Aber selbst bei oft aktualisierten Tabellen muss es nicht unbedingt notwendig sein. Für die meisten Anwender wird empfohlen. aber nicht Änderungen an der Tabellendefinition) laufen. VACUUM für die ganze Datenbank auszuführen und als Ergänzung. Die Standardform vom VACUUM wird am besten mit dem Ziel angewendet. Diese Statistiken werden vom Befehl ANALYZE zusammengetragen. nicht VACUUM FULL. Es könnte hilfreich sein. dass die Speicherplatzanforderungen ins Unendliche wachsen. Aktualisieren. für oft aktualisierte Tabellen nützlicher als für selten aktualisierte. Aber irgendwann wird sich keine Transaktion mehr für eine alte oder gelöschte Zeilenversion interessieren. wenn Sie große oft aktualisierte und große selten aktualisierte Tabellen haben. einigermaßen genaue Statistiken zu haben. um gute Pläne für Anfragen erzeugen zu können. anstatt DELETE gefolgt von VACUUM zu verwenden. ansonsten kann die schlechte Wahl von Plänen die Datenbankleistung beeinträchtigen. Dieses Verhalten ist notwendig um das Multiversionssystem für den Mehrbenutzerbetrieb zu ermöglichen (siehe Kapitel 12): Die Zeilenversion darf nicht gelöscht werden.2 kann die Standardform von VACUUM parallel mit normalen Datenbankoperationen (Anfragen. sodass die stabile Größe der Tabelle mit dem aggressiveren Ansatz von VACUUM FULL erheblich verringert werden kann. können Sie VACUUM FULL verwenden – aber welchen Sinn hat es. häufigeres Vacuum von oft aktualisierten Tabellen. und es ist auch nicht mehr so wichtig. der alleine oder als zusätzlicher Schritt in VACUUM aufgerufen werden kann. dass Sie die Mehrzahl der Zeilen in einer Tabelle gelöscht haben. für routinemäßiges Vacuum zur Platzwiedergewinnung. Das wird von VACUUM erledigt. (Wenn Sie mehrere Datenbanken in einem Cluster haben. Aber das ist wahrscheinlich nur sinnvoll. um sich darüber Gedanken zu machen. Es ist wichtig. Festplattenplatz an das Betriebssystem zurückzugeben. VACUUM FULL ist zu empfehlen. um VACUUM in einer kleinen Tabelle auszuführen. es an Tageszeiten mit niedriger Belastung auszuführen. Löschen.2 Planerstatistiken aktualisieren Der PostgreSQL-Anfrageplaner benötigt statistische Informationen über den Inhalt der Tabellen. denn der zusätzliche Aufwand. einmal am Tag. wie beim Vacuum zur Platzgewinnung. wenn nötig. auslässt. der sowieso bald wieder verwendet werden muss? Einigermaßen häufige VACUUM-Läufe in der Standardform sind für oft aktualisierte Tabellen ein besserer Ansatz als seltene VACUUM FULL-Läufe. deren Inhalt ab und zu komplett gelöscht wird.) Verwenden Sie das einfache VACUUM. Einfügen. Wenn Sie eine Tabelle haben. von denen bekannt ist. 21. Eine Tabelle. einen cron-Auftrag zu registrieren. Die Standardform findet alte Zeilenversionen und macht deren Platz für die Wiederverwendung in der Tabelle verfügbar. in der oft aktualisiert oder gelöscht wird. dass sie sich nicht oft ändern. wie es in früheren Versionen war. das Programm vacuumdb kann da hilfreich sein. wenn sich die statistische Verteilung kaum ver- 296 . das mit TRUNCATE zu tun. muss also offensichtlich öfter “gevacuumt” werden als Tabellen. vergessen Sie nicht. Häufiges Aktualisieren der Statistiken ist. Der davon belegte Platz muss für die Wiederverwendung durch neue Zeilen wiedergewonnen werden. die Statistiken zu aktualisieren.Kapitel 21 Seit PostgreSQL 7. 21.

es einfach ab und zu für die ganze Datenbank auszuführen.Routinemäßige Datenbankwartungsaufgaben ändert.2 ist ANALYZE sogar bei großen Tabellen ziemlich schnell. wenn es die Anwendung erfordert. das Ausmaß der gesammelten Statistiken einzustellen. Seit PostgreSQL 7. aber da die Konsequenz. die “älter”. wenn man sich nicht daran hält. sich zu überlegen. Nummer 1 und 2 (BootstrapXID und FrozenXID). Kurz gesagt würden Sie die totale Datenverlustkatastrophe erleben. wie sehr sich die Minimal. Diese beiden XIDs werden immer als älter als alle anderen XIDs betrachtet. ist “in der Zukunft” und sollte für die aktuelle Transaktion nicht sichtbar sein. die Zeit seit dem letzten VACUUM zu verfolgen. die “neuer” sind. Der Preis dafür ist diese Wartungsanforderung: Jede Tabelle in der Datenbank muss mindestens einmal alle eine Milliarde Transaktionen gevacuumt werden. sagen wir. zum Transaktionsnummernüberlauf kommen: Der XIDZähler fängt wieder bei null an und plötzlich werden Transaktionen aus der Vergangenheit so aussehen. Der neue Ansatz erlaubt es. Anwender mit Tabellenstatistiken. um den Datenbankadministratoren zu helfen. dass deren Ergebnisse unsichtbar werden. kann es in einem Cluster. Das bedeutet. die größer als die XID der aktuellen Transaktion ist.) Vor PostgreSQL 7. (Die Daten sind eigentlich noch da. Da aber Transaktionsnummern eine begrenzte Größe haben (gegenwärtig 32 Bits). aber das ist sicherlich nicht sehr beruhigend. ANALYZE kann man auch für bestimmte Tabellen und sogar nur für bestimmte Spalten einer Tabelle aus- geführt werden. und zwei Milliarden. eine Spalte. könnten jedoch zu der Feststellung gelangen. dass es für jede normale XID zwei Milliarden XIDs. In der Praxis ist der Nutzen dieser Fähigkeit allerdings zweifelhaft. weil es nur eine zufällige Auswahl der Tabellenzeilen verwendet. Tipp Obwohl ein verschieden häufiges ANALYZE für verschiedene Spalten in der Regel nicht sehr produktiv ist. Spalten. anstatt jede einzelne Zeile zu lesen. wenn man nicht auf sie zugreifen kann. dass man mindestens alle 4 Milliarden Transaktionen initdb neu ausführt. Eine timestamp-Spalte. wurden einige besondere Vorkehrungen errichtet. der eine lange Zeit läuft (mehr als 4 Milliarden Transaktionen). Sehen Sie bei ALTER TABLE SET STATISTICS nach. Dieser Weg war für Anwendungen mit viel Betrieb nicht zufriedenstellend und daher wurde eine bessere Lösung erdacht. sodass man einige Statistiken öfter als andere aktualisieren kann. könnten ein detaillierteres Datenhistogramm gebrauchen als andere. die sich relativ langsam verändern. ANALYZE einmal am Tag.und Maximalwerte in den Tabellenspalten ändern. die speichert. hat einen ständig steigenden Maximalwert. Für die meisten Anwender wird empfohlen. zum Beispiel. gibt. kompletter Datenverlust sein kein (nicht nur verschwendeter Speicherplatz oder schlechte Leistung). Es ist also wahrscheinlich viel einfacher. als ob sie in der Zukunft wären. die die Zeit der letzten Zeilenaktualisierung enthält. das kann am besten mit einem nächtlichen VACUUM verbunden werden. was bedeutet. für die ganze Datenbank auszuführen. welche URLs einer Website abgerufen wurden. so eine Spalte benötigt wahrscheinlich häufigeres Aktualisieren der Statistik als. aber die statistische Verteilung der Werte ändert sich wahrscheinlich nur sehr langsam. wenn wenig Betrieb ist. dass das übertrieben ist und dass weniger häufige ANALYZE-Läufe ausreichend sind. 21. dass der Server endlos laufen kann.1. Der neue Ansatz beim XID-Vergleich kennt zwei besondere XIDs. In der Praxis ist das keine besonders umständliche Forderung. Der Rest dieses Abschnitts gibt dazu Einzelheiten. die oft in WHERE-Klauseln verwendet werden und sehr unregelmäßige Datenverteilungen haben.2 war die einzige Verteidigung gegen Transaktionsnummernüberlauf. Am einfachsten ist es. Die URL-Spalte mag sich vielleicht genauso oft ändern.3 Transaktionsnummernüberlauf verhindern Im MVCC-System von PostgreSQL spielt das Vergleichen von Transactionsnummern (XID) eine wichtige Rolle: Eine Zeilenversion mit einer Einfügungs-XID. anders ausge- 297 . ohne initdb oder irgendeinen Neustart. kann es sehr wohl sinnvoll sein. Normale XIDs (die größer als 2) werden mit Arithmetik modulo 231 verglichen.

dass diese Beschränkung eingehalten wird. um in allen offenen Transaktionen gültig zu sein. Diese Neuzuweisung der XID wird von VACUUM erledigt. die älter als der Grenzwert sind. aber das hilft Ihnen sicher nicht weiter. speichert VACUUM Transaktionsnummernstatistiken in der Systemtabelle pg_database. wenn irgendein pg_database-Eintrag für age mehr als 1. bevor Sie zwei Milliarden Transaktionen alt werden. ist es unwahrscheinlich. um die Datenbank 298 . Wenn age sich zwei Milliarden nähert. bis sie wahrscheinlich nicht mehr von Interesse ist. Wenn dann die Datenbank nicht weiter verändert wird. muss sie auch nicht mehr gevacuumt werden. wenn VACUUM FREEZE in einer ansonsten gerade unbenutzten Datenbank durchgeführt wird. Better vacuum them within 533713463 transactions. in jeder Datenbank mindestens alle halbe Milliarde (500 Millionen) Transaktionen VACUUM auszuführen. wie lange das sein wird. VACUUM VACUUM mit der Option FREEZE verfolgt eine aggressivere Strategie beim Einfrieren: Zeilenversionen werden eingefroren. dann werden Sie für alle normalen Transaktionen als “in der Vergangenheit” erscheinen. und daher werden sie bis zum Löschen gültig bleiben. dass alle Zeilenversionen in dieser Datenbank eingefroren werden. (Die meisten Zeilenversionen werden wahrscheinlich entstehen und verschwinden. folgende Anfrage auszuführen: SELECT datname.h. gibt jedes datenbankweite VACUUM automatisch eine Warnung aus. scheint sie für die nächsten zwei Milliarden Transaktionen als “in der Vergangenheit”. das keine bestimmte Tabelle benennt) aktualisiert. sich diese Information anzusehen. kann es sein. Wenn ihnen einmal diese besondere XID zugewiesen wurde. Die normale Strategie von VACUUM ist es. dann erscheint sie plötzlich in der Zukunft zu sein. Wenn daher eine Zeilenversion mit einer bestimmten XID erzeugt worden ist. dass eine Zeilenversion. sie ist für Sie verloren. Dadurch wird die originale EinfügungsXID so lange erhalten. deren XID mehr als eine Milliarde Transaktionen in der Vergangenheit liegt.) Da regelmäßige VACUUM-Läufe aus den schon beschriebenen Gründen sowieso nötig sind. Um aber Administratoren zu helfen. dass eine Tabelle eine ganze Milliarde Transaktionen in diese nicht mit einbezogen würde. um Überlaufprobleme zu vermeiden. ist. jetzt zu alt ist und in der Zukunft liegt. Wir empfehlen. egal welche normale XID es ist. um Problemen mit Transaktionsnummernüberlauf zu begegnen. ohne jemals “eingefroren” zu werden. or you may have a wraparound failure. dieser Regel zu folgen. Ein bequemer Weg. um umnummeriert zu werden. Wenn die Zeilenversion nach mehr als zwei Milliarden Transaktionen noch existiert. ist garantiert. Diese Technik wird von initdb verwendet. muss alten Zeilenversionen irgendwann die XID FrozenXID zugewiesen werden (sie müssen also quasi “eingefroren” werden). zum Beispiel: play=# VACUUM.5 Milliarden Transaktionen zeigt. Das hieße. muss VACUUM bald wieder ausgeführt werden.) Mit dieser Strategie ist der höchste sichere Zeitraum zwischen VACUUM-Läufen für eine Tabelle genau eine Milliarde Transaktionen: Wenn Sie länger warten. ungeachtet der Überlaufproblematik. age(datfrozenxid) FROM pg_database. Insbesondere wird die Spalte datfrozenxid der zu einer Datenbank gehörigen pg_database-Zeile am Ende jeder datenbankweiten VACUUMOperation (d. Mit der Standardstrategie fängt die Spalte age in einer Datenbank direkt nach einem VACUUM bei einer Milliarde an. Insbesondere gilt.Kapitel 21 drückt ist der Raum der normalen XIDs kreisförmig ohne Endpunkte. Um Datenverlust zu vermeiden. egal. damit reichlich Sicherheitsspielraum bleibt. WARNING: Some databases have not been vacuumed in 1613770184 transactions. sind in jener Datenbank garantiert durch FrozenXID ersetzt worden. VACUUM. die beim letzten Mal noch nicht alt genug war. wenn sie alt genug sind. Der in diesem Feld gespeicherte Wert ist quasi die vom letzten VACUUM verwendete Einfriergrenze: Alle normalen XIDs. (Natürlich wird sie nach weiteren zwei Milliarden Transaktionen wieder auftauchen. Die Spalte age misst die Anzahl der Transaktionen von jenem Grenzwert bis zur XID der aktuellen Transaktion. Um Ihnen zu helfen. die FrozenXID jeder Zeilenversion zuzuweisen.

wenn indizierte Zeilen gelöscht werden. daher müssen Sie selbst darauf achten. wenn Sie stderr von postmaster per Pipe mit einem Logrotierprogramm verbinden. Sie sollte auch für Datenbanken verwendet werden. da man in Datenbanken. 21. 299 . Wenn Sie den Server mit pg_ctl starten. Als Lösung können Sie regelmäßig den Befehl REINDEX ausführen. dass solche Datenbanken ordnungsgemäß eingefroren werden. dass VACUUM für Datenbanken mit datallowconn = false keine automatischen Warnungen über einen zu langen Zeitraum seit dem letzten VACUUM ausgibt. wird stderr von postmaster automatisch an stdout umgeleitet. Beachten Sie.conf auf 2 (um nur mit Syslog zu loggen). was die ganze Datenbank reindizieren kann. aber im Internet werden Sie eine Auswahl finden. setzen Sie den Konfigurationsparameter Syslog in postgresql. In solchen Fällen wächst der von dem Index belegte Platz auf der Festplatte ins Endlose. aber einen Produktionsserver sollten Sie so nicht laufen lassen. Dann ist es vielleicht angebrachter. sie an Syslog zu schicken und die Dateirotierung Syslog zu überlassen. Wenn Sie einfach den stderr von postmaster in eine Datei umleiten. indem Sie den Server anhalten und wieder neu starten. Die Logausgabe kann jedoch ziemlich umfangreich werden (besonders bei einer Einstellung mit viel Debugausgaben) und man will sie in der Regel nicht endlos lange aufbewahren. Daher müssen Sie die Logdateien “rotieren”. Wenn zum Beispiel indizierte Zeilen gelöscht werden und die neu eingefügten/ aktualisierten Zeilen viel höhere Werte haben. 21. damit neue Logdateien angefangen und alte ab und zu weggeworfen werden. auch kein VACUUM ausführen kann. anstatt sie einfach an /dev/null zu schicken. damit für solche Datenbanken keine falschen Warnungen ausgegeben werden. wenn man Sie sie am meisten benötigt. besonders bei großen Logmeldungen. Auf vielen Systemen ist Syslog jedoch nicht sehr zuverlässig. Außerdem gibt es contrib/reindexdb. B-Tree-Indexseiten wiederzuverwenden. die Logausgabe des Servers irgendwo zu speichern. Dann können Sie an den Syslog-Daemon das Signal SIGHUP schicken. wenn man Probleme diagnostizieren muss. Solche neuen Zeilen müssen vielmehr in neuen Indexseiten abgelegt werden. können diese Indexseiten nur von Zeilen mit ähnlichen Werten wiederverwendet werden. zum Beispiel gibt es in der Apache-Distribution eins. Das Problem ist. mit denen man nicht verbinden kann. können Sie die Logdatei nur verkürzen. um von gelöschten Zeilen belegte Seiten freizugeben.3 Logdateiverwaltung Es ist ratsam. dass der eine neue Logdatei anfängt.2 Routinemäßiges Reindizieren In bestimmten Fällen ist PostgreSQL unfähig. Der Log ist unschätzbar. Meldungen könnten gerade dann abgeschnitten oder fallen gelassen werden. wenn Sie wollen. sodass Sie nur einen einfachen Pipe-Befehl benötigen: pg_ctl start | logrotate Die PostgreSQL-Distribution enthält kein passendes Logrotierprogramm. selbst wenn häufig VACUUM ausgeführt wird. können die neuen Zeilen den von den gelöschten Zeilen freigegebenen Platz im Index nicht verwenden.Routinemäßige Datenbankwartungsaufgaben template0 vorzubereiten. Um das zu veranlassen. Die einfachste Lösung zur Verwaltung der Logausgabe ist. bei denen in pg_database datallowconn = false gesetzt wird. Das mag für Entwicklungsumgebungen ausreichend sein.

.

PostgreSQL bietet zu diesem Zweck das Hilfsprogramm pg_dump an. (Günstigerweise hat der Server normalerweise den gleichen eingebauten Vorgabewert. wenn diese Zugriff auf die Datenbank hat. verwenden Sie die Kommandozeilenoptionen -h host und -p port. Dieser Befehl wird generell so verwendet: pg_dump dbname > ausgabedatei Wie Sie sehen. mit der Datenbank.22 22 Datensicherung und wiederherstellung PostgreSQL-Datenbanken sollten. Um das zu übergehen. wenn man Sie an den Server zurückschickt. Das bedeutet. dann wird der lokale Host oder der. regelmäßig gesichert werden. die. dass Sie die zugrunde liegenden Techniken und Annahmen verstehen. wie sie zum Zeitpunkt der Sicherung war. dass Sie die Datensicherung von einer beliebigen Maschine im Netzwerk ausführen können. es es wichtig. verwendet. Unten werden wir sehen. Sie müssen insbesondere Leseerlaubnis für alle Tabellen haben. die SQL-Befehle enthält. Wenn nichts angegeben wird. schreibt pg_dump seine Ergebnisse auf den Standardausgabestrom. pg_dump ist eine normale PostgreSQL-Clientanwendung (wenn auch eine ziemlich schlaue). die Datenbank wieder so erzeugen. wie alles. Obwohl das Verfahren eigentlich ganz einfach ist. Es gibt zwei grundlegend verschiedene Ansätze.) Wie jede andere PostgreSQL-Clientanwendung verbindet pg_dump. den die Umgebungsvariable PGHOST angibt. 301 . wie nützlich das sein kann. Ähnlich wird der Port durch die Umgebungsvariable PGPORT oder den eingebauten Vorgabewert bestimmt. eine Textdatei zu erzeugen. dass pg_dump keine besonderen Zugriffsrechte hat. Um anzugeben. wenn nichts anderes angegeben wird. welchen Datenbankserver pg_dump kontaktieren soll. um eine PostgreSQL-Datenbank zu sichern: ❏ SQL-Dump ❏ Archivierung auf Dateisystemebene 22. die den gleichen Namen wie der aktuelle Betriebssystembenutzer hat. die Sie sichern wollen. wenn kein anderer angegeben wird. in der Praxis müssen Sie fast immer ein Datenbank-Superuser sein. geben Sie entweder die Option -U an oder setzen Sie die Umgebungsvariable PGUSER.1 SQL-Dump Die Idee der SQL-Dump-Methode ist es. Aber bedenken Sie. was wertvolle Daten enthält.

. dass Sie die Erlaubnis haben müssen. wie Benutzer und Gruppen.2 pg_dumpall verwenden Der oben beschriebene Mechanismus ist umständlich und unangebracht. dass Sie die Clientauthentifizierungseinstellungen vorübergehend etwas lockern. Prozeduren usw. der Reihe nach als jeden Benutzer zu verbinden und dann die entsprechenden Objekte zu erzeugen. müssen Sie die leere Datenbank aus template0 erzeugen. Mit pg_dump erzeugte Dumps sind intern konsistent. als jeder dieser Benutzer zu verbinden. wie zum Beispiel VACUUM FULL. dass Aktualisierungen.Kapitel 22 Bedenken Sie. Die Datenbank dbname wird von diesem Befehl nicht erzeugt. Schauen Sie auf die Referenzseite von pg_dump. Aufgerufen wird pg_dumpall einfach so: pg_dumpall > ausgabedatei 302 . um einen Dump zurückzuspielen. während pg_dump läuft. Das bedeutet jedoch auch. müssen Sie pg_dump anweisen. erhalten werden. Dadurch werden die Eigentumsverhältnisse richtig wiederhergestellt. von pg_dump mit ausgegeben werden. 22. die zu template1 hinzugefügt wurden. Sie müssen sie aus template0 selbst erzeugen. (Ausnahmen sind Operationen. die zur Ausführung eine exklusive Sperre benötigen. aus Pipes lesen können. 22. Aus diesem Grund steht das Programm pg_dumpall zur Verfügung. zum Beispiel: pg_dump -h host1 dbname | psql -h host2 dbname Wichtig Die von pg_dump erzeugten Dumps sind auf template0 basierend. wenn Sie Large Objects verwenden. die OIDs mit zu sichern. wenn Sie bei der Wiederherstellung eine selbst angepasste template1-Datenbank haben. bevor Sie psql ausführen (zum Beispiel mit createdb -T template0 dbname). und ferner. nicht im Dump sein werden. dass all diese Benutzer schon vorhanden sein müssen. Da pg_dump und psql in Pipes schreiben bzw. psql hat ähnliche Optionen wie pg_dump.1. kann man eine Datenbank direkt von einem Server zu einem anderen übertragen. pg_dump blockiert keine anderen Operationen in der Datenbank. Es kann daher notwendig sein. Das bedeutet.1. das heißt. um den Namen des Datenbankservers und den Benutzernamen zu kontrollieren. ist psql dbname < eingabedatei wobei eingabedatei die Datei ist. mit dem Programm psql gelesen zu werden. dass globale Daten. “Large Objects” werden auch ohne weiteres Zutun nicht ausgegeben.) Wichtig Wenn Ihr Datenbankschema OIDs verwendet (zum Beispiel als Fremdschlüssel). dass Verbindungen mit pg_dump den normalen Clientauthentifizierungsmechanismen unterworfen sind (welche in Kapitel 19 beschrieben sind). die in der Datenbank vorgenommen werden. Dazu verwenden Sie die Kommandozeilenoption -o. Die generelle Form eines Befehls.1 Den Dump wiederherstellen Die von pg_dump erzeugten Textdateien sind dafür gedacht. pg_dumpall sichert alle Datenbanken in einem Cluster und sorgt auch dafür. Wenn die Objekte in der ursprünglichen Datenbank verschiedene Eigentümer hatten. wird der Dump psql anweisen. wie im Beispiel oben. wenn man einen ganzen Datenbankcluster sichern will. Daher gilt. die Sie oben bei pg_dump als ausgabedatei angegeben hatten. Auf der Referenzseite finden Sie weitere Informationen. dass Sprachen. während es läuft.

die größer als die maximale Dateigröße auf Ihrem System sind. zum Beispiel gzip.gz Die Wiederherstellung geht mit createdb dbname gunzip -c dateiname. wird noch mehr Arbeit auf Sie zukommen.gz | psql dbname oder cat dateiname.4 Vorbehalte pg_dump (und als Konsequenz auch pg_dumpall) hat ein paar Beschränkungen. Sie können Ihr Lieblingskomprimierungsprogramm verwenden. kann das Dump-Format “custom” die Daten beim Schreiben in die Ausgabedatei komprimieren. Das Programm split ermöglicht Ihnen. Aber in diesem Fall müssen Sie auf jeden Fall Superuser-Rechte haben. Der folgende Befehl sichert eine Datenbank in diesem speziellen Format: pg_dump -Fc dbname > dateiname Einzelheiten finden Sie auf den Referenzseiten zu pg_dump und pg_restore. 303 . kann es problematisch sein.3 Große Datenbanken Da PostgreSQL Tabellen zulässt. die mit gzip erreicht wird. den Dump von Hand richtig zu sortieren. die eine für das Dateisystem akzeptable Größe haben. 22.Datensicherung und wiederherstellung Die sich daraus ergebenden Dumps können mit psql wie oben beschrieben wiederhergestellt werden. nicht sonderlich intelligent. Für große Datenbanken ergibt das eine Ausgabedatei mit etwa der Größe. wenn Funktionen in Spaltenvorgabewerten verwendet werden. da die daraus resultierende Datei wahrscheinlich größer als die von Ihrem System erlaubte Dateigröße sein würde. Wenn PostgreSQL auf einem System mit der Komprimierungsbibliothek zlib kompiliert wurde.und Gruppeninformationen erforderlich ist.gz | gunzip | psql dbname split verwenden. die Ausgabe in Stücke zu teilen. welche daher rühren. bestimmte Informationen aus den Systemkatalogen wieder zusammenzusetzen. können Sie Unix-Standardwerkzeuge verwenden. Die einzige Lösung ist. dass die Tabellen selektiv wiederhergestellt werden können.1. die aber den zusätzlichen Vorteil hat. Wenn Sie zwischen Objekten gegenseitige Abhängigkeiten erzeugt haben. Insbesondere ist die Reihenfolge. da das zur Wiederherstellung der Benutzer. dass es schwierig ist.dateiname Die Wiederherstellung geht mit createdb dbname cat dateiname* | psql dbname Das Dump-Format “custom” verwenden. Zum Beispiel. Das kann zum Beispiel zu Problemen führen. pg_dump dbname | gzip > dateiname. um 1 Megabyte große Stücke zu erzeugen: pg_dump dbname | split -b 1m . Da pg_dump in den Standardausgabestrom schreiben kann. 22. so eine Tabelle in eine Datei zu sichern. Komprimierte Dumps verwenden.1. in der pg_dump die Objekte ausgibt. um dieses mögliche Problem zu umgehen.

1. die PostgreSQL zum Speichern der Daten in der Datenbank verwendet. sind Sie vielleicht versucht.6. Um eine brauchbare Sicherungsdatei zu erhalten. 7. die Dateien. diese haben immer kompatible Speicherformate. direkt zu kopieren. um sie neu zu erzeugen. Sie können also nichts kaputt machen. Um diese Dateien zu sichern. welche den Status aller Transaktionen (abgeschlossen/abgebrochen/weder noch) enthalten. die behaupten. Daher wird auch nicht empfohlen.Kapitel 22 Wegen der Rückwärtskompatibilität gibt pg_dump in der normalen Einstellung keine Large Objects aus. finden Sie in Abschnitt 16.2 Archivierung auf Dateisystemebene Eine alternative Datensicherungsstrategie ist es. bevor Sie die Daten wiederherstellen. können Sie jede Methode verwenden. indem Sie nur die entsprechenden Dateien oder Verzeichnisse kopieren. Es bedarf keiner Erwähnung. die dafür sorgen. haben Sie sie sicher schon selbst gefunden. funktionieren nicht. (pg_dump muss zum Beispiel den Inhalt der Indexe nicht sichern. Ansonsten müssen Sie Ihre Daten mit pg_dump sichern und dann auf dem neuen Server wiederherstellen. Das Verzeichnis contrib/pg_dumplo im PostgreSQL-Quellbaum enthält ein Programm. 2. Das funktioniert nicht. dass Sie den Server auch herunterfahren müssen. das Large Objects auch sichern kann. nur eine Tabelle und die zugehörigen pg_clog-Daten wiederherzustellen. Zum Beispiel sind die Versionen 7. dass Sie nichts falsch machen. Natürlich ist es auch nicht möglich. Wenn Sie zwischen kompatiblen Versionen wechseln. weil das alle anderen Tabellen im Cluster unbrauchbar machen würde. Um Large Objects mit zu sichern. Bedenken Sie auch. da immer irgendwelche Daten in einem Zwischenspeicher sind.2 sind es. die diese Methode unpraktisch oder zumindest der pg_dumpMethode unterlegen machen: 1. Im Gegenteil.2 und 7. Die andere Hälfte ist in den Commit-Log-Dateien pg_clog/*.2 wurde beschrieben. müssen Sie entweder das “custom” oder das TAR-Dumpformat und die Option -b von pg_dump verwenden.2 nicht kompatibel. aber wenn Sie sich für diese Methode interessieren. sondern nur die Befehle. können Sie einfach den Datenbereich auf der Festplatte mit den neuen Programmdateien verwenden. mit der Sie auch sonst Ihr Dateisystem sichern.1. wo diese Dateien sich befinden.tar /usr/local/pgsql/data Es gibt allerdings zwei Einschränkungen.0. zum Beispiel: tar -cf backup. In Abschnitt 16. “konsistente Schnappschüsse” zu ermöglichen. sie wird höchstwahrscheinlich größer sein. dass eine Kopie der Dateistruktur auch nicht unbedingt kleiner als ein SQL-Dump sein wird. aber 7. (Es gibt mehrere Kontrollmechanismen.1 und 7.1. Das betrifft nicht die unterschiedlichen “Patch-Level” innerhalb einer Hauptversion. nur einzelne Tabellen oder Datenbanken zu sichern oder wiederherzustellen. wie alle Verbindungen zu unterbinden. 22. Dateisystemen zu vertrauen.) 22. Einzelheiten finden Sie auf der Referenzseite. Informationen. Bitte machen Sie sich mit der Referenzseite zu pg_dump vertraut. Eine Tabellendatei ist nur mit diesen Informationen brauchbar.3 Umstieg zwischen PostgreSQL-Versionen Generell ändert sich das interne Datenformat bei jeder neuen Hauptversion von PostgreSQL. Wenn Sie findig waren und Einzelheiten über die Dateisystemstruktur der Daten herausgefunden haben. wie Sie den Server anhalten können.1. weil die in diesen Dateien enthaltenen Informationen nur die halbe Wahrheit darstellen. wenn Sie 304 . Teilmaßnahmen. muss der Datenbankserver gestoppt werden.

dass die Datenbank nicht mehr verändert wird. aber wenn Sie beide Installationen noch eine Weile verwenden wollen. wo die anderen Teile sich befinden. ansonsten verlieren Sie logischerweise diese Daten.) Der genaue Installationsvorgang wird in diesem Abschnitt nicht beschrieben. ist sie nicht mehr voll gebrauchsfähig. bevor Sie den Wechsel vollziehen. In der Praxis sollten Sie Ihre Clientanwendungen mit der neuen Serverversion testen. bevor die neue Version installieren. nachdem Sie pg_dumpall ausgeführt haben. Einzelheiten dazu finden Sie in Kapitel 14. Die geringste Ausfallzeit können Sie erreichen. Schauen Sie in Kapitel 19 nach. dann sollten Sie ihnen wie vorgesehen bei der Installation unterschiedliche Verzeichnisse zuweisen. Oder wenn Sie wollen.gmake install initdb -D /usr/local/pgsql/data postmaster -D /usr/local/pgsql/data psql template1 < backup In Kapitel 16 finden Sie Informationen. verschieben die alte Version woandershin.Datensicherung und wiederherstellung etwas durcheinander bringen. um diese Schritte auszuführen. Anmerkung Wenn Sie die alte Version “woandershin” verschieben. Sie sollten sich versichern. um Ihre Daten zu übertragen. Das ist normalerweise kein großes Problem. Die Installationsanweisungen sagen Ihnen die richtigen Stellen.old cd ~/postgresql. indem Sie den neuen Server in ein anderes Verzeichnis installieren und den alten und den neuen Server parallel. Zum Beispiel: pg_dumpall > backup pg_ctl stop mv /usr/local/pgsql /usr/local/pgsql. mit verschiedenen Portnummern. Einige Teile der Installation enthalten Informationen darüber. Wenn Sie keine zwei Server parallel laufen haben wollen oder können. wie Sie den Zugriff verbieten können. können Sie eine Zwischendatei verwenden. installieren Sie die neue Version und starten den neuen Server. 305 . ausführen. wie Sie den Server starten und stoppen können und andere Einzelheiten. In jedem Fall können Sie dann den alten Server herunterfahren und den neuen am Port des alten starten. Dann können Sie einen Befehl wie pg_dumpall -p 5432 | psql -d template1 -p 6543 verwenden. dann halten Sie den Server an. dann können Sie den Datensicherungsschritt ausführen.

.

1 7084 1472 pts/1 process postgres 965 0. dass der Statistikkollektor nicht gestartet wird.4 6532 3080 pts/1 [local] idle in transaction SN SN SN SN SN SN 13:17 13:17 13:17 13:18 13:19 13:19 0:00 postmaster -i 0:00 postgres: stats buffer 0:00 postgres: stats collector 0:00 postgres: tgl runbug 0:00 postgres: tgl regression 0:00 postgres: tgl regression (Die Syntax von ps ist auf verschiedenen Plattformen unterschiedlich.0 2. Hier ist eine Beispielausgabe: $ ps auxww | grep ^postgres postgres 960 0. werden diese Prozesse nicht vorhanden sein. In Abschnitt 13. ebenso wie das Format der ausgegebenen Informationen. Wenn man eine zu langsame Anfrage gefunden hat.0 1.0 1.) Jeder 307 .1 2. muss man eventuell weitere Nachforschungen mit dem PostgreSQL-Befehl EXPLAIN anstellen. die angegeben wurden. wie ps und top.1 idle postgres 1003 0.) Der erste hier aufgeführte Prozess ist der Postmaster. um das Verhalten einzelner Anfragen zu verstehen.1 6104 1480 pts/1 postgres 963 0. 23. Es gibt mehrere Werkzeuge. wie Sie das herausfinden können.1 gibt es eine ausführliche Beschreibung von EXPLAIN und anderer Methoden.23 23 Überwachung der Datenbankaktivität Ein Datenbankadministrator fragt sich häufig: “Was macht das System gerade?” Dieses Kapitel bespricht. Dieses Beispiel ist von einem neueren Linux-System.0 2.0 1. aber man sollte normale Unix-Befehl zur Überwachung. Die nächsten zwei Prozesse implementieren den Statistikkollektor.0.4 6532 3128 pts/1 [local] SELECT waiting postgres 1016 0. der Hauptserverprozess. nicht vernachlässigen. (Wenn Sie das System so eingestellt haben.1 Unix-Standardwerkzeuge Auf den meisten Plattformen verändert PostgreSQL den von ps angezeigten Prozesstitel.1 6152 1512 pts/1 process postgres 998 0.0. Die dahinter gezeigten Argumente sind dieselben. um die Datenbankaktivität zu überwachen und die Datenbankleistung zu analysieren. Der Großteil dieses Kapitels ist der Beschreibung des Statistikkollektors von PostgreSQL gewidmet. welcher im nächsten Abschnitt beschrieben wird. als der Befehl ausgeführt wurde. damit einzelne Serverprozesse leicht identifiziert werden können.3 6532 2992 pts/1 127.

aber es ist möglich. Die Parameter stats_command_string. bestimmen. Außerdem muss die ursprüngliche Befehlszeile von postmaster eine kürzere ps-Anzeige haben als die von jedem Serverprozess eingestellte. (Siehe Abschnitt 16. wenn der Serverprozess augenblicklich auf eine Sperre wartet. wie sehr die Leistung beeinträchtigt wird. welche Informationen tatsächlich an den Kollektor geschickt werden. die normalerweise in postgresql. Zugriffsstatistiken auf Diskblock-Ebene bzw. dass Prozess 1016 seine Transaktion abschließt und dadurch irgendeine Sperre aufgehoben wird. wenn die Sitzung auf einen Befehl vom Client wartet. Sie ist idle. aber Sie können diesen Parameter ausschalten. dass diese Option nicht geändert werden kann. (Die Verbesserung wird allerdings gering sein. und damit auch.) Der Parameter stats_start_collector muss auf true gesetzt sein. um über diese zu berichten. das Informationen über die Serveraktivität sammelt und Schnittstellen bietet. Das wird von Konfigurationsparametern. ist die Ausgabe für jeden Serverprozess die ursprüngliche Befehlszeile von postmaster. Gegenwärtig kann der Kollektor Tabellen. die Datenbank und der Host der Verbindungsquelle bleiben für die gesamte Lebensdauer der Clientverbindung gleich. Normalerweise werden diese Parameter in postgresql. Wenn Sie eine dieser Voraussetzungen nicht erfüllen. Sie müssen /usr/ucb/ps anstatt /bin/ps verwenden und zweimal die Option w angeben. 23.conf gesetzt. (Damit gewöhnliche Benutzer ihre Aktivitäten nicht vor dem Administrator verstecken können.) 308 .4 für Einzelheiten.2. dass Prozess 1003 darauf wartet.und ausgeschaltet werden. können nur Superuser diese Parameter mit SET ändern. wie etwa SELECT. kontrolliert.) Beachten Sie. Im obigen Beispiel können wir ableiten.2 Der Statistikkollektor Der Statistikkollektor in PostgreSQL ist ein Subsystem.1 Konfiguration des Statistikkollektors Da die Sammlung von Statistiken die Leistung der Anfrageausführung leicht beeinträchtigt. damit Sie für alle Serverprozesse gelten. aber die Aktivitätsanzeige verändert sich.conf gesetzt werden. stats_block_level und stats_row_level kontrollieren.oder auszuschalten. Tipp Solaris erfordert eine besondere Behandlung. 23. wie man Konfigurationsparameter setzt. Außerdem kann er den genauen Befehl. nicht nur einmal. der gerade von einem anderen Serverprozess ausgeführt wird.Kapitel 23 der übrigen Prozesse ist ein Serverprozess. Das ist die Voreinstellung und auch empfohlen. wenn der Client in einem BEGIN-Block ist. der eine Clientverbindung bearbeitet. damit der Statistikkollektor überhaupt gestartet wird.und Indexzugriff in Diskblöcken und Zeilen zählen. idle in transaction. während der Server läuft. wenn Sie kein Interesse an Statistiken haben und jedes Quäntchen Leistung aus Ihrem Server herauspressen wollen. ansonsten der Name eines Befehlstyps. Zugriffsstatistiken auf Zeilenebene an den Kollektor schickt. die von einem anderen Serverprozess gehalten wird. ob ein Serverprozess seinen aktuellen Befehlstext. sie mit dem Befehl SET für einzelne Sitzungen an. Außerdem wird waiting angehängt. Jeder dieser Prozesse setzt die angezeigte Kommandozeile auf das Format postgres: benutzer datenbank host aktivität Der Benutzer. kann die Sammlung von Informationen ein. Die Parameter bestimmen.

Außerdem ermittelt der Kollektor selbst höchstens alle pgstat_stat_interval Millisekunden (500 in der Voreinstellung) neue Gesamtwerte. Alternativ kann man sich mit den zugrunde liegenden Statistikfunktionen eigene Sichten bauen. die vermieden wurden. Für jede Tabelle in der aktuellen Datenbank. solange Sie die aktuelle Transaktion fortsetzen. gibt es einige vordefinierte Sichten. (Beachten Sie. Wie pg_stat_all_tables.2 Ansehen der gesammelten Statistiken Um die Ergebnisse der Statistiksammlung zu zeigen. dass. wenn Indexeinträge auf abgelaufene Heap-Tupel zeigen. dass die aktuelle Anfrage wegen der Verzögerung der Kollektorergebnisse nur bei lange laufenden Anfragen auf dem richtigen Stand ist. stats_block_level und stats_row_level in der Voreinstellung falsch sind. 23. Für jeden Index in der aktuellen Datenbank. Gesamtzahl gelesener Diskblöcke und Gesamtzahl der Puffertreffer (d. Sie müssen einen oder mehrere dieser Parameter anschalten. denn dadurch können Sie mehrere Anfragen über die Statistiken ausführen und die Ergebnisse zueinander in Beziehung setzen. Die aktuelle Anfrage ist nur für Superuser zugänglich. die Gesamtzahl der Indexscans mit diesem Index. Wie pg_stat_all_tables. ohne sich Sorgen zu machen. dass sich die Zahlen gleichzeitig ändern könnten. (Das kann weniger sein.Überwachung der Datenbankaktivität Anmerkung Da die Parameter stats_command_string. aber nur für Indexe von Benutzertabellen. pg_stat_database pg_stat_all_tables pg_stat_sys_tables pg_stat_user_tables pg_stat_all_indexes pg_stat_sys_indexes pg_stat_user_indexes Tabelle 23.) Wie pg_stat_all_indexes. um die aktuellen Aktivitäten zu überwachen. führen Sie die Anfragen außerhalb eines Transaktionsblocks aus.) Eine Zeile pro Datenbank. damit Sie brauchbare Ergebnisse von den Auswertungsfunktionen erhalten. bevor er auf einen neuen Befehl vom Client wartet. müssen Sie bedenken. Sichtname pg_stat_activity Beschreibung Eine Zeile pro Serverprozess. mit der Anzahl aktiver Serverprozesse. dass diese Informationen nicht sofort aktualisiert werden. aber nur für Indexe von Systemtabellen. er zuerst die zuletzt vom Kollektorprozess ermittelten Gesamtwerte holt und diesen Schnappschuss dann für alle Statistiksichten und -funktionen bis zum Ende seiner aktuellen Transaktion verwendet. Wenn Sie die Statistiken verwenden. Gesamtzahl der sequenziellen und Indexscans.1 gelistet sind. wenn ein Serverprozess eine dieser Statistiken anzeigen soll. weil der Block im Cache war). Gesamtzahl der von jeder Scan-Art zurückgegebenen Tupel und die Gesamtzahl eingefügter. welche in Tabelle 23. Blockleseversuche. für andere ist sie der NULL-Wert. Das ist Absicht und kein Fehler. aktualisierter und gelöschter Tupel. Jeder Serverprozess übermittelt neue Zugriffszählungen an den Kollektor. Die angezeigten Ergebnisse hinken der tatsächlichen Aktivität also hinterher.h. die Gesamtzahl gelesener Indextupel und die Gesamtzahl erfolgreich gelesener Heap-Tupel.2. aber nur für Systemtabellen. werden in der Ausgangskonfiguration keine Statistiken gesammelt. mit Prozessnummer. Die Statistiken werden sich also nicht ändern. Wie pg_stat_all_indexes. Datenbankbenutzer und aktueller Anfrage.1: Standard-Statistiksichten 309 . eine noch in der Ausführung befindliche Anfrage hat also keine Auswirkungen auf die angezeigten Ergebnisse. Ein weiterer wichtiger Punkt ist. Gesamtzahl abgeschlossener und zurückgerollter Transaktionen in der Datenbank. Wenn Sie mit jeder Anfrage neue Ergebnisse sehen wollen. aber nur für Benutzertabellen.

die Anzahl der Puffertreffer. die Gesamtzahl der aus dieser Tabelle gelesenen Diskblöcke. Tabelle 23. Wenn die Anzahl der tatsächlich gelesenen Diskblöcke wesentlich kleiner ist als die Anzahl der Puffertreffer. welche Indexe verwendet werden und wie effektiv sie sind. also ist diese Sicht immer leer.1: Standard-Statistiksichten (Forts. die den Standardsichten zugrunde liegen. können Sie selbst Anfragen schreiben. die Anzahl der gelesenen Diskblöcke und Puffertreffer für alle Indexe dieser Tabelle. Wie pg_statio_all_indexes. die über Serverprozesse berichten. dass diese Funktionen nur über Tabellen und Indexe in der aktuellen Datenbank berichten können. aber nur mit Benutzersequenzen. pg_statio_sys_sequen Wie pg_statio_all_sequences. haben die Datenbank-OID als Argument. (Gegenwärtig sind ces keine Systemsequenzen definiert.) Die Funktionen. aber nur für Indexe von Systemtabellen. pg_statio_sys_tables pg_statio_user_table s pg_statio_all_indexe Für jeden Index in der aktuellen Datenbank. welche von eins bis zur Anzahl der aktiven Serverprozesse zählen. um zu ermitteln. aber nur für Benutzertabellen. Die Funktionen.Kapitel 23 Sichtname pg_statio_all_tables Beschreibung Für jede Tabelle in der aktuellen Datenbank.) Die indexspezifischen Statistiken sind nützlich.2 aufgelistet. die Datenbankstatistiken berichten. die Anzahl der gelesenen Diskblöcke und s Puffertreffer für diesen Index. um die Effektivität des Puffercache zu ermitteln. Die pg_statio_-Sichten sind hauptsächlich nützlich. dann erfüllt der Cache die meisten Leseanfragen ohne einen Kernelaufruf zu benötigen. die Anzahl der gelesenen Diskblöcke und Puffertreffer für die zugehörige TOAST-Tabelle dieser Tabelle (falls vorhanden) und die Anzahl der gelesenen Diskblöcke und Puffertreffer für den Index der TOAST-Tabelle. (Beachten Sie. aber nur für Systemtabellen.) pg_statio_user_seque nces Wie pg_statio_all_sequences. Wenn Sie die Statistiken auf andere Weise betrachten wollen. Wie pg_statio_all_tables. die Anzahl gelesener Diskblöcke ces und Puffertreffer in dieser Sequenz. verlangen die laufende Nummer eines Serverprozesses als Argument. aber nur für Indexe von Benutzertabellen. die die selben Statistikfunktionen verwenden.2: Statistikfunktionen 310 . pg_statio_all_sequen Für jedes Sequenzobjekt in der aktuellen Datenbank.und Indexstatistiken verlangen die OID einer Tabelle oder eines Index. Die Funktionen für Tabellen. Diese Funktionen sind in Tabelle 23. Wie pg_statio_all_tables. Funktion pg_stat_get_db_numbackends(oid) pg_stat_get_db_xact_commit(oid) pg_stat_get_db_xact_rollback(oid) Ergebnistyp integer bigint bigint Beschreibung Anzahl aktiver Serverprozesse für die Datenbank Anzahl erfolgreich abgeschlossener Transaktionen in der Datenbank Anzahl zurückgerollter Transaktionen in der Datenbank Anzahl angeforderter Diskblock-Lesevorgänge für die Datenbank Anzahl im Cache gefundener Diskblöcke für die Datenbank pg_stat_get_db_blocks_fetched(oid) bigint pg_stat_get_db_blocks_hit(oid) bigint Tabelle 23. pg_statio_sys_indexe s pg_statio_user_index es Wie pg_statio_all_indexes. aber nur mit Systemsequenzen.

eine Zeile für jeden aktiven Serverprozess zu erzeugen.backendid) AS procpid. weil der Kernel auch noch einen Cache hat. Um zum Beispiel die PID und die aktuelle Anfrage für jeden Serverprozess anzuzeigen. pg_stat_get_tuples_returned(oid) bigint pg_stat_get_tuples_fetched(oid) bigint pg_stat_get_tuples_inserted(oid) pg_stat_get_tuples_updated(oid) pg_stat_get_tuples_deleted(oid) pg_stat_get_blocks_fetched(oid) pg_stat_get_blocks_hit(oid) pg_stat_get_backend_idset() bigint bigint bigint bigint bigint set of integer integer integer oid pg_backend_pid() pg_stat_get_backend_pid(integer) pg_stat_get_backend_dbid(integer) pg_stat_get_backend_userid(integer oid ) pg_stat_get_backend_activity (integer) pg_stat_reset() text boolean Tabelle 23. die Anzahl der von sequenziellen Scans gelesenen Tupel.backendid) AS current_query FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s. Siehe Verwendungsbeispiel im Text. wenn es ein Index ist. die Anzahl der von sequenziellen Scans gelesenen gültigen (nicht abgelaufenen) Tabellentupel. aber die Anzahl der eigentlichen physikalischen Lesevorgänge ist normalerweise niedriger. die Anzahl ausgeführter Indexscans Wenn das Argument eine Tabelle ist.) Anmerkung pg_stat_get_db_blocks_fetched minus pg_stat_get_db_blocks_hit ergibt die Anzahl der vom Kernel ausgeführten read()-Aufrufe für die Tabelle. wenn es ein Index ist. können Sie folgende Anfrage verwenden: SELECT pg_stat_get_backend_pid(s. wenn der aktuelle Benutzer kein Superuser ist) Setzt alle gesammelten Statistiken zurück. wenn es ein Index ist. die Anzahl der von Indexscans gelesenen Indextupel Wenn das Argument eine Tabelle ist.2: Statistikfunktionen (Forts. den Index oder die Datenbank. Prozessnummer des zu dieser Sitzung gehörenden Serverprozesses Prozessnummer des angegebenen Serverprozesses Datenbank-OID des angegebenen Serverprozesses Benutzer-ID des angegebenen Serverprozesses Aktiver Befehl des angegebenen Serverprozesses (NULL-Wert. pg_stat_get_backend_activity(s. Die Funktion pg_stat_get_backend_idset bietet einen praktische Möglichkeit. die Anzahl ausgeführter sequentieller Scans. die Anzahl der von Indexscans gelesenen gültigen Tabellentupel Anzahl der in die Tabelle eingefügten Tupel Anzahl der in der Tabelle aktualisierten Tupel Anzahl der aus der Tabelle gelöschten Tupel Anzahl angeforderter Diskblock-Lesevorgänge für die Tabelle oder den Index Anzahl im Cache gefundener Diskblöcke für die Tabelle oder den Index Menge der aktuell aktiven Serverprozessnummern (von 1 bis zur Anzahl der aktiven Serverprozesse).Überwachung der Datenbankaktivität Funktion pg_stat_get_numscans(oid) Ergebnistyp bigint Beschreibung Wenn das Argument eine Tabelle ist. 311 .

tut sie das. Die Sicht pg_locks enthält eine Zeile pro sperrbares Objekt und angeforderten Sperrmodus.3: Spalten von pg_locks 312 . wenn die andere Transaktion zu Ende geht und ihre Sperren freigibt. Wenn die Sperre für eine globale Tabelle ist. werden die internen Datenstrukturen der Sperrenverwaltung einen Augenblick lang gesperrt und es wird davon für die Sicht eine Kopie gemacht. Anmerkung Wenn auf die Sicht pg_locks zugegriffen wird. Das kann erst erfolgreich sein.Kapitel 23 23. ❏ die Tabelle in der aktuellen Datenbank mit den meisten nicht gewährten Sperren (welche eine Quelle möglicher Konflikte zwischen Clients sein könnten) zu ermitteln. Weitere Informationen über Sperren und Mehrbenutzerbetrieb in PostgreSQL finden Sie in Kapitel 12. oder der NULLWert. in dem sie versucht.) Spaltenname relation Datentyp oid Beschreibung Die OID der gesperrten Relation oder der NULL-Wert. ohne die Sperrenverwaltung länger als notwendig zu blockieren. database oid transaction xid Tabelle 23. Diese Spalte kann mit der Spalte oid der Systemtabelle pg_class verbunden werden. ist die Systemtabelle pg_locks. wenn das sperrbare Objekt eine Relation ist. Diese Fähigkeit kann zum Beispiel verwendet werden. Ein sperrbares Objekt ist entweder eine Relation (z. alle Sperren in einer bestimmten Datenbank. Wenn eine Transaktion auf eine Zeilensperre wartet. Nichtsdestotrotz könnte es sich auf die Leistung der Datenbank auswirken. Die OID der Datenbank. Das versichert. um weitere Informationen über die Tabelle zu erhalten. dass eine Transaktion speziell auf eine andere warten muss. bei denen die Spalte database gleich der OID der aktuellen Datenbank oder null ist) funktioniert. wenn das sperrbare Objekt eine Transaktionsnummer ist. um weitere Informationen über die Datenbank des sperrbaren Objekts zu erhalten. dass die Sicht konsistente Ergebnisse liefert. um die Datenbankaktivität zu überwachen. alle Sperren für eine bestimmte Tabelle oder alle von einer bestimmten PostgreSQL-Sitzung gehaltenen Sperren zu sehen.3 Ansehen der Sperren Ein weiteres nützliches Werkzeug. dass diese Transaktion auf die Transaktionnummer der Transaktion wartet. wenn diese Sicht oft angeschaut wird. Wenn es sich ergibt. wenn das sperrbare Objekt eine Transaktionsnummer ist.3 zeigt die Definition der Spalten von pg_locks.B. Ein sperrbares Objekt kann also mehrfach auftauchen. ❏ Die Auswirkung von Sperrkonflikten auf die Gesamtleistung der Datenbank sowie das Ausmaß des Zusammenhangs zwischen der Konflikthäufigkeit und dem Datenbankverkehr zu ermitteln. Mit ihr können Datenbankadministratoren Informationen über die aktuell ausstehenden Sperren ansehen. eine Tabelle) oder eine Transaktionsnummer. Dieses Spalte kann mit der Spalte oid der Systemtabelle pg_database verbunden werden. Beachten Sie jedoch. Jede Transaktion hält für ihre gesamte Dauer eine exklusive Sperre für ihre Transaktionsnummer. Die Nummer der Transaktion oder der NULL-Wert. erscheint in der Sicht. wenn mehrere Transaktionen Sperren halten oder auf solche warten. (Beachten Sie. nicht aber auf Zeilenebene enthält. dass das nur für Relationen in der aktuellen Datenbank (jene. um: ❏ alle aktuell ausstehenden Sperren. die die Sperre gerade hält. Tabelle 23. in der das sperrbare Objekt liegt. dann ist dieses Feld 0. dass diese Sicht nur Sperren auf Tabellenebene. eine geteilte Sperre für die Nummer der anderen Transaktion zu erhalten.

um weitere Informationen über die Sitzung. Weitere Informationen über die unterschiedlichen Sperrmodi in PostgreSQL finden Sie in Kapitel 12. die die Sperre hält oder darauf wartet. diese Sperre setzen zu können.3: Spalten von pg_locks (Forts.Überwachung der Datenbankaktivität Spaltenname pid Datentyp integer Beschreibung Die Prozess-ID des PostgreSQL-Serverprozesses. der zu der Sitzung gehört. bis die andere Sperre aufgehoben wird (oder eine Verklemmung entdeckt wird). zu erhalten. dass eine andere Sitzung für dasselbe sperrbare Objekt eine Sperre hält. Ist wahr. Wenn Sie den Statistikkollektor angeschaltet haben.) 313 . Die wartende Sitzung schläft. die mit der gewünschten in Konflikt steht. wenn die Sperre von dieser Sitzung gehalten wird. Eine einzelne Sitzung kann zu jeder Zeit nur auf höchstens eine Sperre warten. Der Modus der gewünschten oder gehaltenen Sperre. dass diese Sitzung gegenwärtig darauf wartet. Falsch zeigt an. kann diese Spalte mit der Sicht pg_stat_activity verbunden werden. woraus folgt. die die Sperre gesetzt hat oder versucht. sie zu setzen. mode isgranted text boolean Tabelle 23.

.

mit psql und den Werkzeugen in contrib/dbsize sowie von der Kommandozeile mit den Werkzeugen in contrib/oid2name. Sie können den Festplattenplatzverbrauch auf dreierlei Arten überwachen: mit psql auf Basis von VACUUMInformationen. wie Sie den Speicherplatzverbrauch mit Betriebssystemwerkzeugen verwalten können. deren. in der neulich VACUUM oder ANALYZE ausgeführt wurde. wo die meisten Daten gespeichert sind.) Um den von TOAST-Tabellen belegten Platz anzuzeigen.relfilenode) gebildet wird.1 Ermittlung des Festplattenplatzverbrauchs Zu jeder Tabelle gehört eine Heap-Datei. wie Sie den Festplattenplatzverbrauch eines PostgreSQL-Datenbanksystems überwachen können. 24. (Erinnern Sie sich. wobei Sie die relfilenode-Nummer des Heaps einsetzen müssen (welche mit obiger Anfrage ermittelt wird): SELECT relname. Name aus der OID der Tabelle (genau gesagt eigentlich pg_class. können Sie mit psql durch Anfragen den Platzverbrauch einer jeden Tabelle sehen: SELECT relfilenode. In einer Datenbank. relpages FROM pg_class WHERE relname = 'customer'. und einen Index für die TOASTTabelle.24 24 Überwachung des Festplattenplatzverbrauchs Dieses Kapitel bespricht. relfilenode | relpages -------------+---------16806 | 60 (1 row) Jede Seite (page) ist normalerweise 8 kB groß. Um lange Spaltenwerte zu speichern gibt es außerdem eine zur Tabelle gehörende TOAST-Tabelle. 315 . verwenden Sie eine Anfrage wie die folgende. In der aktuellen Version hat der Datenbankadministrator nicht viel Kontrolle über die Struktur und die Verteilung der Datenbankdateien und daher ist dieses Kapitel eher informativ und kann Ihnen einige Ideen geben. dass relpages nur von VACUUM und ANALYZE aktualisiert wird. Außerdem kann es Indexe für die eigentliche Tabelle geben. relpages FROM pg_class WHERE relname = 'pg_toast_16806' OR relname = 'pg_toast_16806_index' ORDER BY relname.

24. bis die Festplatte voll ist. wenn sie fast voll sind. Also warten Sie nicht. führen. Wenn die Festplatte voll ist. ohne VACUUM oder ANALYZE ausführen zu müssen. dann kann eine volle Festplatte bei der Datenbankinitialisierung zu verfälschten oder unvollständigen WAL-Dateien führen. Sie können auch contrib/oid2name verwenden. Dieser fehlerhafte Zustand würde entdeckt werden und der Datenbankserver würde sich weigern zu starten.indrelid AND c2. sicherzustellen. dass pg_dump in solchen Situationen die Verteilung der Dateien nicht sichern kann.relpages FROM pg_class c. dass Ihnen der Festplattenplatz ausgeht. Wenn Sie keinen zusätzlichen Platz auf der Festplatte schaffen können. pg_index i WHERE c. Tipp Einige Dateisysteme haben eine enorm verschlechterte Leistungsfähigkeit. um den Festplattenplatzverbrauch anzuzeigen. dass die Festplatte nicht voll wird. Um zu verhindern. 316 . pg_class c2.relname. Weitere Informationen dazu finden Sie in der Dokumentation zu initdb und in Abschnitt 18.relname. können Sie WAL-Dateien und Datenbanken bei der Erzeugung gleich an andere Stellen verlegen.indexrelid ORDER BY c2. In der Datei README.oid = i.oid = i. Ein Skript. nicht aber der Tabellen selbst. die es Ihnen erlauben. kann das zur Verfälschung der Datenbankindexe. bevor Sie etwas unternehmen. relpages FROM pg_class ORDER BY relpages DESC.2 Verhalten bei voller Festplatte Die wichtigste Aufgabe für den Datenbankadministrator bei der Überwachung des Festplattenplatzverbrauchs ist. Aber beachten Sie. c2. ist dort enthalten.oid2name in diesem Verzeichnis finden Sie Beispiele. Wenn die WAL-Dateien auf der gleichen Festplatte sind (was in der Standardeinstellung der Fall ist).Kapitel 24 relname | relpages ----------------------+---------pg_toast_16806 | 0 pg_toast_16806_index | 1 Sie können ganz leicht auch Indexgrößen anzeigen: SELECT c2. eine Wiederherstellung würde alles wieder an einer einzigen Stelle ablegen. das für jede Datenbank den Platzverbrauch anzeigt.relname = 'customer' AND c. relname | relpages ----------------------+---------customer_id_indexdex | 26 Mit diesen Informationen können Sie leicht Ihre größten Tabellen und Indexe finden: SELECT relname. relname | relpages ----------------------+---------bigtable | 3290 customer | 3144 contrib/dbsize lädt Funktionen in Ihre Datenbank. die Größe einer Tabelle oder Datenbank aus psql zu ermitteln. können Sie einige der Datenbankdateien auf andere Dateisysteme verschieben und von der ursprünglichen Stelle einen symbolischen Link erzeugen. indem Sie andere Sachen löschen.5.

dass man im Falle eines Absturzes die Datenbank mit dem Log wiederherstellen kann: Änderungen. total zerstörter Inhalt von Tabellen. Die Wahrheit ist. die noch nicht auf die Datenseiten übertragen wurden. das heißt.oder Indexseiten wegen unvollständig geschriebener Datenseiten Probleme mit den Indexen (Probleme 1 und 2) könnten möglicherweise durch zusätzliche fsync()-Aufrufe behoben werden. Wenn man so vorgeht. die auf nicht existierende Tabellenzeilen zeigen 2. WAL sichert den gesamten Datenseiteninhalt im Log. Vor WAL konnte ein Absturz beim Schreiben folgende Konsequenzen haben: 1.25 25 Write-Ahead Logging (WAL) Write-Ahead Logging (WAL) ist eine Standardtechnik für das Aufzeichnen (Loggen) von Transaktionen. dass Änderungen in Datendateien (wo Tabellen und Indexe abgelegt sind) erst geschrieben werden dürfen. Der nächste Nutzen ist die Konsistenz der Datenseiten. aber es ist nicht klar. wie der letzte Fall ohne WAL zu ausgeräumt werden kann. 317 . nachdem Sie im Log aufgezeichnet wurden und die Logeinträge auf ein permanentes Speichermedium geschrieben wurden. Indexzeilen. dass PostgreSQL vor WAL die Konsistenz im Falle eines Absturzes nicht garantieren konnte. um die Konsistenz der Seite für den Fall einer Wiederherstellung nach einem Absturz zu garantieren. wenn das notwendig ist. bei Splitoperationen verlorene Indexzeilen 3. in Mehrbenutzerumgebungen können die Commits vieler Transaktionen mit einem einzigen fsync()-Aufruf für die Logdatei erledigt werden. wodurch das Synchronisieren der Logdatei viel effizienter wird als das Rückschreiben der Datenseiten. Eine detaillierte Beschreibung davon kann in den meisten (wenn nicht gar allen) Büchern über die Transaktionsverarbeitung gefunden werden. Außerdem wird die Logdatei sequenziell geschrieben. da nur die Logdatei am Ende jeder Transaktion auf die Festplatte zurückgeschrieben werden muss. weil man weiß. dass die Anzahl der Schreibvorgänge auf die Festplatte erheblich verringert wird. werden zuerst aus den Logaufzeichnungen wiederhergestellt (das ist Vorwärts-Wiederherstellung. auch REDO genannt) und dann werden Änderungen aus nicht abgeschlossenen Transaktionen aus den Datenseiten entfernt (Rückwärts-Wiederherstellung. Zusammengefasst ist das zentrale Konzept von WAL. wenn diese Änderungen geloggt wurden. UNDO). 25.1 Nutzen aus WAL Der erste offensichtliche Nutzen aus WAL ist. muss man die Datenseiten nicht nach jeder Transaktion auf die Festplatte zurückschreiben.

nach. alte pg_clog-Einträge ewig zu behalten. es wird beim Herunterfahren des Servers gelöscht werden können. Sicherungspunkte zu implementieren.2 Zukünfiger Nutzen Die UNDO-Operation ist nicht implementiert.) Mit UNDO wird es auch möglich sein.3 WAL-Konfiguration Es gibt mehrere WAL-Konfigurationsparameter. wird irgendeine Form von komprimiertem WAL-Format benötigt werden. die auf die Leistung der Datenbank Auswirkung haben.4 wegen Einzelheiten. ist. um den Transaktionsstatus aufzuzeichnen. Das ist gegenwärtig kein ernsthaftes Problem. werden alle Segmente vor dem Redo-Eintrag nicht mehr benötigt und können wiederverwendet oder entfernt werden. da die Einträge nur für ein oder zwei Checkpoint-Intervalle aufbewahrt werden müssen. (Die Dringlichkeit dieser Angelegenheit wurde aber durch die Einführung einer segmentierten Speichermethode für pg_clog enorm verringert: Es ist nicht mehr notwendig. 25. wie bei einer Wiederherstellung nach einem Absturz. (Wenn Datensicherung und -wiederherstellung auf WAL-Basis implementiert ist. Checkpoints sind Punkte in der Folge von Transaktionen. dass sie erfordern. um den nächsten Checkpoint zu erzeugen. so lang wie die längstmögliche Transaktion. bei welchem Eintrag im Log (der so genannte Redo-Eintrag) die REDO-Operation starten soll. Zum Zeitpunkt des Checkpoints werden alle schmutzigen Datenseiten auf die Festplatte zurückgeschrieben. Nachdem ein Checkpoint erzeugt wurde. Ein Checkpoint wird alle checkpoint_segments Logsegmente oder alle checkpoint_ 318 .) Der Server startet in regelmäßigen Abständen einen besonderen Prozess. Dieser Abschnitt beschreibt die Verwendung. man müsste auch eine Methode zum Kopieren der Datendateien entwickeln (die Kopierbefehle im Betriebssystem sind nicht ausreichend). um ungültige Transaktionsoperationen (Syntaxfehler durch Tippfehler in Befehlen. da es viele Schnappschüsse von Diskseiten enthält. die davor an Datendateien gemacht wurden. da alle Änderungen. wie man Konfigurationsparameter setzt. ein Bandlaufwerk oder einen anderen Rechner kopieren und außerdem die WALLogdateien archivieren. da Transaktionsnummern nicht wiederverwendet werden können. aber um diese zukünftigen Nutzen zu erreichen. dass WAL-Einträge für beträchtliche Zeiträume gespeichert werden (z. die der Umsetzung dieser möglichen Nutzen im Weg steht. dann würden die Logsegmente vor dem Wiederverwenden oder Entfernen archiviert werden. Eine Schwierigkeit. dass die Transaktion abgebrochen wird. Um diese Methode zu implementieren müssten das Erzeugen und das Löschen von Datendateien und Indexen geloggt werden. schon auf der Festplatte sind. dass alle Datendateien mit den vor dem Checkpoint geloggten Informationen aktualisiert wurden.) teilweise zurückrollen zu können und gleichzeitig die in der Transaktion vor dem Fehler durchgeführten Operationen fortführen oder die Transaktion abschließen zu können. Jedes Mal. könnten die alten Logdateien entfernt werden. Schauen Sie in Abschnitt 16. WAL bietet die Möglichkeit für eine neue Methode für online Datenbanksicherung und wiederherstellung. Gegenwärtig macht jeder Fehler die ganze Transaktionen ungültig und erfordert. Im Fall eines Absturzes kann man daher wissen. dass von abgebrochenen Transaktionen verursachte Änderungen immer noch Speicherplatz verbrauchen und dass immer noch eine permanente pg_clog-Datei benötigt wird. Um diese Methode zu verwenden. muss pg_clog nicht mehr permanent sein.B.Kapitel 25 25. Die Kopie der Datenbankdateien und die archivierten Logdateien könnten zur Wiederherstellung verwendet werden. wenn Transaktions-UNDO gewünscht wird). Das gegenwärtige Format der WAL-Einträge ist ziemlich umfangreich. an denen es garantiert ist. Wenn UNDO implementiert ist. Einfügen von doppelten Primärschlüsseln usw. müsste man in regelmäßigen Abständen die Datendateien auf eine andere Festplatte. Das bedeutet. wenn die Datenbankdateien kopiert würden. und es wird ein besonderer Checkpoint-Eintrag in den Log geschrieben.

dass die Genauigkeit einer Schlafoperation auf den meisten Plattformen zehn Millisekunden ist. aber vor der LogFlush-Operation schlafen wird. weil LogInsert bei jeder Datenbankoperation auf unterster Ebene (zum Beispiel das Einfügen einer Zeile) verwendet wird. nicht mehr benötigte Logsegmente wiederverwendet (umbenannt. 319 . Diese Einstellung könnte in der Zukunft durch einen allgemeineren Mechanismus ersetzt werden. dass die Daten der Transaktion auf einem permanenten Speichermedium angekommen sind. um die schmutzigen Datenseiten häufiger zurückzuschreiben. durch eine kurzzeitige Spitze bei der Logausgabe. dass jeder Wert für commit_delay zwischen 1 und 10000 Mikrosekunden die gleiche Wirkung haben würde. Auf Systemen mit großem Logausgabevolumen kann es sein. Damit können Sie die Speicherplatzanforderungen von WAL abschätzen. Das ermöglicht schnellere Wiederherstellung nach einem Absturz (da weniger Arbeit wiederhergestellt werden muss). Gegenwärtig macht es keinen Unterschied. Der Parameter wal_sync_method bestimmt. Wenn man checkpoint_segments und/oder checkpoint_timeout verringert. während auf den betroffenen Datenseiten eine exklusive Sperre liegt. Die Optionen sollten in Sachen Zuverlässigkeit gleichwertig sein. dass WAL-Puffer von LogInsert geschrieben werden müssen. wenn fsync ausgeschaltet wurde. dass LogFlush nicht oft genug ausgeführt wird. aber es ist ziemlich plattformabhängig. wenn fsync nicht angeschaltet ist oder wenn weniger als commit_siblings andere Sitzungen gegenwärtig in aktiven Transaktionen sind. Man kann auch mit dem SQL-Befehl CHECKPOINT einen Checkpoint direkt erzwingen. muss LogInsert einige gefüllte WAL-Puffer zurückschreiben (bzw. daher muss diese Operation so schnell wie möglich sein. um die nächsten Segmente in der durchnummerierten Reihe zu werden). Auf solchen Systemen sollte man die Anzahl der WAL-Puffer erhöhen. Es gibt immer mindestens eine Segmentdatei zu 16 MB und normalerweise gibt es höchstens 2 * checkpoint_segments + 1 Dateien. Die Standardeinstellung ist 3 Segmente bzw. Dieses Schlafen wird nicht durchgeführt. WAL-Änderungen auf die Festplatte zurückzuschreiben. Wenn es. 300 Sekunden. um einen neuen Eintrag in die WAL-Puffer im Shared Memory zu stellen. in den Kernelcache verschieben). wie PostgreSQL den Kernel darum bittet. wie viele Mikrosekunden ein Serverprozess nach dem Schreiben eines Commit-Eintrags mit LogInsert. Diese Verzögerung erlaubt es anderen Serverprozessen. Normalerweise sollten WAL-Puffer von einer LogFlush-Operation zurückgeschrieben werden. dass dieser Parameter irrelevant ist. Man muss das jedoch abwägen gegen die erhöhten Kosten. bis das System wieder unter die Grenze kommt. erzeugt. Der Parameter commit_delay bestimmt. Es gibt zwei häufig verwendete WAL-Funktionen: LogInsert und LogFlush. das vermeidet die Verzögerung. wenn es unwahrscheinlich ist. LogInsert wird verwendet. Ein höherer Wert erfordert entsprechend mehr Shared Memory. Die voreingestellte Zahl der WAL-Puffer ist 8. was eher kommt. welche im Großen und Ganzen jeweils beim erfolgreichen Abschluss einer Transaktion ausgeführt wird. dass. je nachdem. ihre Commit-Einträge zum Log hinzuzufügen. Wenn es keinen Platz für einen neuen Eintrag gibt. werden die unbenötigten Segmentdateien nicht wiederverwendet. welche die schnellste ist. bei der ersten Modifikation einer Datenseite nach einem Checkpoint der gesamte Seiteninhalt geloggt. sondern gelöscht. Beachten Sie. was genau der Wert ist. damit sie alle mit einer einzigen Operation zurückgeschrieben werden können. damit sichergestellt wird. Das ist aber nicht wünschenswert. werden Checkpoints häufiger gemacht. wird jede LogInsertund LogFlush-Operation im Serverlog vermerkt. Gute Werte für diese Parameter sind noch nicht ganz klar. was noch mehr Zeit in Anspruch nimmt. Und noch schlimmer ist. dass ein neues Logsegment erzeugt werden muss. Gewöhnlich werden alte. Beachten Sie. zu experimentieren. Ein kleineres Checkpoint-Intervall erhöht folglich die in den Log geschriebene Datenmenge. um die Konsistenz der Datenseiten sicherzustellen.Write-Ahead Logging (WAL) timeout Sekunden. das dann auch dazu führen kann. um zu verhindern. wenn WAL-Puffer geschrieben werden. indem man den Konfigurationsparameter wal_buffers verändert. dass weitere Sitzungen ihre Transaktionen in Kürze abschließen werden. Wenn man den Parameter wal_debug auf einen Wert verschieden von null setzt. was hieße. mehr als 2 * checkpoint_segments + 1 Segmentdateien gibt. wir ermutigen Sie. wodurch teilweise das Ziel eines kleineren Intervalls zunichte gemacht wird und auf jeden Fall die Eingabe. Außerdem wird.und Ausgabeaktivität auf der Festplatte erhöht wird.

indem er von der im Checkpoint-Eintrag angegebenen Logposition vorwärts verfährt. WAL-Logs werden im Verzeichnis $PGDATA/pg_xlog gespeichert. um die Checkpoint-Position zu ermitteln. beschleunigt den Wiederherstellungsvorgang. Das kann man erreichen. bevor Datenbanksätze geändert werden. der Administrator muss nichts weiter unternehmen. die fälschlicherweise Schreibvorgänge an den Kernel als erfolgreich melden. die für PostgreSQL die WAL-Logdateien speichern. wenn der Log auf einer anderen Festplatte als die anderen Datenbankdateien ist.3). Segmentdateien erhalten stetig steigende Nummern als Namen. Ein Stromausfall kann in solchen Fällen immer noch zu Datenzerstörung ohne Chance auf Wiederherstellung führen. Der Verbrauch an Shared Memory hängt von der Anzahl der Puffer ab. Es ist von Vorteil.Kapitel 25 25. Die voreingestellte Größe der WAL-Puffer ist 8 Puffer zu je 8 kB. dass der Log geschrieben wird. der Inhalt des Eintrags hängt vom Typ des geloggten Ereignisses ab. aber es sollte sehr lange dauern. aber um mit einer möglichen Verfälschung von pg_control fertig zu werden.4 Interna WAL ist automatisch angeschaltet. liest der Server daher zuerst pg_control und dann den Checkpoint-Eintrag. Da bei der ersten Seitenveränderung nach einem Checkpoint der gesamte Inhalt einer Datenseite im Log gesichert wird. kann von Festplattenlaufwerken untergraben werden. sie werden durch leichtgewichtige Sperren geschützt.h beschrieben. Die Nummern haben keine Überlaufvorrichtung. dann führt er die REDO-Operation aus. wird die Position des Checkpoints in der Datei pg_control gesichert. können alle Änderungen nach dem Checkpoint in einen konsistenten Zustand wiederhergestellt werden. obwohl sie tatsächlich die Daten nur in den Cache gestellt und nicht wirklich auf die Platte geschrieben haben. Jedes Segment ist in 8 kB große Seiten aufgeteilt. Nachdem ein Checkpoint erzeugt und der Log zurückgeschrieben wurde. Die WAL-Puffer und -Kontrollstrukturen sind im Shared Memory und werden von den Serverkindprozessen verwaltet. bis die verfügbaren Nummern aufgebraucht sind. also insgesamt 64 kB. als ein Satz Segmentdateien. indem man das Verzeichnis pg_xlog an eine andere Stelle verschiebt (natürlich während der Server nicht läuft) und einen symbolischen Link von der ursprünglichen Stelle in $PGDATA an die neue Stelle erzeugt. Wenn eine Wiederherstellung ansteht. sicherzustellen. Administratoren sollten sich versichern. jede 16 MB groß. sollten wir eigentlich die existierenden Logsegmente in umgekehrter Reihenfolge – vom neusten zum ältesten – lesen und so den letzten Checkpoint finden. Das ist noch nicht implementiert. Die Verwendung von pg_control. dass die Festplatten. außer für zusätzlichen Festplattenplatz für die WAL-Logs zu sorgen und die nötigen Feinabstimmungen vorzunehmen (siehe Abschnitt 25. Der Kopf eines Logeintrags ist in access/ xlog. 320 . beginnend mit 0000000000000000. Das Ziel von WAL. keine solchen falschen Ergebnisse liefern.

Um die Regressionstests nach dem Compilieren aber vor der Installation auszuführen. um Tests in Gruppen gleichzeitig laufen zu lassen. Außerdem gibt es eine “parallele” und eine “sequenzielle” Methode.1 sind die Regressionstests für jede offizielle Version aktuell. geben Sie ein gmake check während Sie sich im obersten Verzeichnis (oder in src/test/regress) befinden.) Alternativ können Sie die Tests nach der Installation ausführen. Das parallele Testen gibt Vertrauen. Am Ende sollten Sie etwas wie ====================== All 77 tests passed. um die Tests durchzuführen. ====================== sehen oder ansonsten eine Mitteilung darüber. Seit PostgreSQL 6. Siehe Abschnitt 26. und dann das Testskript ausgeführt.1 Die Tests ausführen Die Regressionstests können mit einem schon installierten Server ausgeführt werden oder mit einer temporären Installation im Quelltextverzeichnis. wohingegen die parallele Methode mehrere Serverprozesse startet.26 26 Regressionstests Die Regressionstests sind eine umfassende Testsammlung für die SQL-Implementierung in PostgreSQL. dass jemand anders hinter Ihrem Rücken die Testergebnisse verändern könnte. 321 . wie einige Triggerfunktionen als Beispiel.3 unten für mehr. 26. Aus historischen Gründen werden die sequenziellen Tests normalerweise mit einer bestehenden Installation ausgeführt und die parallele Methode mit einer temporären Installation. dass die Interprozesskommunikation und die Sperren richtig arbeiten. (Das einzige mögliche “Sicherheitsproblem” hier ist. welchen Tests fehlgeschlagen sind. Die sequenzielle Methode führt jedes Testskript nacheinander aus. Sie testen standardisierte Operationen und auch die erweiterten Fähigkeiten von PostgreSQL. Dadurch werden erst ein paar Hilfsdateien gebaut. aber dafür gibt es keine technischen Gründe. Verwalten Sie also Ihre Zugriffsrechte weise.

dann müssen Sie nicht nochmal ganz von vorne anfangen. dass diese Grenze mindestens um 75 liegt. 26. Wenn ein Test als nicht bestanden berichtet wird.Kapitel 26 Anmerkung Weil diese Testmethode einen vorübergehenden Testserver startet. falls nicht die Umgebungsvariablen PGHOST und PGPORT anderes aussagen. ein psql und einen Shell-Elternprozess für psql für jedes Testskript. Die Tests werden gegenwärtig mit einem einfachen diff-Vergleich mit den auf einem Bezugssystem erzeugten Ausgaben ausgewertet. In diesem Fall sollten Sie eine andere Bourne-kompatible Shell auf der Befehlszeile angeben. Tipp Auf einigen Systemen wird die Bourne-kompatible Shell verwirrt. wie in Kapitel 16 erklärt. Dadurch kann es vorkommen. Gegenwärtig ist das Höchste 20 parallele Tests. Sie 322 . wodurch die Ergebnisse empfindlich für kleine Unterschiede sind. ansonsten erhalten Sie in den Tests willkürlich scheinende Misserfolge. Wenn Sie die Grenze nicht erhöhen können. dann achten Sie darauf. wegen plattformabhängigen Umständen wie die Darstellung von Fließkommazahlen oder Zeitzonenunterstützung. Wenn Sie schon den Rest des Builds als root gemacht haben. dann können Sie die Datei src/test/regress/parallel_schedule bearbeiten. Zum Beispiel: root# chmod -R a+w src/test/regress root# chmod -R a+w contrib/spi root# su . können Sie wie oben beschrieben den Testplan der parallelen Tests verändern. dass sie den Server auf der lokalen Maschine mit der Standardportnummer kontaktieren können. Um die Tests nach der Installation (siehe Kapitel 14) auszuführen. initialisieren Sie das Datenverzeichnis und starten den Server. was 60 Prozesse bedeutet: ein Serverprozess. und geben Sie dann ein gmake installcheck Die Tests erwarten. Wenn Ihr System eine Begrenzung der Prozesse pro Benutzer hat. melden Sie sich als der Benutzer an und starten Sie die Tests. wenn sie zu viele Kindprozesse gleichzeitig zu verwalten hat. Machen Sie stattdessen das Testverzeichnis durch einen anderen Benutzer schreibbar. sollten Sie immer die Unterschiede zwischen den erwarteten und den tatsächlichen Ergebnissen betrachten. funktioniert Sie nicht als root (der Server startet nicht als root).2 Testauswertung Auf einigen ordnungsgemäß installierten und voll funktionsfähigen PostgreSQL-Installationen könnten trotzdem einige Tests nicht “erfolgreich” sein. um die großen Paralleltestgruppen in kleinere Gruppen aufzuteilen. dass die Tests sich festfahren oder abbrechen.joeuser joeuser$ cd oberstes build verzeichnis joeuser$ gmake check Tipp Die parallelen Tests starten eine ganze Zahl von Prozessen unter Ihrem Benutzerzugang. zum Beispiel: gmake SHELL=/bin/ksh check Wenn keine funktionierende Shell zur Verfügung steht.

wenn zwischendurch die Sommerzeit angefangen oder aufgehört hat. Diese Unterschiede verursachen scheinbar gescheiterte Tests. Um zu überprüfen. dass die Unterschiede nicht erheblich sind.und Zeitergebnisse hängen von der Zeitzone ab.diffs zum Anschauen gespeichert.2. Irgendwelche Unterschiede werden für Sie in der Datei src/ test/regress/regression.out bewältigt viele andere Locales.1 Unterschiede bei Fehlermeldungen Einige der Regressionstests beinhalten absichtlich ungültige Eingabewerte. Wenn die Testergebnisse plattformabhängig sind. Die eigentlichen Ausgabedateien der Tests sind im Verzeichnis src/test/regress/results. kann es Unterschiede wegen der Sortierreihenfolge und eventuelle Folgefehler geben. Im letzteren Fall könnten die Fehlertexte zwischen verschiedenen Plattformen variieren.2. ist die erwartete Ausgabedatei char. können Sie eine neue Datei hinzufügen. was nicht der Fall ist. also können Sie erwarten.) Wenn die bestehenden erwarteten Dateien eine Locale aus irgendwelchen Gründen nicht verarbeiten können. sollten Sie stattdessen die in Abschnitt 26. dass der Testtreiber alle solche Dateien als gleichermaßen gültiges Testergebnis betrachtet.3 Unterschiede bei Datum und Zeit Einige Anfragen im Test horology schlagen fehl. wird es zu Abweichungen kommen. 26. wenn Sie die Tests an einem Tag der Sommer/Winterzeitumstellung oder einen Tag davor oder danach ausführen. die zusammen eine große Zahl von Locales abdecken. Nichtsdestotrotz versuchen wir.2 Unterschiede durch Locales Wenn Sie die Tests auf einem bestehenden Server ausführen. (Das bedeutet. dass die Regressionstests nicht entdecken können. dass alle Tests erfolgreich sind. die aber durch manuelle Inspektion abgetan werden können. 26.) 26. Die Tests suchen sich einfach die Ergebnisdatei. ob das Ergebnis für die eingestellte Locale angebracht ist. geben Sie Folgendes ein: env TZ=PST8PDT date 323 . Denken Sie aber daran.out. Der Testtreiber setzt die Umgebungsvariable PGTZ auf PST8PDT. Die eigentliche Ziffer ist unerheblich. wenn er auf Erfolg prüft oder bei Misserfolg die Unterschiede berechnet. der mit einer anderen Sortierreihenfolge als C initialisiert wurde. Diese Anfragen gehen davon aus. was normalerweise ausreicht.out für die Locales C und POSIX und die Datei char_1. für alle Plattformen genaue Bezugsdateien zur Verfügung zu stellen. Aber Ihr Betriebssystem muss die Zeitzone PST8PDT unterstützen oder die zeitzonenabhängigen Tests werden nicht bestehen. die am besten passt. (Oder wenn Sie wollen. können Sie diff auch selbst ausführen. heute Mitternacht und morgen Mitternacht jeweils genau 24 Stunden ist. indem sie alternative Ausgabedateien haben. Das Testskript verwendet diff. Das Namensschema ist testname_ziffer. Fehlermeldungen kommen entweder vom PostgreSQL-Code oder aus dem Betriebssystem. Beim Test char zum Beispiel. dass der Zeitabstand zwischen gestern Mitternacht. sollten aber ähnliche Informationen darstellen.Regressionstests könnten feststellen. Der Testtreiber wählt automatisch die am besten passende Datei aus. Die Regressionstests sind darauf vorbereitet. ob Ihr System diese Unterstützung hat. um jede Ausgabedatei mit den erwarteten Ergebnissen in Verzeichnis src/ test/regress/expected zu vergleichen. Die Bezugsdateien wurden für die Zeitzone PST8PDT (Kalifornien) erzeugt und wenn die Tests nicht mit dieser Zeitzoneneinstellung durchgeführt werden.3 beschriebene Technik verwenden.2. Die meisten Datums.

wodurch Zeiten in der Zeitzone PDT (entspricht Sommerzeit) vor 1970 als PST (Normalzeit) ausgegeben werden. sind die folgenden: SELECT * from street. (Sortierunterschiede können auch von Locale-Einstellungen verursacht werden. welche meistens 10 Stellen nach dem Komma sind.0. und daher ist die Reihenfolge der Ergebniszeilen nach dem SQL-Standard nicht definiert. anders als von PostgreSQL gegenwärtig erwartet. außer wenn die Anfrage ein ORDER BY hat. Einige Anfragen zeigen aber doch Unterschiede bei der Sortierreihenfolge auf unterschiedlichen Plattformen. um die tatsächliche Erheblichkeit dieser Unterschiede. Die Tests float8 und geometry sind besonders anfällig für kleine Unterschiede zwischen Plattformen. Die Kartendaten sind als Polygone dargestellt. nicht akzeptieren.01. hat Ihr System die Zeit vielleicht in GMT ausgegeben. Ein Vergleich mit dem menschlichen Auge ist vonnöten. Wenn die Zeitzone PST8PDT fehlt. Es sind Unterschiede bei den Ergebnissen mathematischer Funktionen mit Spalten vom Typ double precision beobachtet worden.5 Unterschiede bei Polygonen Einige Tests beinhalten geografische Daten über die Straßenkarte von Oakland/Berkeley.2. 26. Wenn die Zeitzone PST8PDT nicht verfügbar ist. Dadurch gibt es stellenweise Unterschiede in den Testergebnissen. Einige Systeme signalisieren Fehler bei den Funktionen pow() und exp(). um die Zeitzonenregeln selbst einzustellen. Am Anfang werden einige Tabellen erzeugt und mit geografischen Daten geladen. dann werden einige Sichten erzeugt. einzuschätzen. bei denen die gleichen Zeilen in anderer Reihenfolge als in der erwarteten Datei ausgegeben werden.4 Unterschiede bei Fließkommaberechnungen Einige Tests beinhalten die Berechnung von 64-bittigen Fließkommazahlen (double precision) aus Tabellenspalten. das die Anfrage nicht beachtet. In den meisten Fällen ist das streng genommen kein Programmfehler.2. 26. oder selbst bei unterschiedlichen Compiler-Optimierungsoptionen. Stelle nach dem Komma. können Sie die Zeitzonenregeln selbst einstellen: PGTZ='PST8PDT7. da müssen Sie womöglich einen anderen Wert für PGTZ verwenden. Die SQL-Befehle. export PGTZ Es scheint einige Systeme zu geben.05.03'. erhalten wird normalerweise die gleiche Ergebnisreihenfolge auf allen Plattformen und daher ist das fehlende ORDER BY kein Problem.M04. 26.M10. Einige Systeme mit älteren Zeitzonenbibliotheken wenden die Sommerzeitumstellung nicht auf Daten vor 1970 an. dann ist das kein Anlass zur Sorge. Die meisten Regressionstests sind nicht so pedantisch und verwenden ORDER BY nicht bei jedem einzelnen SELECT. Aber sagen Sie uns trotzdem 324 .2. und dann wird eine Anfrage mit der Sicht ausgeführt.6 Unterschiede bei der Zeilenreihenfolge Die könnte einige Unterschiede sehen. wo diese Probleme auftreten. deren Eckpunkte ein Paar Zahlen vom Typ double precision (geografische Länge und Breite) sind. die zwei Tabellen mit dem Polygonschnittoperator (##) verbinden. ergeben sich Unterschiede an der 2. Kalifornien. Da wird aber in der Praxis die gleichen Anfragen ausgeführt mit den gleichen Daten auf der gleichen Software sehen. SELECT * from iexit. oder 3. Wenn man die Ergebnisse unterschiedlicher Plattformen vergleicht.) Wenn Sie also einen Unterschied bei der Sortierreihenfolge sehen. die die empfohlene Syntax.Kapitel 26 Dieser Befehl sollte die aktuelle Systemzeit in der Zeitzone PST8PDT ausgeben.

enthält resultmap horology/hppa=horology-no-DST-before-1970 was für alle Maschinen angewendet wird. die angibt. da sie dann hauptsächlich Anfrageplantypen. warum wir die Testanfragen nicht alle ausdrücklich sortieren lassen und damit das Problem ein für alle Mal aus dem Weg räumen. Andere Zeilen in resultmap wählen alternative Ergebnisdateie für andere Plattformen. Der Vergleichsdateiname ist der Name der Ersatzvergleichsdatei. Das Plattformmuster ist ein Muster im Stile des Unix-Werkzeugs expr (das heißt ein regulärer Ausdruck mit einem impliziten ^ am Anfang). Das verursacht ein paar Unterschiede im Regressionstest horology. Sie fragen sich vielleicht. sollten Sie sich vielleicht doch Sorgen machen. 26. bieten wir eine Methode. der zufällige Ergebnisse liefern soll. 325 . Jede Zeile der Steuerdatei hat die Form testname/plattformmuster=vergleichsdateiname Der Testname ist einfach der Name des bestimmten Regressionstestmoduls. Häufig passt die gleiche Variation für mehrere Plattformen. Zum Beispiel: Einige Systeme mit älteren Zeitzonenbibliotheken wenden die Sommerzeitumstellung nicht auf Daten vor 1970 an. vernachlässigen würden. Der Grund ist. müssen Sie eine alternative Ergebnisdatei wählen oder erstellen und dann eine Zeile zur Steuerdatei resultmap hinzufügen. ob Sie den GNU-Compiler oder den Systemcompiler verwenden (auf den Systemen.3 Plattformspezifische Vergleichsdateien Da einige Tests der Natur der Sache wegen plattformspezifische Ergebnisse produzieren. gibt es eine Datei. (Wenn der Test andererseits auch in vielen Versuchen immer erfolgreich ist. wo es einen Unterschied gibt). wodurch Zeiten vor 1970 in der Zeitzone PDT als PST erscheinen. Daher haben wir eine alternative Vergleichsdatei horology-no-DST-before-1970.2. die keine sortierten Ergebnisse liefern.) 26. Um die falschen Fehlermeldungen auf HPPA-Plattformen auszuschalten. wenn nötig.guess mit hppa anfängt.out erstellt. dass das die Regressionstests weniger nützlich machen würde. damit wir das ORDER BY hinzufügen können und damit die falschen Fehlerberichte in der Zukunft verhindern können. testen würden und solche.7 Der Test random Es gibt mindestens einen Testfall im Test random.guess ausgegebenen Plattformnamen. Es wird verglichen mit dem von config. der Test ist auch nach wiederholten Versuchen nie erfolgreich.out expected/random. Wenn Sie eingeben diff results/random. Sie müssen sich keine Sorgen machen. es sei denn.Regressionstests Bescheid. um plattformspezifische Ergebnisvergleichsdateien anzugeben. die sortierte Ergebnisse liefern. Dadurch fällt der Test ab und zu (vielleicht einmal alle fünf bis zehn Versuche) durch. anstatt eine getrennte Vergleichsdatei für jede Plattform anzugeben. welche Vergleichsdatei für jede Plattform zu verwenden ist. bei denen die Ausgabe von config.out sollten Sie nur einige wenige Zeilen Unterschied sehen. gefolgt von :gcc oder :cc. Um also fälschlicherweise fehlgeschlagene Tests zu eliminieren. je nach dem. die die auf diesen Systemen zu erwartenden Ergebnisse enthält.

.

wie man SQL-Befehle verwendet. um die Datenbank zu bearbeiten und abzufragen (siehe Teil II). die getrennt erhältlich sind und ihre eigene Dokumentation enthalten. 327 . Jedes dieser Kapitel kann einzeln gelesen werden. und natürlich sollten sie die von der Schnittstelle verwendete Programmiersprache kennen. Leser dieses Teils sollten wissen.3 Teil IV Client-Schnittstellen Dieser Teil beschreibt die mit PostgreSQL gelieferten Client-Programmierschnittstellen. Beachten Sie. dass es viele andere Programmierschnittstellen für Clientprogramme gibt.

VAKAT VAKAT .

wie man Programme schreibt. Beachten Sie. PGconn *PQconnectdb(const char *conninfo). 329 . die libpq verwenden. Die Funktion PQstatus sollte verwendet werden. Im Gegensatz zu PQsetdbLogin unten kann die Parametersammlung erweitert werden. die libpq verwenden. libpgtcl (Tcl). die zeigen. ist. Perl und ECPG.27 27 libpq: Die C-Bibliothek libpq ist die Schnittstelle zu PostgreSQL für Anwendungsprogrammierung in C. libpq wird auch als Fundament für mehrere andere PostgreSQL-Anwendungsschnittstellen verwendet. das zu tun. um zu prüfen. Am Ende dieses Kapitels (Abschnitt 27. ohne die Signatur der Funktion zu ändern.) Jede Verbindung wird durch ein Objekt vom Typ PGconn repräsentiert.h einbinden und die libpq-Bibliothek einlinken. die in der Zeichenkette conninfo stehen. Mehrere komplette Beispiele von libpq-Anwendungen finden sich außerdem im Verzeichnis src/test/examples in der Quelltext-Distribution. Einige Aspekte über das Verhalten von libpq sind daher auch für Sie von Bedeutung. 27. Anfragen an den PostgreSQL-Server zu schicken und die Ergebnisse dieser Anfragen zu erhalten. einschließlich libpq++ (C++). müssen die Headerdatei libpq-fe. Ein Anwendungsprogramm kann mehrere Serververbindungen zur gleichen Zeit offen halten. welches von der Funktion PQconnectdb oder PQsetdbLogin erhalten wurde. auf mehrere Datenbanken zuzugreifen. libpq ist eine Sammlung von Bibliotheksfunktionen. Clientprogramme. bevor Anfragen durch das Verbindungsobjekt geschickt werden. PQconnectdb Baut eine neue Verbindung mit dem Datenbankserver auf. Diese Funktion öffnet eine neue Datenbankverbindung mit den Parametern. außer wenn womöglich selbst für das PGconn-Objekt zu wenig Speicher vorhanden ist. dass diese Funktionen nie einen Null-Zeiger ergeben. wenn Sie eines dieser anderen Pakete verwenden.1 Funktionen zur Datenbankverbindung Die folgenden Funktionen dienen zum Aufbau einer Verbindung mit dem PostgreSQL-Server. die es Clientprogrammen erlauben. ob die Verbindung erfolgreich aufgebaut wurde.13) finden Sie drei kurze Programme. (Ein Grund. Daher ist die Verwendung dieser Routine oder der nicht blockierenden Analoga PQconnectStart und PQconnectPoll bei neuen Anwendungen zu bevorzugen.

Apostrophe und Backslashes müssen von einem Backslash eingeleitet werden. zum Beispiel schlüssel = 'ein wert'. Wenn sowohl host als auch hostaddr angegeben werden. außer wenn Kerberos verwendet wird. der Wert für host wird ignoriert. Der Vorgabewert ist eine Unix-Domain-Socket in /tmp. in dem sich die Socketdatei befindet. dann wird dadurch eine umgekehrte Namensauflösung verursacht. Authentifizierung mit Kerberos erfordert allerdings einen Hostnamen. dann wird der Wert für die Authentifizierung mit Kerberos verwendet. Folgendes gilt daher: Wenn host ohne hostaddr angegeben wird. (Um einen leeren Wert oder einen Wert mit Leerzeichen zu schreiben. mit dem verbunden werden soll. Die gegenwärtig erkannten Parameterschlüsselwörter sind: host Name des Servers. dbname Der Datenbankname. setzen Sie Apostrophe darum. hostaddr Die IP-Adresse der Servers. das der Verbindungsfunktion gegeben wird.) Leerzeichen um das Gleichheitszeichen sind wahlfrei. das heißt \' bzw. dann wird eine Verbindung über Unix-Domain-Sockets statt TCP/IP verwendet. Wenn ein nicht leerer Wert angegeben wird. dann wird eine TCP/IP-Verbindung verwendet. password Das Passwort. wenn Kerberos verwendet wird. Null oder nicht gesetzt heißt unendlich. bestimmt der Wert für hostaddr die Serveradresse. um alle Vorgabeparameter zu verwenden. Durch die Verwendung von hostaddr statt host können Anwendungen die Auflösung von Hostnamen vermeiden. wenn Sie libpq einen Hostnamen übergeben. connect_timeout Das Zeitfenster in Sekunden. bestimmt der Wert für hostaddr die Serveradresse. port Die Portnummer. Wenn weder Hostname noch Hostadresse angegeben sind. verbindet libpq über eine lokale UnixDomain-Socket.Kapitel 27 Die angegebene Zeichenkette kann leer sein. bzw. Der Wert sollte in der Standardform aus Zahlen und Punkten bestehen. oder sie kann mehrere durch Whitespace getrennte Parametereinstellungen enthalten. dann wird der Hostname aufgelöst. Beachten Sie. \\. Jede Parametereinstellung hat die Form schlüssel = wert. mit der auf dem Server verbunden werden soll. Wenn hostaddr ohne host angegeben wird. dass die Authentifizierung wahrscheinlich fehlschlagen wird. Wenn der Wert mit einem Schrägstrich anfängt. für den Fall. der Wert ist das Verzeichnis. dass der Server Authentifizierung mit Passwörtern fordert. options 330 . der nicht der wirkliche Name der Maschine mit der Adresse hostaddr ist. user Der Benutzername für die Verbindung. was in Anwendungen mit Zeitvorgaben wichtig sein könnte. die Dateierweiterung bei Verbindungen über Unix-Domain-Sockets.

Es ist hauptsächlich wegen der Kompatibilität mit alten Programmen vorhanden. die an den Server geschickt werden. *login. PQconnectPoll Baut eine neue Verbindung mit dem Datenbankserver auf. Wenn ein Parameter nicht angegeben wurde. wird die entsprechende Umgebungsvariable (siehe Abschnitt 27. *pgport. 331 . Wenn 0 (Vorgabe). PQconnectStart. *pgport. wenn der Server kein SSL anbietet. ohne zu blockieren. PQsetdbLogin Baut eine neue Verbindung mit dem Datenbankserver auf. PGconn *PQconnectStart(const char *conninfo). Diese zwei Funktionen werden verwendet. Wenn die Umgebungsvariable auch nicht gesetzt ist. wird eine SSL-Verbindung mit dem Server verlangt. *pgtty.libpq: Die C-Bibliothek Konfigurationsoptionen. PostgresPollingStatusType PQconnectPoll(PGconn *conn). *dbName). PQsetdb Baut eine neue Verbindung mit dem Datenbankserver auf. PGconn *PQsetdb(char char char char char *pghost. *pgoptions. PGconn *PQsetdbLogin(const const const const const const const char char char char char char char *pghost. *pgoptions. werden die eingebauten Vorgaben verwendet. libpq verweigert dann die Verbindung.9) untersucht. wird libpq den Verbindungstyp mit dem Server aushandeln. *pgtty. Dies ist der Vorgänger von PQconnectdb mit einer festen Zahl von Parametern. requiressl Wenn 1. tty Eine Datei oder ein TTY für Debug-Ausgaben vom Server.oder Ausgabeoperationen blockiert wird. um eine Verbindung mit dem Datenbankserver zu öffnen. das PQsetdbLogin mit Null-Zeigern für die Parameter login und pwd aufruft. *pwd). *dbName. Das ist ein Makro. ohne dass die Anwendung während der Eingabe. aber mit der gleichen Funktionalität.

können diese natürlich auch verwendet werden. Es sei angemerkt. Wenn der Status gleich CONNECTION_BAD ist. Wenn select() anzeigt. zur Verfügung stehen. fahren Sie mit der Verbindungsprozedur fort und achten dabei auf die Statusmeldungen. nur ein (wahrscheinliches) Beispiel ist. dass das Objekt. betrachten Sie sie als “aktiv”. ist die Verbindungsprozedur fehlgeschlagen. warten Sie mit select() auf Schreibfreigabe auf der gleichen Socket. wie oben beschrieben. Wenn Sie PQconnectPoll noch nicht ausgeführt haben. die PQconnectStart übergeben wird. ist die Verbindung bereit. warten Sie mit select() auf lesbare Daten auf der durch PQsokket(conn) ermittelten Socket. ❏ Wenn Sie PQtrace aufrufen. Weder PQconnectStart noch PQconnectPoll blockieren. Schauen Sie in der Dokumentation dieser Parameter oben unter PQconnectdb wegen Einzelheiten nach. dass die Verwendung von select(). rufen Sie PQconnectPoll(conn) noch einmal auf. in das der Datenstrom geschrieben wird. zum Beispiel mit poll(). Wenn PQconnectPoll(conn) zuletzt PGRES_POLLING_READING ergab. erstellt. nach dem AufPQconnectStart. Wenn dies CONNECTION_BAD ergibt. wenn es CONNECTION_OK ergibt. Beide dieser Zustände können genauso durch das Ergebnis der Funktion PQconnectPoll erkannt werden. dann ist PQconnectStart fehlgeschlagen. Wenn PQconnectStart erfolgreich war. Wenn andere Möglichkeiten. Zu jedem beliebigen Zeitpunkt während des Verbindungsaufbaus kann der Zustand der Verbindung mit PQstatus geprüft werden. Nachdem PQconnectStart zurückkehrt. Diese Zustände sind: CONNECTION_STARTED Wartet auf die Erstellung der Verbindung. Wenn dieser Aufruf PGRES_POLLING_FAILED ergibt. betrachten Sie sie stattdessen als “aktiv”. dass die Verbindung “aktiv” ist. Wenn es zuletzt PGRES_POLLING_WRITING ergab. als ob das letzte Ergebnis ruf von PGRES_POLLING_WRITING gewesen wäre. dass die Socket bereit ist. wenn bestimmte Voraussetzungen erfüllt sind: ❏ Die Parameter hostaddr und host werden entsprechend verwendet um Hostnamenauflösungen zu vermeiden. achten Sie darauf. ist die Verbindungsprozedur fehlgeschlagen. Führen Sie folgende Schleife aus: Betrachten Sie eine Verbindung anfangs als “inaktiv”. um Rückmeldungen an den Benutzer zu erzeugen.Kapitel 27 Die Datenbankverbindung wird mit den Parametern in der Zeichenkette conninfo. ❏ Bringen Sie die Socket selbst in den passenden Zustand. konnte libpq nicht genug Speicher für eine neue PGconn-Struktur vergeben. Wenn entschieden wurde. rufen Sie zuerst conn = PQconnectStart("verbindungs_parameter") auf.h. d. Um eine nicht blockierende Verbindung aufzubauen. verhalten Sie sich. CONNECTION_MADE Verbindung in Ordnung. Die Zeichenkette hat das gleiche Format wie unter PQconnectdb beschrieben. rufen Sie status = PQstatus(conn) auf. Wenn conn dann ein Null-Zeiger ist. CONNECTION_AWAITING_RESPONSE 332 . Wenn der Aufruf PGRES_POLLING_OK ergibt. wartet auf Senden. um die Socket zu prüfen. Diese geben dann den aktuellen Fortschritt der Verbindungsprozedur an und können zum Beispiel nützlich sein. bevor Sie PQconnectPoll wie unten beschrieben aufrufen. nicht blockieren kann. Ansonsten erhalten Sie einen gültigen PGconn-Zeiger zurück (der aber noch keine gültige Verbindung zur Datenbank darstellt). Wenn PQconnectPoll zuletzt PGRES_POLLING_ACTIVE ergab. Auch andere Zustände können während einer asynchronen Verbindungsprozedur (und nur) auftreten. wurde die Verbindung erfolgreich aufgebaut.

break. wartet auf Fortsetzung des Verbindungsaufbaus.. Schließlich belassen diese Funktionen die Socket im nicht blockierenden Zustand. default: feedback = "Verbinde. typedef { char char char struct *keyword. PQconndefaults Gibt die Vorgabeverbindungseinstellungen zurück. wenn Sie fertig sind..".libpq: Die C-Bibliothek Wartet auf Antwort vom Server.. Diese Einschränkung wird möglicherweise in der Zukunft entfernt werden. /* Schlüselwort */ /* Name der Umgebungsvariable */ /* eingebauter Vorgabewert */ 333 . case CONNECTION_MADE: feedback = "Mit Server verbunden. *envvar. dass obwohl diese Konstanten bleiben werden (um Kompatibilität zu erhalten). dann beachten Sie. . Beachten Sie.". break. PQconninfoOption *PQconndefaults(void). Eine Anwendung kann Folgendes machen: switch(PQstatus(conn)) { case CONNECTION_STARTED: feedback = "Verbinde. . CONNECTION_AUTH_OK Authentifizierung erhalten. um die Verbindungsstruktur und zugehörige Speicherblöcke freizugeben. } Wenn PQconnectStart einen gültigen Zeiger (nicht Null) zurückgibt. .. dass sie in einer bestimmten Reihenfolge oder überhaupt auftreten oder dass der Zustand immer einer dieser beschriebenen Werte sein wird... wenn PQconnectStart oder PQconnectPoll nicht erfolgreich waren. CONNECTION_SETENV Aushandlung der Umgebung (Teil des Verbindungsaufbaus). dass Sie PQfinish aufrufen müssen. *compiled. eine Anwendung sich niemals darauf verlassen sollte. als ob PQsetnonblocking aufgerufen worden wäre.". Das muss auch getan werden. wenn libpq mit SSL-Unterstützung compiliert wurde. PQconnectPoll blockiert gegenwärtig.

ohne zu blockieren. verursachen Sie mit jedem Aufruf von PQconndefaults ein kleines Speicherleck. wenn eine funktionierende Verbindung verloren gegangen ist.normalerweise nicht anzeigen */ int dispsize. Wenn Sie mit dem Parameterarray fertig sind. anstelle eines dynamisch angelegten Arrays. Ergibt ein Array mit Verbindungsparametern vom Typ PQconninfoOption. Das kann verwendet werden. PQreset Setzt den Kommunikationskanal zum Server zurück. Diese Funktion schließt die Verbindung zum Server und versucht. Beachten Sie. void PQfinish(PGconn *conn). dass die Anwendung PQfinish auch dann aufrufen sollten. Beachten Sie. dass die aktuellen Vorgabewerte (in val) von Umgebungsvariablen und anderen Faktoren abhängen. wenn der Verbindungsversuch mit dem Server fehlgeschlagen ist (durch PQstatus erkennbar). char *label. In PostgreSQL-Versionen vor 7. 334 . Der PGconn-Zeiger sollte nach dem Aufruf von PQfinish nicht mehr verwendet werden. PQfinish Schließt die Verbindung mit dem Server. eine neue Verbindung zum selben Server mit den gleichen Parametern aufzubauen. um alle möglichen Parameter für PQconnectdb und ihre aktuellen Vorgabewerte zu ermitteln. int PQresetStart(PGconn *conn). PostgresPollingStatusType PQresetPoll(PGconn *conn).0 gab PQconndefaults einen Zeiger in ein statisches Array zurück. eine neue Verbindung zum selben Server mit den gleichen Parametern aufzubauen. In das Ergebnis sollte nicht geschrieben werden. Diese Funktionen schließen die Verbindung zum Server und versuchen. /* Feldgröße in Zeichen für Dialogfenster */ } PQconninfoOption. Wenn Sie das nicht tun. sollten Sie es mit PQconninfoFree freigeben. oder NULL */ /* Feldbeschriftung in Dialogfenster */ /* Darstellung des Feldes in einem Dialogfenster: "" normale Darstellung "*" Passwort . Das kann zur Fehlerbehandlung nützlich sein. Das kann zur Fehlerbehandlung nützlich sein. void PQreset(PGconn *conn). Gibt außerdem den vom PGconn-Objekt belegten Speicher frei. char *val. PQresetPoll Setzen den Kommunikationskanal zum Server zurück. Der letzte Eintrag des Arrays hat einen Null-Zeiger im Feld keyword. PQresetStart.nicht darstellen "D" Debugoption . Das war nicht Thread-sicher und wurde deswegen geändert.Kapitel 27 /* aktueller Vorgabewert. um den vom PGconn-Objekt belegten Speicher freizugeben. char *dispchar.

char *PQport(const PGconn *conn). libpq-Anwendungsprogrammierer sollten darauf achten. char *PQpass(const PGconn *conn). als ob Sie die Verbindung über PQconnectPoll aufbauen. PQpass Ergibt das Passwort der Verbindung. ist er fehlgeschlagen. um auf den Inhalt von PGconn zuzugreifen. die Abstraktion von PGconn zu bewahren.h vorhanden. PQhost Ergibt den Serverhostnamen der Verbindung. dass sie auf eine nicht blockierende Art und Weise vorgehen. Vermeiden Sie es. char *PQuser(const PGconn *conn). aber Sie sollten Ihren Code sehr bald ausbessern. Sie haben dabei die gleichen Einschränkungen wie PQconnectStart und PQconnectPoll. Wenn es 0 ergibt. Wenn Sie alten Code haben. Um einen Verbindungs-Reset einzuleiten. char *PQhost(const PGconn *conn). rufen Sie PQresetStart auf. PQtty Ergibt das TTY für Debugausgaben der Verbindung. überwachen Sie den Reset mit PQresetPoll auf genau die gleiche Art. Die Werte sind während der Lebenszeit des PGconn-Objekts unveränderlich. Sie unterscheiden sich von PQreset (siehe oben) dadurch. PQoptions 335 . weil diese sich in der Zukunft ändern könnten. wenn Sie zusätzlich die Datei libpq-int. PQport Ergibt den Port der Verbindung. der auf die Felder von PGconn direkt zugreift. char *PQdb(const PGconn *conn). Wenn es 1 ergibt.libpq: Die C-Bibliothek wenn eine funktionierende Verbindung verloren gegangen ist.h einbinden. die bei der Verbindung festgestellt werden. können Sie ihn weiter verwenden. PQuser Ergibt den Benutzernamen der Verbindung. (Seit PostgreSQL 6.) PQdb Ergibt den Datenbanknamen der Verbindung. PQdb und die nächsten paar Funktionen ergeben die Werte.4 ist die Definition des struct hinter PGconn nicht mehr in der Datei libpq-fe. direkt auf die Felder der PGconn-Struktur zuzugreifen. char *PQtty(const PGconn *conn). Verwenden Sie die folgenden Zugriffsfunktionen.

aber ein Kommunkationsfehler kann dazu führen. PQerrorMessage Ergibt die Fehlermeldung. dass die PID zu einem Prozess auf der Datenbankservermaschine und nicht auf der lokalen Maschine gehört! PQgetssl Ergibt die SSL-Struktur für die Verbindung oder einen Null-Zeiger. Beachten Sie. Informationen über diese Struktur finden Sie in der Anleitung zu OpenSSL. die in der Verbindungsanfrage übergeben wurden. SSL *PQgetssl(const PGconn *conn). int PQbackendPID(const PGconn *conn). bleibt er normalerweise so bis zu PQfinish. 336 . Eine Verbindung. PQbackendPID Ergibt die Prozesskennung (PID) des Serverprozesses. Beachten Sie. Dadurch wird auch automatisch ssl. Schauen Sie im Eintrag für PQconnectStart und PQconnectPoll bezüglich der anderen möglichen Statuscodes nach. In diesem Fall könnte die Anwendung versuchen. Diese Struktur kann verwendet werden. char *PQoptions(const PGconn *conn). hat den Status CONNECTION_OK. wenn ein Fehler auftritt. Wenn der Status in Ordnung ist. PQstatus Ergibt den Status der Verbindung.Kapitel 27 Ergibt die Konfigurationsoptionen. müssen Sie USE_SSL definieren. das Ergebnis -1 sagt aus. die zuletzt durch eine Operation auf dieser Verbindung verursacht wurde. Die PID kann zum Debuggen nützlich sein und um NOTIFY-Mitteilungen zuzuordnen (da diese die PID des Ursprungsprozesses enthalten). die Verbindung mit PQreset zu erneuern. um Verschlüsselungsgrade zu ermitteln. Fast alle libpq-Funktionen setzen eine Meldung für PQerrorMessage. dass aktuell keine Verbindung offen ist. der diese Verbindung bearbeitet. wenn SSL nicht verwendet wird. die in Ordnung ist. Serverzertifikate zu prüfen und mehr. dass der Status vorzeitig auf CONNECTION_BAD wechselt. Nur zwei davon werden allerdings außerhalb einer asynchronen Verbindungsprozedur auftreten: CONNECTION_OK und CONNECTION_BAD. ConnStatusType PQstatus(const PGconn *conn). PQsocket Ermittelt die Dateideskriptor-Nummer der mit dem Server verbundenen Socket.h von OpenSSL eingebunden. Um den Prototyp für diese Funktion sichtbar zu machen. Der Status kann einer aus einer Reihe von Werten sein. Ein gültiger Deskriptor ist größer oder gleich 0. char *PQerrorMessage(const PGconn* conn). int PQsocket(const PGconn *conn). Ein gescheiterter Verbindungsversuch wird vom Status CONNECTION_BAD signalisiert. dass ein nicht leeres PQerrorMessage-Ergebnis ein abschließendes Newline-Zeichen enthält.

direkt auf die Felder der PGresult-Struktur zuzugreifen. aber Sie sollten Ihren Code sehr bald ausbessern. Das Ergebnis von PQresultStatus ist einer der folgenden Werte: PGRES_EMPTY_QUERY Die an den Server gesendete Zeichenkette war leer. wenn der Befehl nicht an den Server geschickt werden konnte.4 ist die Definition des struct hinter PGresult nicht mehr in der Datei libpq-fe. wie zum Beispiel. const char *command). können Sie ihn weiter verwenden. Die Funktion ergibt einen Zeiger auf ein PGresult oder möglicherweise einen Null-Zeiger. der keine Daten liefert. wenn Sie zusätzlich die Datei libpq-int. PGRES_COMMAND_OK Erfolgreicher Abschluss eines Befehls.2 Funktionen zur Ausführung von Befehlen Wenn eine Verbindung mit dem Datenbankserver erfolgreich aufgebaut wurde.h vorhanden. weil diese sich in der Zukunft ändern könnten. Die Struktur PGresult enthält das vom Server geschickte Ergebnis. PGRES_TUPLES_OK Die Anfrage wurde erfolgreich ausgeführt. Normalerweise wird ein gültiger Zeiger zurückgegeben. PGresult *PQexec(PGconn *conn.1 Hauptfunktionen PQexec Schickt einen Befehl an den Server und wartet auf das Ergebnis.2. Verwenden Sie PQerrorMessage. außer wenn der Speicher knapp ist oder bei ernsthaften Fehlern. um mehr Informationen über den Fehler zu erhalten. dann werden die hier beschriebenen Funktionen verwendet.) PQresultStatus Ergibt den Status des Befehls. ExecStatusType PQresultStatus(const PGresult *res). libpq-Anwendungsprogrammierer sollten darauf achten. PGRES_COPY_IN 337 .h einbinden. 27. um auf den Inhalt von PGresult zuzugreifen. (Seit PostgreSQL 6. der auf die Felder von PGresult direkt zugreift. die Abstraktion von PGresult zu bewahren.libpq: Die C-Bibliothek 27. sollte es wie ein Ergebnis mit Status PGRES_FATAL_ERROR behandelt werden. Verwenden Sie die folgenden Zugriffsfunktionen. um SQL-Anfragen und -Befehle auszuführen. PGRES_COPY_OUT Ausgehender COPY-Datentransfer (vom Server) gestartet. Vermeiden Sie es. Wenn Sie alten Code haben. Wenn das Ergebnis ein Null-Zeiger ist.

wenn es nicht mehr benötigt wird. PGRES_NONFATAL_ERROR Ein nicht fataler Fehler trat auf. Wenn die Antwort PGRES_EMPTY_QUERY ist. und verwenden Sie PQerrorMessage. PGRES_FATAL_ERROR Ein fataler Fehler trat auf. PQmakeEmptyPGresult 338 . dann deutet das oft auf einen Fehler in der Clientsoftware hin. char *PQresultErrorMessage(const PGresult *res). Direkt nach einem Aufruf von PQexec oder PQgetResult ergibt PQerrorMessage (aufgerufen mit der Verbindung als Argument) das gleiche Resultat wie PQresultErrorMessage (aufgerufen mit dem Ergebnis als Argument). UPDATE usw. void PQclear(PQresult *res). PGRES_COMMAND_OK ist für Befehle. dass ein SELECT-Befehl. Verwenden Sie PQresultErrorMessage. Sie können ein PGresult-Objekt so lange behalten. Ein PGresult behält allerdings die Fehlermeldung. Beachten Sie.Kapitel 27 Eingehender COPY-Datentransfer (zum Server) gestartet. die niemals Zeilen als Ergebnis haben (INSERT. verursachen Sie Speicherlecks in ihrer Clientanwendung. bis es zerstört wird. wenn kein Fehler vorliegt. wenn Sie den Status eines bestimmten PGresult-Objekts wissen wollen. müssen Sie PQclear aufrufen. Jedes Befehlsergebnis sollte mit PQclear freigegeben werden. wie sie wollen. char *PQresStatus(ExecStatusType status). PQresultErrorMessage Ergibt die von dem Befehl verursachte Fehlermeldung oder eine leere Zeichenkette. Wenn Sie das nicht tun. wenn ein neuer Befehl ausgeführt wird oder gar wenn die Verbindung geschlossen wird. um die von der Anfrage gelieferten Zeilen auszulesen. die den Statuscode beschreibt. es bleibt auch gültig.). PGRES_BAD_RESPONSE Die Antwort des Servers wurde nicht verstanden. der zufällig null Zeilen im Ergebnis hat. wenn Sie den Status der letzten Operation auf einer Verbindung wissen wollen. PQresStatus Wandelt den von PQresultStatus ermittelten Statuscode in eine Textkonstante um. PQclear Gibt den zu einem PGresult-Objekt gehörenden Speicherplatz frei. trotzdem PGRES_TUPLES_OK anzeigt. Wenn das Ergebnis PGRES_TUPLES_OK ist. können die unten beschriebenen Funktionen verwendet werden. wohingegen die Fehlermeldung im Verbindungsobjekt bei der nächsten Operation geändert wird. Um es zu entfernen.

Ergebnisobjekte (besonders solche mit Fehlerstatus) selbst zu erzeugen. wird die aktuelle Fehlermeldung der angegebenen Verbindung in das PGresult-Objekt kopiert. die dem Bytewert entspricht. Vielmehr sollten Sie bestimmte Zeichen.3 Binäre Daten für SQL-Befehle vorbereiten PQescapeBytea Bereitet binäre Daten zur Verwendung in SQL-Befehlen mit dem Typ bytea vor. 27. und der Parameter from_length gibt die Anzahl der Bytes in dieser Datenkette an. wenn Sie in einer bytea-Konstante in einem SQL-Befehl verwendet werden. ansonsten ist das Verhalten undefiniert. in der Sonderzeichen durch Fluchtfolgen ersetzt worden sind. PQescapeString führt diese Operation aus.2. Weitere Informationen finden Sie in Abschnitt 8. die vom SQL-Parser besonders behandelt werden. dass von libpq selbst erzeugt wurde. Der Apostroph (') und der Backslash (\) haben besondere Fluchtfolgen. sollten Sie diese aus Sicherheitsgründen nicht direkt in einen SQL-Befehl einbauen. noch wird es mitgezählt. size_t length).libpq: Die C-Bibliothek Konstruiert eine leeres PGresult-Objekt mit dem angegebenen Status. Das ist die Funktion. wenn die Parameter to und from sich überschneiden. Das Verhalten ist nicht definiert. (Ein Null-Byte am Ende ist weder notwendig. 27. Ein Aufruf von PQescapeString schreibt eine Version der Zeichenkette from in den Puffer to. indem bestimmte Zei- chen durch Fluchtfolgen ersetzt werden. Das Ergebnis von PQescapeString ist die Anzahl der nach to geschriebenen Zeichen. size_t *to_length). die von libpq intern verwendet wird. Generell wird bei einer solchen Umwandlung ein Byte durch eine dreistellige Oktalzahl. Wenn conn kein Null-Zeiger ist und status einen Fehler anzeigt. Die Apostrophe. der bearbeitet werden soll. size_t from_length. Der Parameter from zeigt auf das erste Byte der Kette. genauso wie bei einem PGresult. weil manche Anwendungen es praktisch finden.4. Wenn Sie Zeichenketten verwenden wollen. unsigned char *PQescapeBytea(unsigned char *from. sodass sie kein Unheil anrichten können. durch Fluchtfolgen ersetzen. Sie ist öffentlich. Beachten Sie. und der Parameter length zählt die Zeichen im Text. ohne das abschließende Null-Byte. const char *from. dass das Ergebnis mit PQclear freigegeben werden muss. PGresult* PQmakeEmptyPGresult(PGconn *conn. um ein leeres PGresult-Objekt anzulegen. PQescapeBytea führt diese Operation aus und wandelt nur die Bytes um.2 Zeichenketten für SQL-Befehle vorbereiten PQescapeString bereitet Zeichenketten zur Verwendung in SQL-Befehlen vor. der mindestens ein Zeichen mehr als zweimal der Wert von length aufnehmen.) to muss auf einen Puffer zeigen. Der Parameter from zeigt auf das erste Zeichen des Textes. die aus nicht vertrauenswürdigen Quellen stammen (zum Beispiel weil irgendein wahlloser Benutzer sie eingegeben hat). die um eine Zeichenkettenkonstante in PostgreSQL gehören. (Ein abschließendes Null-Byte ist we- 339 . die bearbeitet werden soll. Bestimmte Bytewerte müssen durch Fluchtfolgen ersetzt werden (aber alle Bytewerte dürfen durch Fluchtfolgen ersetzt werden). bei denen es nötig ist. sind nicht Teil des Ergebnisses.2. size_t PQescapeString (char *to. ExecStatusType status). und einen vorangestellten Backslash ersetzt. und fügt ein abschließendes Null-Byte an.

die die Länge der umgewandelten Datenkette aufnimmt. Ein abschließendes Null-Byte wird angehängt. sodass sie vom Zeichenkettenparser und von der bytea-Eingabefunktion ordnungsgemäß verarbeitet werden können. Das Ergebnis ist -1. int PQnfields(const PGresult *res). 27. wenn es auf eine bytea-Spalte angewendet wird. wie sie zum Beispiel von PQgetvalue zurückgegeben werden. char *PQfname(const PGresult *res. Das Ergebnis ist ein Zeiger in einem mit malloc() angelegten Puffer. in der alle Sonderzeichen durch Flucht- folgen ersetzt wurden.4 Ermittlung von Informationen über Anfrageergebnisse PQntuples Ergibt die Anzahl der Zeilen (Tupel) im Anfrageergebnis. Der Parameter from zeigt auf eine Zeichenkette mit bytea-Fluchtfolgen. die Länge des Puffers wird in to_length abgelegt. unsigned char *PQunescapeBytea(unsigned char *from. PQfname Ergibt den Spaltennamen der Spalte mit der angegebenen Nummer. Spaltennummern beginnen bei 0. PQftype 340 . PQunescapeBytea wandelt diese Zeichendarstellung in die entsprechende binäre Darstellung um. int PQntuples(const PGresult *res). PQunescapeBytea Wandelt eine Zeichenkettendarstellung mit Fluchtfolgen von binären Daten in binäre Daten um – die Umkehrung von PQescapeBytea. int spalten_nummer). Die Apostrophe. PQescapeBytea ergibt eine Version der Binärdaten in from.) Der Parameter to_length zeigt auf eine Variable. PQnfields Ergibt die Anzahl der Spalten (Felder) in jeder Zeile des Anfrageergebnisses. size_t *to_length).2. Die Länge des Ergebnis schließt das abschließende Null-Byte im Ergebnisses mit ein. wenn keine Spalte den angegebenen Namen hat. oder bei einem Fehler ein Null-Zeiger. PQfnumber Ergibt die Spaltennummer zum angegebenen Spaltennamen. sind nicht Teil des Ergebnisses.Kapitel 27 der notwendig noch wird es mitgezählt. die um eine Zeichenkettenkonstante in PostgreSQL gehören. const char *field_name). int PQfnumber(const PGresult *res. Der Ausgabepuffer wird mit malloc() angelegt.

Bei den meisten Anfragen ist der von PQgetvalue zurückgegebene Wert eine Zeichenkettendarstellung. mit einem abschließenden Null-Byte.5 Auslesen von Anfrageergebnissen PQgetvalue Liest einen einzelnen Spaltenwert aus einer Zeile aus einem PGresult. also die Größe in der internen Darstellung des Servers. Es liegt dann in der Verantwortung des Programmierers. Spaltennummern beginnen bei 0. int spalten_nummer).und Spaltennummern beginnen bei 0. Sie können die Systemtabelle pg_type abfragen. PQfsize Ergibt die Größe in Bytes der Spalte mit der angegebenen Nummer. int spalten_nummer). wenn es Textdaten enthält. die Daten in den korrekten C-Typ umzuwandeln. int spalten_nummer). wie viel Speicher die Spalte in einer Datenbankzeile belegt. Aber wenn PQbinaryTuples 1 ergibt.libpq: Die C-Bibliothek Ergibt den Datentyp der Spalte mit der angegebenen Nummer. char* PQgetvalue(const PGresult *res. um Namen und Eigenschaften der verschiedenen Datentypen zu erfahren. dann ist der von PQgetvalue zurückgegebene Wert in der internen binären Darstellung des Typs wie im Server (aber ohne das Größenwort. 341 . Oid PQftype(const PGresult *res. wenn die Spalte eine variable Größe hat. und 0. wenn das PGresult binäre Zeilendaten enthält. Die OIDs der eingebauten Datentypen sind in der Datei src/include/catalog/pg_type. Spaltennummern beginnen bei 0. PQbinaryTuples Ergibt 1. 27. Das Ergebnis ist ein ganzzahliger Typ. int spalten_nummer). Spaltennummern beginnen bei 0. wenn der Typ eine variable Länge hat).h im Quelltextbaum definiert. die Daten aus einem binären Cursor ausliest. Zeilen. int PQbinaryTuples(const PGresult *res). int zeilen_nummer. int PQfmod(const PGresult *res. PQfsize ergibt. Das Ergebnis ist -1. der die interne OID-Nummer des Typs darstellt. int PQfsize(const PGresult *res.2. PQfmod Ergibt die typenspezifischen Modifikationsdaten der Spalte mit der angegebenen Nummer. Gegenwärtig können binäre Zeilendaten nur von einer Anfrage erzeugt werden.

das heißt die Größe des durch PQgetvalue erhaltenen Objekts. Beachten Sie. pqbool align. /* Ausgabestrom */ const PGresult *res. PQgetisnull Testet.und Spaltennummern beginnen bei 0. Man sollte die Daten. der zur PGresult-Struktur gehört. pqbool standard. zurückgibt. wenn die Spalte den NULL-Wert enthält. pqbool expanded. wenn nicht. int spalten_nummer). Dies ist die wirkliche Länge des Datenwerts.Kapitel 27 Der von PQgetvalue erhaltene Zeiger zeigt in einen Speicherbereich. auf die er zeigt. Zeilen.) PQgetlength Ergibt die Länge eines Spaltenwerts in Bytes. keinen Null-Zeiger. int spalten_nummer). } PQprintOpt. int PQgetlength(const PGresult *res. Zeilen. um Anfrageergebnisse auszugeben. int PQgetisnull(const PGresult *res. PQprint Gibt alle Zeilen und wahlweise die Spaltennamen im angegebenen Ausgabestrom aus. char *tableOpt. int zeilen_nummer. 342 . und man muss die Daten selbst in einen anderen Speicher kopieren. /* /* /* /* /* /* /* /* /* /* Kopfzeilen und Zeilenzahl ausgeben */ Felder mit Leerzeichen ausrichten */ altes blödes Format */ HTML-Tabellen ausgeben */ erweitertes Format */ Pager wenn nötig verwenden */ Feldtrennzeichen */ Attribute für table-Element in HTML */ Caption in HTML-Tabellen */ Ersatzfeldnamen (Array mit NULL abgeschlossen) */ Diese Funktion wurde früher von psql verwendet. Diese Funktion ergibt 1. char *caption. (Beachten Sie.und Spaltennummern beginnen bei 0. typedef struct { pqbool header. dass bei Daten in Textformat dies wenig mit der von PQfsize ermittelten binären Größe zu tun hat. char *fieldSep. nicht verändern. dass PQgetvalue bei NULL-Werten eine leere Zeichenkette. char **fieldName. void PQprint(FILE* fout. pqbool pager. wenn man sie über die Lebensdauer der PGresult-Struktur hinaus verwenden will. und 0. aber das ist nicht mehr der Fall und die Funktion wird nicht mehr aktiv betreut. pqbool html3. int zeilen_nummer. const PQprintOpt *po). ob eine Spalte den NULL-Wert enthält.

27. Wenn die gesendete Befehlszeichenkette mehrere SQL-Befehle enthält. Wenn der Befehl ein anderer war. char * PQoidStatus(const PGresult *res). Sie ist auch nicht Thread-sicher.2. PQoidValue Ergibt die OID der eingefügten Zeile.6 Ermittlung von Ergebnissen anderer Befehle PQcmdStatus Ergibt die Statuszeichenkette des SQL-Befehls. der das PGresult geschaffen hat. die für einige Benutzer von Bedeutung sein können: ❏ PQexec wartet. das genau eine Zeile eingefügt hat. wenn die SQL-Anweisung ein INSERT war. aber nicht anders.) Wenn der Befehl kein INSERT war. char * PQcmdTuples(PGresult *res).libpq: Die C-Bibliothek 27. der dieses PGresult geschaffen hat. ergibt dies eine leere Zeichenkette. (Es geht mit einem Signalhandler. Oid PQoidValue(const PGresult *res). Der Typ Oid und die Konstante InvalidOid sind definiert. Ansonsten ergibt es InvalidOid. 343 . dass sie den aktiven Befehl abbrechen möchte. Sie hat allerdings ein paar Mängel. wenn Sie die libpq-Headerdatei eingebunden haben. PQcmdTuples Ergibt die Anzahl der Zeilen. ❏ Da die Ausführung der Clientanwendung angehalten ist. Wenn der SQL-Befehl. während sie auf das Ergebnis wartet. die die Anzahl der betroffenen Zeilen angibt. ergibt dies eine Zeichenkette. Beide sind ein ganzzahliger Typ.) ❏ PQexec kann nur eine PGresult-Struktur zurückgeben. wenn das INSERT nicht genau eine Zeile eingefügt oder die Zieltabelle keine OIDs hat. dann ergibt die Funktion eine leere Zeichenkette. PQoidStatus Ergibt eine Zeichenkette mit der OID der eingefügten Zeile. wenn die SQL-Anweisung ein INSERT war. UPDATE oder DELETE war.3 Asynchrone Befehlsverarbeitung Die Funktion ist angemessen für das Absenden von Befehlen in normalen. synchronen Anwendungen. bis der Befehl abgeschlossen ist. char * PQcmdStatus(PGresult *res). Die Anwendung hat möglicherweise andere Dinge zu tun (zum Beispiel eine Benutzerschnittstelle zu bedienen) und kann nicht blockieren. während sie auf das Ergebnis wartet. ist es schwer für die Anwendung zu entscheiden. und die Zieltabelle OIDs hat. (Die Zeichenkette ist 0. die eine Zahl enthält. dann werden alle PGresult-Ergebnisse außer dem letzten von PQexec verworfen. Dieser Funktion sollte PQoidValue vorgezogen werden. INSERT. auf die der SQL-Befehl Auswirkung hatte.

PQsetnonblocking Stellt den Blockierzustand der Verbindung ein. wenn arg 1 ist. dann wird der Zustand der Verbindung vorübergehend auf blockierend gestellt. ehe PQgetResult einen Null-Zeiger zurückgegeben hat. und 0 im blockierenden Modus. wenn die Verbindung im nicht blockierenden Modus ist. wenn arg 0 ist. sondern einen Fehler zurückgeben. PQsendQuery kann nicht erneut (auf derselben Verbindung) aufgerufen werden. Ältere Programme. Nach einem erfolgreichen Aufruf von PQsendQuery rufen Sie PQgetResult einmal oder mehrmals auf. int PQsendQuery(PGconn *conn. wenn der Befehl erfolgreich gesendet wurde. die diese Funktionalität sowie PQputline und PQputnbytes benutzen. PQisnonblocking Ergibt den Blockierzustand der Datenbankverbindung.Kapitel 27 Anwendungen. wenn sie nochmal aufgerufen werden müssen. und blokkierend. die diese Beschränkungen nicht mögen. ohne auf das Ergebnis zu warten. Im nicht blockierenden Zustand werden Aufrufe von PQputline. 344 . int arg). können blockieren. Wenn der Befehl beendet ist und es keine weiteren Ergebnisse gibt. um die Ergebnisse zu erhalten. wenn alles in Ordnung ist. PQputnbytes. Wenn eine Datenbankverbindung sich im nicht blockierenden Modus befindet und PQexec aufgerufen wird. PQsendQuery und PQendcopy nicht blockieren. PGresult *PQgetResult(PGconn *conn). wurde die Funktion PQsetnonblocking hinzugefügt. welcher anzeigt. Der Zustand wird auf nicht blockierend gesetzt. während sie darauf warten. um eine vollständig blockierungsfreie Verbindung mit dem Server zu erreichen. und 0. Gibt 0 zurück. Um diesem Problem zu begegnen. PQgetResult Wartet auf das nächste Ergebnis eines vorangegangenen PQsendQuery-Aufrufs und gibt es zurück. Ältere Anwendungen können PQsetnonblokking weiterhin vernachlässigen und erhalten eine möglicherweise blockierende Verbindung. dass in der Zukunft weitere Teile von libpq für den nicht blockierenden Modus bereitgemacht werden. Der Rückgabewert ist 1. const char *query). wenn nicht (in dem Fall können Sie mit PQerrorMessage Informationen über den Fehler erhalten). Es ist zu erwarten. Ergibt 1. int PQisnonblocking(const PGconn *conn). die auch PQexec zugrunde liegen: PQsendQuery und PQgetResult. können die Funktionen verwenden. Daten an den Server zu schicken. int PQsetnonblocking(PGconn *conn. PQsendQuery Schickt einen Befehl an den Server. und -1 bei einem Fehler. dass der Befehl beendet ist. wird ein Null-Zeiger zurückgegeben. bis der PQexec-Aufruf vorbei ist. Neuere Programme können PQsetnonblocking verwenden.

bis es einen Null-Zeiger zurückgibt. Nur Anwendungen. oben beschriebenen Zugriffsfunktionen für PGresult verarbeitet werden. jedes Ergebnisobjekt mit PQclear freizugeben. daher muss zuerst PQconsumeInput aufgerufen werden. oder EOF. ob ihr Status sich geändert hat. Wenn 0 zurückgegeben wird. dass das Ergebnis nicht aussagt. und kann die Ergebnisse dann untersuchen. während der Server noch an den folgenden Befehlen in derselben Befehlszeichenkette arbeitet. flush). das heißt. Beachten Sie. PQconsumeInput kann auch aufgerufen werden. bevor select() ver- wendet wird. PQisBusy Ergibt 1. dass keine Daten zwischengespeichert sind. wenn ein Befehl aktiv ist und die notwendigen Antwortdaten noch nicht von PQconsumeInput gelesen wurden. Das kann durch die richtige Verwendung dreier weiterer Funktionen vermieden werden: PQconsumeInput Konsumiert Daten vom Server. oder der beschäftigte Zustand wird niemals enden. ergibt PQgetResult sofort einen Null-Zeiger. um zu überprüfen. dass PQgetResult nur blockiert. die noch an den Server geschickt werden müssen. wenn ein Fehler auftrat. (Wenn es aufgerufen wird und kein Befehl aktiv ist. PQisBusy liest selbst keine Daten vom Server. Nach dem Aufruf von PQconsumeInput kann die Anwendung PQisBusy und/oder PQnotifies aufrufen. PQconsumeInput ergibt normalerweise 1. wenn die Anwendung noch nicht bereit ist. können die Ergebnisse dieser Befehle einzeln ausgelesen werden. Die Funktion liest die verfügbaren Daten und speichert sie in einem Puffer. die PQsetnonblocking verwendet haben. wel- cher anzeigt.) Jedes Ergebnis von PQgetResult (außer Null-Zeiger) sollte mit denselben. PQflush Versucht etwaige zwischengespeicherte Daten an den Server zu schicken (sog. ob irgendwelche Daten angesammelt wurden. aber 0. dass der Befehl beendet ist. wenn es passt. um zu prüfen. wenn kein Fehler vorliegt. ein Er- gebnis oder eine Nachricht zu verarbeiten. int PQflush(PGconn *conn). PQflush muss auf einer nicht blockierenden Verbindung aufgerufen werden. haben dies nötig. dann ist sichergestellt. wenn ein Befehl beschäftigt ist. Die Verwendung von PQsendQuery und PQgetResult löst eins der Probleme von PQexec: Wenn eine Befehlszeichenkette mehrere SQL-Befehle enthält. int PQisBusy(PGconn *conn). falls vorhanden. int PQconsumeInput(PGconn *conn). Beachten Sie. kann PQgetResult mit der Versicherung aufgerufen werden. 345 . wenn Sie damit fertig sind. ob eine Antwort angekommen ist. (Das ermöglicht übrigens eine einfache Form der überschneidenden Verarbeitung: Der Client kann die Ergebnisse eines Befehls verarbeiten. dass es nicht blockieren wird. Ergibt 0. Vergessen Sie auch nicht. wenn irgendein Problem auftrat (dann kann PQerrorMessage verwendet werden).) Durch einen Aufruf von PQgetResult wird die Clientanwendung allerdings nach wie vor blockieren. Die Anwendung kann also PQconsumeInput verwenden. wodurch die Anzeige von lesbaren Daten in select() verschwindet. um den select()-Zustand sofort zu löschen. wenn es erfolgreich war (oder keine Daten zwischengespeichert waren).libpq: Die C-Bibliothek PQgetResult muss so lange wiederholt aufgerufen werden. wenn PQgetResult beim Warten auf Daten blockieren würde. Wenn 0 zurückgegeben wird. bis der Server den nächsten SQL-Befehl abgeschlossen hat.

die diese Funktionen verwendet. int fnid. was für select() bedeutet. Wenn die Hauptschleife das entdeckt. und 0. Nicht blockierende Verbindungen (solche. was ein mögliches Sicherheitsloch darstellen kann. Dadurch wird direkter Zugriff auf Systeminterna gegeben. hat eine Hauptschleife.ruft PQrequestCancel im Signalhandler für SIGINT auf und ermöglicht dadurch das interaktive Abbrechen von Befehlen. die Bearbeitung des aktuellen Befehls abzubrechen. wird im Client keine Auswirkung zu erkennen sein. dass auf dem durch PQsokket ermittelten Dateideskriptor Daten zum Lesen bereitstehen. int result_is_int. Der Rückgabewert ist 1. const PQArgBlock *args. um Funktionsaufrufe an den Server zu schicken. einen Befehl. wenn PQisBusy 0 ergab. abzubrechen. PQrequestCancel Bittet den Server. an den Server geschickt zu werden. (Wenn nicht. int *result_buf. die PQsetnonblocking verwendet haben). dass. was anzeigt. int nargs). wird der aktuelle Befehl vorzeitig beendet und liefert ein Ergebnis mit einer Fehlermeldung. Wenn der Abbruchversuch scheitert (vielleicht weil die Bearbeitung des Befehls schon beendet war). kann auch versuchen. die es mit PQexec ausführt. Die Funktion PQfn fordert die Ausführung einer Serverfunktion über die Fast-Path-Schnittstelle an: PGresult* PQfn(PGconn* conn. wenn der Abbruchversuch in einem Signalhandler ausgelöst wird. um NOTIFY-Nachrichten zu entdecken (siehe Abschnitt 27. Ungeachtet des Rückgabewerts von PQrequestCancel muss die Anwendung mit der normalen Folge von PQgetResult-Aufrufen fortfahren. int PQrequestCancel(PGconn *conn). der PQsendQuery/PQgetResult verwendet. Fastpath. 27. PQrequestCancel kann ohne Probleme von einem Signalhandler aus aufgerufen werden. dann sollte sie PQconsumeInput aufrufen.4 Die Fastpath-Schnittstelle PostgreSQL bietet eine besondere Schnittstelle. dass vom Server Daten zum Lesen vorhanden sind. Ein Client. die ganze Transaktion abgebrochen wird. Wenn der Abbruch Erfolg hatte. int *result_len.Kapitel 27 Eine typische Anwendung. Man kann die Funktion also auch in Verbindung mit dem normalen PQexec verwenden. typedef struct { 346 . wenn nicht. um auf alle Ereignisse zu warten. warum nicht. dass die Anfrage irgendeine Auswirkung haben wird. die select() aufruft. wenn PQflush 0 zurückgegeben hat. Die meisten Benutzer werden diese Fähigkeit nicht benötigen. gefolgt von PQgetResult. der noch vom Server bearbeitet wird. um die Daten zu lesen. Eins dieser Ereignisse wird sein. psql zum Beispiel. dann gibt PQerrorMessage Auskunft. Beachten Sie. sollten select() erst aufrufen. wenn die Abbruchanfrage erfolgreich abgeschickt wurde. Sie kann außerdem PQnotifies aufrufen. dass keine zwischengespeicherten Daten noch darauf warten. auf die sie reagieren muss. wenn der aktuelle Befehl Teil eines Transaktionsblocks ist.5).) Das erfolgreiche Abschicken gibt allerdings keine Gewähr dafür. Sie kann dann PQisBusy aufrufen.

27. wenn ein NOTIFY-Befehl mit dem Namen der Benachrichtigung von irgendeiner Sitzung ausgeführt wird. wenn sie nicht mehr benötigt wird. in dem das Ergebnis abgespeichert wird. int integer.2 finden Sie ein Beispielprogramm. Der Status des Ergebnisses sollte überprüft werden. /* Benachrichtigungsname */ int be_pid. bevor das Ergebnis verwendet wird.5 Asynchrone Benachrichtigung PostgreSQL bietet asynchrone Benachrichtigungen mit den Befehlen LISTEN und NOTIFY. Nachdem ein von PQnotifies zurückgegebenes PGnotify-Objekt verarbeitet wurde. 347 . wird libpq den Wert automatisch an die richtige Bytereihenfolge anpassen. auf die result_len zeigt. die PGresult-Struktur mit PQclear freizugeben. Keine weiteren Informationen werden vom Sender zum Empfänger übertragen. Wenn result_is_int 0 ist. Wenn eine 4-Byte-Ganzzahl als Ergebnis erwartet wird. werden asynchron informiert. sodass er als für die Clientmaschine passender intWert ankommt. dass die Verwendung der asynchronen Benachrichtigung erläutert. Wenn es keine anstehenden Benachrichtigungen gibt. int isint.libpq: Die C-Bibliothek int len. abgelegt. } u. typedef struct pgNotify { char *relname. ansonsten auf 0. die auf eine bestimmte Benachrichtigung warten. Das Argument fnid ist die OID der auszuführenden Funktion. um Speicherlecks zu vermeiden. PQfn ergibt immer einen gültigen PGresult-Zeiger. libpq-Anwendungen schicken die Befehle LISTEN und UNLISTEN als normale SQL-Befehle. die eigentlich übermittelt werden sollen. Die Funktion PQnotifies gibt die nächste unbearbeitete Benachrichtigung aus der Liste der vom Server empfangenen Benachrichtigungen zurück. Das Eintreffen einer NOTIFY-Nachricht kann danach durch Aufrufen von PQnotifies entdeckt werden. /* PID des Serverprozesses */ } PGnotify. result_buf ist der Puffer. wird sie als bearbeitet erachtet und aus der Liste der Benachrichtigungen entfernt. Sie müssen darin ausreichend Platz für das Ergebnis vorgesehen haben. Eine serverseitige Sitzung meldet ihr Interesse an einer bestimmten Benachrichtigung mit dem Befehl LISTEN an (und kann sich mit UNLISTEN wieder abmelden). Die Daten. PGnotify* PQnotifies(PGconn *conn). (Wenn Sie result_is_int auf 1 setzen.) args und nargs geben die der Funktion zu übergebenden Argumente an. union { int *ptr. Es liegt in der Verantwortung der Anwendung. aber eine zugehörige Tabelle muss es nicht geben. Der Name der Benachrichtigung ist oft der Name der zugehörigen Tabelle. setzen Sie result_is_int auf 1. Wenn eine Benachrichtigung von PQnotifies einmal zurückgegeben wurde. wird die vom Server kommende Bytefolge unverändert zurückgegeben. } PQArgBlock. (Es gibt keine Überprüfung!) Die Länge des tatsächlichen Ergebnisses wird in der Variablen. sollte es mit free() freigegeben werden. dann gibt sie einen Null-Zeiger zurück. Alle Sitzungen. In Beispiel 27. werden daher typischerweise über eine Datenbanktabelle verbreitet.

wenn Sie keine sinnvollen Befehl zum Ausführen haben. was bedeutet. ob eine neue Zeile aus den zwei Zeichen \. 27. ist PQconsumeInput() aufzurufen und dann PQnotifies() zu prüfen. 0. Das funktioniert immer noch. nachdem von PQexec oder PQgetResult ein Ergebnisstatus PGRES_COPY_OUT oder PGRES_COPY_IN erhalten wurde. Beachten Sie. um von dieser Möglichkeit Gebrauch zu machen. die länger als length-1 Zeichen sind. int PQgetline(PGconn *conn. Wenn eine Anwendung Zeilen empfangen könnte. Diese Funktionen sollten nur ausgeführt werden. sondern liefert nur Benachrichtigungen. mit Newline abgeschlossen. weil es Rechnerleistung verschwendet. richtig erkennt (und sie zum Beispiel nicht mit dem Ende einer langen Datenzeile verwechselt).6 Funktionen für den COPY-Befehl Der COPY-Befehl in PostgreSQL hat die Möglichkeit. ist aber nicht mehr empfohlen. um auf Daten vom Server zu warten. dass die Anwendung überprüfen muss. dann muss besondere Sorgfalt angewendet werden. dass sie die Zeile mit \. Daher gibt es Funktionen. PQgetlineAsync 348 .) Das funktioniert. wenn Sie einfach PQexec verwenden. wenn Sie Befehle mit PQsendQuery/PQgetResult verschicken. Eine bessere Möglichkeit. die auf die Netzwerkverbindung direkt zugreifen können. Diese Funktion kopiert bis zu length-1 Zeichen in den Puffer und wandelt die abschließende Newline in ein Null-Byte um. Sie sollten sich aber merken. In früheren Versionen vom libpq war die ein- zige Möglichkeit. dass der Server mit der Übertragung des Ergebnisses des COPY-Befehls fertig ist. PQgetline Liest eine vom Server geschickte Zeile. selbst leere. und auch. aber das Zeilenende noch nicht gelesen wurde. wenn nichts zu tun ist. wenn die ganze Zeile gelesen wurde.4 ist be_pid die PID des Prozesses. die als Beispiel einer korrekten Behandlung des COPYProtokolls dienen können. um Benachrichtigungen zu erhalten. int length). nach jedem PQgetResult oder PQexec PQnotifies() aufzurufen. in den Puffer der Größe length. die vorher von einer anderen libpq-Funktion empfangen wurden. Der Code in der Datei src/bin/psql/copy. PQnotifies() empfängt keine Daten vom Server. Sie können select() verwenden. aus der von libpq erstellten Netzwerkverbindung zu lesen bzw. in sie zu schreiben. char *buffer. und verbrauchen dabei keine Rechenleistung. und 1. andauernd Befehle abzuschicken. den rechtzeitigen Empfang einer Benachrichtung sicherzustellen. aber in früheren Versionen war es die PID des eigenen Serverprozesses. (Den Dateideskriptor für select() erhalten Sie von PQsokket(). wenn der Puffer voll ist. um sicherzustellen. der die Benachrichtigung ausführte. die während der Verarbeitung des Befehls hereinkamen. um nach NOTIFY-Nachrichten Ausschau zu halten. besteht. und nach jedem PQexec()-Aufruf mit PQnotifies() nachzuschauen.c enthält Funktionen. Der Rückgabewert von PQgetline ist EOF am Ende des Eingabestroms.Kapitel 27 Anmerkung Seit PostgreSQL 6.

wenn eine vollständige Datenzeile mit Newline im Zwischenspeicher von libpq vorhanden ist. dass Anwendungen die zwei Zeichen \. const char *buffer. bis das Ende der Daten signalisiert wird. dass sie mit dem Senden von Daten fertig sind. den Sie übergeben. char *buffer. Die Ergebniszeichenkette hat kein Null-Byte am Ende. Das kann erkannt werden. dass der Parameter length. an den Server. den Sie tatsächlich haben. Wenn möglich. und EOF. die die Anzahl der Bytes in den zurückgegebenen Daten angibt. Wenn der angebotene Puffer zu klein ist. in einen Puffer. wird die ganze Zeile auf einmal zurückgegeben. Beachten Sie. sollte die Anwendung PQconsumeInput und PQgetlineAsync aufrufen. in der letzten Zeile senden müssen.libpq: Die C-Bibliothek Liest eine vom Server geschickte Zeile. int PQgetlineAsync(PGconn *conn. wenn ein Fehler auftrat. bis der Rest der Zeile angekommen ist. int nbytes). nicht mit Null-Byte abgeschlossen. um in den angebotenen Puffer zu passen. außer dass der Puffer nicht durch ein Null-Byte abgeschlossen sein muss. int length). Die Funktion ergibt -1. int PQputnbytes(PGconn *conn. an den Server. oder 0. int PQendcopy(PGconn *conn). muss als nächstes PQendcopy aufgerufen werden und dann kann normal fortgefahren werden.wenn ein Fehler auftrat. Nachdem der Befehl COPY ausgeführt und das Ergebnis PGRES_COPY_OUT erhalten wurde. die COPY-Daten asynchron. (Wenn Sie eins anfügen wollen. um die vom Server geschickte Zeile aufzunehmen.) PQputline Sendet eine Zeichenkette. oder wenn die Datenzeile zu lang ist. Ergibt 0. Ergibt 0. Bei jedem Aufruf gibt PQgetlineAsync Daten zurück. wenn keine Daten verfügbar sind oder eine positive Zahl. lesen müssen. ob das letzte Byte im Ergebnis \n ist. int PQputline(PGconn *conn. Wenn das Ergebnis -1 war. const char *string). Diese Funktion ist der Funktion PQgetline ähnlich. um anzuzeigen. wird ein Teil der Zeile zurückgegeben. wenn alles in Ordnung ist. wenn die Markierung am Datenende erkannt wurde. PQputnbytes Sendet eine Zeichenkette. Die zurückgegebenen Daten enden spätestens mit dem Newline-Zeichen. um eins kleiner ist als der Platz. Ansonsten werden keine Daten zurückgegeben. Das ist das Gleiche wie PQputline. 349 . da die Anzahl der zu sendenden Bytes direkt angegeben wird. aber sie kann von Anwendungen verwendet werden. achten Sie darauf. das heißt ohne zu blockieren. mit Newline abgeschlossen. indem man prüft. ohne zu blockieren. wenn alles in Ordnung ist. PQendcopy Synchronisiert den Client mit dem Server. mit Null-Byte abgeschlossen. Im Gegensatz zu PQgetline entdeckt diese Funktion das Ende der Daten selbst. und EOF .

und Warnmeldungen verarbeitet werden. Ältere Anwendungen schicken den COPY-Befehl wahrscheinlich mit PQexec ab und gehen davon aus."). Danach sollte sie zur PQgetResult-Schleife zurückkehren. b varchar(16). indem sie PQgetline wiederholt ausführt. dass die Transaktion nach PQendcopy vorbei ist. nachdem die letzten Daten vom Server mit PGgetline empfangen wurden. "COPY foo FROM STDIN. "3\tHallo. PQputline(conn. 350 . Der Rückgabewert ist 0 bei Erfolg und ansonsten verschieden von null. Sie sollte aufgerufen werden. Welt\t7. . Ähnlich wird ein PGRES_COPY_IN-Ergebnis verarbeitet. bis die Abschlusszeile erkannt wird und danach PQendcopy aufruft. "4\tTschüss. PQputline(conn. PQuntrace Schaltet die durch PQtrace eingeschaltete Nachverfolgung wieder aus. PQputline(conn. Sie muss ausgeführt werden. indem man eine Reihe von PQputline-Aufrufen. wenn COPY der einzige SQL-Befehl in der Befehlszeichenkette ist.11\n"). ansonsten verlieren Client und Server die Synchronisation. "\\. bis der Server den COPY-Vorgang abgeschlossen hat. bis PQgetResult einen Null-Zeiger ergibt. den nächsten SQL-Befehl zu empfangen. 27. Dadurch wird sichergestellt. Ein Beispiel: PQexec(conn.Kapitel 27 Diese Funktion wartet.").8 Verarbeitung von Hinweismeldungen Die Funktion PQsetNoticeProcessor kontrolliert. sollte eine Anwendung auf ein PGRES_COPY_OUT-Ergebnis reagieren. d double precision). 27. der mitten in einer Reihe von SQL-Befehlen steht. void PQuntrace(PGconn *conn).\n"). Wenn PQgetResult verwendet wird. tätigt und dann zur PQgetResult-Schleife zurückkehrt. PQexec(conn.7 Funktionen zur Nachverfolgung PQtrace Schaltet die Nachverfolgung (englisch tracing) des Client/Server-Kommunikationsverkehrs in einen Datenstrom ein.. dass ein COPY-Befehl. "CREATE TABLE foo (a integer. ordnungsgemäß ausgeführt wird. void PQtrace(PGconn *conn FILE *stream). Nach der Ausführung dieses Befehls ist der Server bereit. gefolgt von PQendcopy. nachdem die letzte Zeichenkette mit PQputline an den Server geschickt wurde bzw. Welt\t4.5\n"). PQendcopy(conn). wie vom Server erzeugte Hinweis. Das funktioniert aber nur..

❏ PGPASSWORD setzt das Passwort. wenn kein anderer Wert im Funktionsaufruf angegeben wird. "%s". ❏ PGHOST setzt den vorgegebenen Servernamen. welche von PQconnectdb oder PQsetdbLogin verwendet werden. const char *message). Diese Funktion erhält den Text der Hinweismeldung (welcher ein abschließendes Newline-Zeichen enthält) sowie einen typlosen Zeiger. um Funktionen wie PQgetvalue zur Verfügung zu stehen. const char * message) { fprintf(stderr. verwendet werden. in dem sich die Socketdatei befindet (Vorgabe /tmp).10). ❏ PGPORT setzt die vorgegebene TCP-Portnummer bzw. um Vorgabewerte für Verbindungsparameter zu setzen. Der Rückgabewert ist der Zeiger auf die vorher registrierte Rückruffunktion. message). versuchen libpq-Anwendungen die Authentifizierung mit Servern dieses Realms 351 . dass sie aufgerufen werden kann. ❏ PGDATABASE setzt den vorgegebenen PostgreSQL-Datenbanknamen. } Um eine selbstgeschriebene Funktion zur Verarbeitung von Hinweismeldungen zu verwenden. wird nichts gemacht. aber der Zeiger auf die aktuelle Funktion wird zurückgegeben. dass in einfachen Anwendungen der Datenbankname direkt in den Code geschrieben werden muss. ❏ PGREALM setzt das Kerberos-Realm für PostgreSQL. Wenn er mit einem Schrägstrich anfängt. In der Voreinstellung gibt libpq Hinweismeldungen vom Server sowie einige Fehlermeldungen. wenn nötig. die mit den Meldungen etwas anderes macht. Wenn Sie eine Funktion zur Verarbeitung von Hinweismeldungen eingesetzt haben. Diese Umgebungsvariable wird aus Sicherheitsgründen nicht empfohlen.libpq: Die C-Bibliothek typedef void (*PQnoticeProcessor) (void *arg. rufen Sie PQsetNoticeProcessor gleich nach der Erzeugung eines neuen PGconn-Objekts auf.) Die voreingestellte Rückruffunktion ist einfach static void defaultNoticeProcessor(void * arg. wie der.pgpass (siehe Abschnitt 27. 27. ❏ PGUSER setzt den vorgegebenen Benutzernamen für Datenbankverbindungen. PQnoticeProcessor proc. dann wird eine Unix-Domain-Socket statt TCP/IP verwendet. der Wert ist das Verzeichnis. Wenn der übergebene Zeiger ein Null-Zeiger ist. verwenden Sie stattdessen die Datei $HOME/.9 Umgebungsvariablen Die folgenden Umgebungsvariablen können verwendet werden. Bei der Erzeugung eines PGresult-Objekts wird die aktuelle Rückruffunktion des PGconn-Objekts kopiert. auf stderr aus. Dieses Verhalten kann geändert werden. um zu vermeiden. (Dieser Zeiger kann. indem eine Rückruffunktion eingetragen wird. die es selbst erzeugt. der der gleiche ist. void *arg). PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn. falls der Server Authentifizierung mit Passwörtern fordert. solange das PGconn-Objekt oder daraus erzeugte PGresultObjekte existieren. müssen Sie davon ausgehen. die Erweiterung des Unix-Domain-Socket-Namen für die Kommunikation mit dem PostgreSQL-Server. wenn es nicht das lokale Realm ist. Sie sind zum Beispiel nützlich. um auf anwendungsspezifische Daten zuzugreifen. der PQsetNoticeProcessor übergeben wurde. Wenn PGREALM gesetzt ist.

(Entspricht SET geqo TO . ❏ PGTTY setzt die Datei oder das TTY für Debug-Ausgaben vom Server. (Wenn Sie Befehle gleichzeitig ausführen müssen. ❏ PGOPTIONS setzt zusätzliche Konfigurationsoptionen. Die Datei sollte Zeilen mit folgendem Format haben: hostname:port:datenbank:benutzername:passwort Jedes dieser Felder kann eine Konstante sein oder *..pgpass erreicht werden. (Entspricht SET datestyle TO . was auf alles passt. welche oft nicht Thread-sicher ist.. also stellen Sie spezifischere Einträge an den Anfang.) ❏ PGGEQO setzt den Vorgabemodus des genetischen Anfrageoptimierers. Die Zugriffsrechte für .) PGresult-Objekte werden nach der Erstellung nicht mehr verändert und können daher beliebig zwischen Threads umhergereicht werden. Wenn die Zugriffsrechte weniger strikt sind. wenn die Verbindung ein Passwort erfordert (und anderweitig kein Passwort angegeben wurde). die Passwörter enthält... öffnen sie mehrere Verbindungen.) ❏ PGCLIENTENCODING setzt die vorgegebene Zeichensatzkodierung im Client.. Die nicht mehr empfohlenen Funktionen PQoidStatus und fe_setauthsvc sind nicht Thread-sicher und sollten nicht in Multithread-Programmen verwendet werden. die Methode md5 zu verwenden. wenn der Server Authentifizierung mit Kerberos fordert. Das kann mit dem Befehl chmod 0600 ..pgpass müssen Gruppen. die die Authentifizierungsmethode crypt verwenden. (Entspricht SET client_encoding TO . um Konflikte mit lokalen Ticketdateien zu vermeiden.0 ist libpq Thread-sicher. libpq-Anwendungen.pgpass im jeweiligen Home-Verzeichnis ist eine Datei. Die folgenden Umgebungsvariablen können verwendet werden.10Die Passwortdatei Die Datei .. Diese Umgebungsvariable wird nur verwendet. Einträge mit : oder \ müssen ein vorangestelltes Fluchtzeichen \ haben... es aufzurufen. verlassen sich auf die Betriebssystemfunktion crypt(). um Vorgabewerte für jede PostgreSQLSitzung einzustellen. ❏ PGDATESTYLE setzt den vorgegebenen Ausgabestil für Datums..und Weltzugriff verbieten. wird die Datei ignoriert.) Informationen über die korrekten Werte für diese Umgebungsvariablen finden Sie beim SQL-Befehl SET. Für fe_setauthsvc gibt es überhaupt keinen guten Grund. PQoidStatus kann durch PQoidValue ersetzt werden. 27.. Die erste Übereinstimmung wird verwendet. Insbesondere kann man nicht von zwei Threads gleichzeitig Befehle durch dasselbe Verbindungsobjekt schicken. welche auf allen Plattformen Thread-sicher ist.) ❏ PGTZ setzt die Zeitzone.11Thread-Verhalten Seit PostgreSQL 7. (Entspricht SET timezone TO .und Zeitangaben. 352 . die an den PostgreSQL-Server geschickt werden. die verwendet werden. 27. Es ist besser.Kapitel 27 und verwenden getrennte Ticketdateien.. solange nicht zwei Threads dasselbe PGconn-Objekt zu gleichen Zeit bearbeiten.

o testprog2. Sie können stattdessen das Programm pg_config verwenden. um die libpq-Bibliothek einzubinden. (In einigen Fällen wird der Compiler im fraglichen Verzeichnis automatisch suchen. compilieren und linken). sodass Sie diese Option dann auslassen können.h> Wenn Sie das versäumt haben. indem Sie bei Ihrem Compiler die Option -Iverzeichnis angeben. um dem Compiler das Verzeichnis zu zeigen. müssen Sie sämtliche hier genannte Schritte befolgen: ❏ Binden Sie die Headerdatei libpq-fe. wo die Headerdateien auf dem lokalen System sind: $ pg_config --includedir /usr/local/include Wenn Sie nicht die richtige Compileroption angegeben haben. (Wiederum wird der Compiler einige Verzeichnisse automatisch durchsuchen. erhalten Sie eine Fehlermeldung wie diese: testlibpq.c: In foo. dass Ihr Programm auch von anderen Benutzern compiliert werden könnte. erhalten Sie von Ihrem Compiler normalerweise Fehlermeldungen ähnlich dieser: foo.o -L/usr/local/pgsql/lib -lpq 353 . in dem die libpq-Bibliothek abgelegt ist.c:54: foo. sollten Sie die Verzeichnisnamen nicht auf diese Art festschreiben.h.12libpq-Programme bauen Um Ihre libpq-Programme zu bauen (d. fügen Sie die Option an die Variable CPPFLAGS an: CPPFLAGS += -I/usr/local/pgsql/include Wenn die Möglichkeit besteht.c:8:22: libpq-fe.c:34: foo.c:68: foo.) Für maximale Portierbarkeit stellen Sie die -L-Option vor die Option -lpq.h ein: #include <libpq-fe. geben Sie die Option -lpq an.c:95: function `main': `PGconn' undeclared (first use in this function) `PGresult' undeclared (first use in this function) `CONNECTION_BAD' undeclared (first use in this function) `PGRES_COMMAND_OK' undeclared (first use in this function) `PGRES_TUPLES_OK' undeclared (first use in this function) ❏ Zeigen Sie Ihrem Compiler.c Wenn Sie make-Steuerdateien (makefiles) verwenden. Zum Beispiel: cc -o testprog testprog1. sowie die Option -Lverzeichnis.) Die Befehlszeile zum Compilieren könnte zum Beispiel so aussehen: cc -c -I/usr/local/pgsql/include testprog. in welchem Verzeichnis die PostgreSQL-Headerdateien installiert sind. um herauszufinden.h: No such file or directory ❏ Wenn Sie das fertige Programm linken.c:35: foo.libpq: Die C-Bibliothek 27.

Sie müssen also die entsprechende -I-Option zur Compilerbefehlszeile hinzufügen. } main() { char *pghost.c * * Test the C version of libpq. dass Sie -lpq vergessen haben.h> #include <libpq-fe. Ihren Code zu ändern und sie nicht benutzen.h> void exit_nicely(PGconn *conn) { PQfinish(conn). testlibpq.2 in includedir/postgresql/internal/libpq-int.13Beispielprogramme Beispiel 27.Kapitel 27 Das Bibliotheksverzeichnis können Sie auch mit pg_config herausfinden: $ pg_config --libdir /usr/local/pgsql/lib Fehlermeldungen.o(. */ #include <stdio.o(. Wenn Ihr Code die Headerdatei libpq-int. 354 .1: libpq-Beispielprogramm 1 /* * testlibpq. /usr/bin/ld: cannot find -lpq Dies bedeutet. dass Sie die -L-Option vergessen oder nicht das richtige Verzeichnis angegeben haben.text+0x71): testlibpq.h verwendet und Sie sich weigern.o(.o: In function testlibpq. *pgtty.text+0xa4): `main': undefined reference to `PQsetdbLogin' undefined reference to `PQstatus' undefined reference to `PQerrorMessage' Dies bedeutet. the PostgreSQL frontend * library. *pgport. dann befindet sich diese Datei seit PostgreSQL 7. die auf Probleme in diesem Bereich hinweisen. 27. könnten folgendermaßen aussehen.text+0x60): testlibpq. exit(1).h. *pgoptions.

dbName). "%s". exit_nicely(conn). /* special options to start up the backend * server */ pgtty = NULL. /* debugging tty for the backend server */ dbName = "template1". /* * begin. *res. debug). pgtty. nFields. * using hardwired constants */ pghost = NULL. dbName). then the system will try to use reasonable * defaults by looking up environment variables or. */ PGconn PGresult *conn. pgport. "Connection to database '%s' failed. i. */ /* PQtrace(conn. "BEGIN command failed\n").libpq: Die C-Bibliothek char int int *dbName. /* host name of the backend server */ pgport = NULL. exit_nicely(conn)."w"). PQerrorMessage(conn)). /* make a connection to the database */ conn = PQsetdb(pghost. by setting the parameters for a backend connection if the * parameters are null. fprintf(stderr.out". /* FILE *debug. failing that. if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr. /* * check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr. /* port of the backend server */ pgoptions = NULL. 355 . */ /* start a transaction block */ res = PQexec(conn.\n". pgoptions. PQclear(res). } /* debug = fopen("/tmp/trace. j. "BEGIN").

PQfname(res. } PQclear(res). /* close the cursor */ res = PQexec(conn. "FETCH ALL command didn't return tuples properly\n"). if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr. PQclear(res). printf("\n"). the system catalog of * databases */ res = PQexec(conn. } /* first.Kapitel 27 } /* * should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res). "DECLARE CURSOR command failed\n"). "FETCH ALL in mycursor"). for (i = 0. printf("\n\n"). PQclear(res). j < nFields. /* next. /* * fetch rows from the pg_database. i++) printf("%-15s". j)). i++) { for (j = 0. "DECLARE mycursor CURSOR FOR SELECT * FROM pg_database"). i)). i < nFields. 356 . i < PQntuples(res). if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr. exit_nicely(conn). PQclear(res). j++) printf("%-15s". print out the attribute names */ nFields = PQnfields(res). print out the rows */ for (i = 0. exit_nicely(conn). } PQclear(res). "CLOSE mycursor"). res = PQexec(conn. PQgetvalue(res. i.

c * Test of the asynchronous notification interface * * Start this program. PQclear(res). if you want to get fancy. * */ #include <stdio. "COMMIT").libpq: Die C-Bibliothek /* commit the transaction */ res = PQexec(conn.h" void exit_nicely(PGconn *conn) { PQfinish(conn). */ return 0. try this: * Populate a database with the following: * * CREATE TABLE TBL1 (i int4). * * CREATE RULE r1 AS ON INSERT TO TBL1 DO * (INSERT INTO TBL2 values (new. * * Or.2: libpq-Beispielprogramm 2 /* * testlibpq2.i). } Beispiel 27. then from psql in another window do * NOTIFY TBL2. /* close the connection to the database and cleanup */ PQfinish(conn). * * and do * * INSERT INTO TBL1 values (10). /* fclose(debug). exit(1). } 357 .h> #include "libpq-fe. NOTIFY TBL2). * * CREATE TABLE TBL2 (i int4).

*notify. dbName). failing that. /* host name of the backend server */ pgport = NULL. i. } res = PQexec(conn. "LISTEN command failed\n"). "Connection to database '%s' failed. *conn. exit_nicely(conn). dbName). *res. /* * check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr. by setting the parameters for a backend connection if the * parameters are null. PQerrorMessage(conn)). if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr. pgtty. *pgoptions. /* special options to start up the backend * server */ pgtty = NULL.Kapitel 27 main() { char char int int *pghost. nFields. pgport. 358 . /* change this to the name of your test * database */ /* make a connection to the database */ conn = PQsetdb(pghost. * using hardwired constants */ pghost = NULL. pgoptions.\n". *dbName. /* port of the backend server */ pgoptions = NULL. fprintf(stderr. j. "%s". "LISTEN TBL2"). then the system will try to use reasonable * defaults by looking up environment variables or. PGconn PGresult PGnotify /* * begin. /* debugging tty for the backend server */ dbName = getenv("USER"). *pgtty. *pgport.

3: libpq-Beispielprogramm 3 /* * * * * * * * * testlibpq3. 359 . notify->be_pid). "ASYNC NOTIFY of '%s' from backend pid '%d' received\n".c Test the C version of Libpq. d real. /* check for asynchronous notify messages */ while ((notify = PQnotifies(conn)) != NULL) { fprintf(stderr. exit_nicely(conn). } } /* close the connection to the database and cleanup */ PQfinish(conn). p polygon). } /* * should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res). while (1) { /* * wait a little bit between checks. tests the binary cursor interface populate a database by doing the following: CREATE TABLE test1 (i int4. free(notify).libpq: Die C-Bibliothek PQclear(res). the PostgreSQL frontend library. */ sleep(1). } Beispiel 27. notify->relname. /* collect any asynchronous backend messages */ PQconsumeInput(conn). waiting with select() * would be more efficient. return 0.

1. *pgtty.0.05.0.000000. by setting the parameters for a backend connection if the * parameters are null. * * the expected output is: * * tuple 0: got i = (4 bytes) 1. exit(1). 3. nFields.0. failing that.000000.000000.Kapitel 27 * * INSERT INTO test1 values (1. 360 .h" #include "utils/geo_decls.0.000000) * * */ #include <stdio. i.000000/3. j. *dbName. 2. *pgoptions. *res. 1. 4. p = (4 bytes) 2 points boundbox = * (hi=4. 3.h" /* for the POLYGON type */ void exit_nicely(PGconn *conn) { PQfinish(conn). p_fnum.000000. *conn.2. d_fnum. *pgport. 2.567.000000/4.050003.0)'). i_fnum.567000. } main() { char char int int int PGconn PGresult *pghost. lo = * 1. p = (4 * bytes) 2 points boundbox = (hi=3. * * INSERT INTO test1 values (2. polygon '(4. polygon '(3.0. 89. then the system will try to use reasonable * defaults by looking up environment variables or. d = (4 bytes) 3.000000) tuple 1: got i = (4 bytes) 2. d = (4 bytes) * 89.0)').h> #include "libpq-fe. lo = 2. /* * begin.0. 1.

/* pgoptions = NULL. "BEGIN"). if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { 361 . /* * fetch rows from the pg_database. pgport. "DECLARE mycursor BINARY CURSOR FOR SELECT * FROM test1"). "%s". dbName). pgoptions.libpq: Die C-Bibliothek * using hardwired constants */ pghost = NULL. exit_nicely(conn). /* * check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr. "BEGIN command failed\n"). host name of the backend server */ port of the backend server */ special options to start up the backend server */ debugging tty for the backend server */ /* change this to the name of your test * database */ /* make a connection to the database */ conn = PQsetdb(pghost. /* * pgtty = NULL. /* pgport = NULL. /* dbName = getenv("USER"). the system catalog of * databases */ res = PQexec(conn. dbName). if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr. fprintf(stderr. } /* start a transaction block */ res = PQexec(conn. } /* * should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res). PQerrorMessage(conn)).\n". pgtty. PQclear(res). exit_nicely(conn). "Connection to database '%s' failed.

printf(" i = (%d bytes) %d. p_fnum). PQclear(res). *ival). res = PQexec(conn. i. memmove((char *) &pval->npts. i. int plen. "FETCH ALL command didn't return tuples properly\n"). p_fnum). i. i_fnum). "d"). exit_nicely(conn). float *dval. i. "DECLARE CURSOR command failed\n"). PQfsize(res. i. i). PQgetlength(res. i)). for (i = 0. i < PQntuples(res).Kapitel 27 fprintf(stderr. p_fnum = PQfnumber(res. i_fnum). i < 3. } i_fnum = PQfnumber(res. i. if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr. POLYGON *pval. i). } PQclear(res). dval = (float *) PQgetvalue(res. PQclear(res). } for (i = 0.\n". PQgetvalue(res. /* we hard-wire this to the 3 fields we know about */ ival = (int *) PQgetvalue(res. plen). "p"). PQftype(res. size[%d] = %d\n". pval->size = plen. d_fnum). /* * plen doesn't include the length field so need to * increment by VARHDSZ */ pval = (POLYGON *) malloc(plen + VARHDRSZ). exit_nicely(conn). i++) { int *ival. printf("tuple %d: got\n". "FETCH ALL in mycursor"). i++) { printf("type[%d] = %d. plen = PQgetlength(res. d_fnum = PQfnumber(res. 362 . i. "i").

"CLOSE mycursor"). /* commit the transaction */ res = PQexec(conn.yl).\n". pval->boundbox. pval->boundbox.%f)\n". pval->boundbox. lo = %f. pval->boundbox. PQgetlength(res. /* close the cursor */ res = PQexec(conn.xl. PQclear(res). pval->npts. /* close the connection to the database and cleanup */ PQfinish(conn). "COMMIT"). i. printf(" p = (%d bytes) %d points \tboundbox = (hi=%f/%f. *dval). PQclear(res). } 363 .libpq: Die C-Bibliothek printf(" d = (%d bytes) %f.yh. return 0. PQgetlength(res. } PQclear(res). i.xh. d_fnum). d_fnum).

.

Ein bleibender Vorteil der Large-Object-Schnittstelle ist. Andere Schnittstellen verwenden möglicherweise die Large-Object-Schnittstelle intern. Dadurch wird die Large-Object-Schnittstelle teilweise obsolet. Obgleich der Zugriff darauf langsamer ist.2. bot drei eingebaute Implementierungen von Large Objects: als Dateien außerhalb des POSTGRES-Servers. 365 . Aus historischen Gründen wird dieses Speichersystem als Inversion large object bezeichnet. Wir verwenden die C-Bibliothek libpq für die Beispiele in diesem Kapitel.1 werden alle Large-Object-Daten in einer Systemtabelle namens pg_largeobject abgespeichert. bot PostgreSQL. um allgemeine Unterstützung für große Werte anzubieten.und SQL-Schnittstellen für LargeObject-Daten in PostgreSQL. bietet es striktere Datenintegrität.28 28 Large Objects In PostgreSQL vor Version 7. Um die Speicherung von größeren atomaren Werten zu unterstützen. und bietet immer noch. PostgreSQL 7. Dies wird hier nicht beschrieben. die in einer besonderen Large-Object-Struktur gespeichert sind. (Gelegentlich werden Sie den Begriff Inversion als Synonym für Large Object verwendet sehen. als externe Dateien.1 konnte die Größe eine Zeile in der Datenbank die Größe einer Datenseite nicht überschreiten. Als Ergebnis gibt es in PostgreSQL nur noch Unterstützung für Large Objects als Daten in der Datenbank. war die Obergrenze für die Größe eines Datenwerts ziemlich niedrig.) Seit PostgreSQL 7. Diese Schnittstelle bietet dateiähnlichen Zugriff auf Benutzerdaten. dass Datenzeilen viel größer als einzelne Datenseiten sein können.1 führte einen Mechanismus (mit dem Spitznamen “TOAST”) ein. die vom POSTGRES-Server verwaltet wurden. dass sie Werte bis 2 GB Größe erlaubt. 28. wohingegen TOAST nur 1 GB verarbeiten kann. aber die meisten PostgreSQL-spezifischen Programmierschnittstellen bieten die gleiche Funktionalität. der mittelbare Vorgänger von PostgreSQL. eine Large-Object-Schnittstelle. Das verursachte beträchtliche Verwirrung unter den Benutzern. Dieses Kapitel beschreibt die Implementierung und die Programmier.1 Geschichte POSTGRES 4. Da die Größe einer Datenseite 8192 Bytes ist (der Vorgabewert. der es ermöglicht. und als Daten in der POSTGRES-Datenbank. welcher bis auf 32768 erhöht werden kann).

die als Large Object importiert werden soll. write (schreiben). 366 . Der Rückgabewert ist die dem neuen Large Object zugewiesene OID. Alle Manipulationen von Large Objects mit diesen Funktionen müssen in einem SQL-Transaktionsblock stattfinden. lesen oder beides) wird durch die Bits INV_READ und INV_WRITE.2 Ein Large Object importieren Um eine Datei aus dem Betriebssystem als Large Object zu importieren. mit Analoga von open (öffnen).Kapitel 28 28. read (lesen). zu identifizieren. (Diese Anforderung wird seit PostgreSQL 6. const char *filename). erzeugt eine neues Large Object. wenn beliebige Datenteile gelesen und geschrieben werden. lseek (suchen) usw.3.h einbinden und die libpq-Bibliothek einlinken. Der Parameter mode ist eine Bitmaske.3. um auf Large-Object-Daten zuzugreifen. 28. Ein B-Tree-Index ermöglicht schnellen Zugriff auf das korrekte Stück. 28. Clientanwendungen. um den Speichermanager. die diverse Attribute des neuen Objekts beschreibt. Die niedrigeren 16 Bits der Maske wurden früher in Berkeley verwendet. die von PostgreSQL-Clientbibliotheken angeboten werden. obwohl sie schon in vorherigen Versionen eine unausgesprochene Anforderung war.2 Implementierungsmerkmale Die Large-Object-Implementierung zerlegt Large-Object-Werte in “Stücke” und speichert die Stücke in Zeilen in der Datenbank. die bei Vernachlässigung in Fehlverhalten resultierte. sollten die Headerdatei libpq/libpq-fs. Die hier beschriebenen symbolischen Konstanten sind in der Headerdatei libpq/ libpq-fs. Diese Bits sollten jetzt null sein. filename gibt den Betriebssystemnamen der Datei an. mit “oder” verknüpft. kontrolliert. int mode).h definiert.5 strikt durchgesetzt.) Die Large-Object-Schnittstelle in PostgreSQL wurde der Dateisystemschnittstelle in UNIX nachempfunden.3 Clientschnittstellen Dieser Abschnitt beschreibt die Schnittstellen. rufen Sie Oid lo_import(PGconn *conn. 28. Der Zugriffstyp (schreiben.1 Ein Large Object erzeugen Die Funktion Oid lo_creat(PGconn *conn. auf dem das Large Object abgelegt werden soll. auf. Der Rückgabewert ist die dem neuen Large Object zugewiesene OID. die die Large-Object-Schnittstelle in libpq verwenden. Ein Beispiel: inv_oid = lo_creat(INV_READ|INV_WRITE).

lo_lseek. der später mit lo_read. Das Argument lobjId ist die OID des zu öffnenden Large Object.3 Ein Large Object exportieren Um ein Large Object in eine Betriebssystemdatei zu exportieren.3. Oid lobjId. Oid lobjId. 28. die tatsächlich geschrieben wurden. ob das Objekt zum Lesen (INV_READ). int fd.4 Ein bestehendes Large Object öffnen Um ein bestehendes Large Object zu öffnen. lo_tell und lo_close verwendet werden kann. const char *filename).oder Schreibposition in einem Large Object zu ändern. bevor es erzeugt worden ist. wird zurückgegeben. Die Anzahl der Bytes.3. char *buf. Das Argument lobjId ist die OID des zu exportierenden Large Object und das Argument filename gibt den Betriebssystemnamen der Datei an. wird zurückgegeben.3. die tatsächlich gelesen wurden. lo_open gibt einen Large-Object-Deskriptor zurück. 28. schreibt len Bytes aus buf in das Large Object fd. int fd. Im Falle eines Fehlers ist der Rückgabewert negativ. size_t len). Das Argument fd muss vorher von lo_open erhalten worden sein. 28. rufen Sie int lo_open(PGconn *conn. 367 . int whence). liest len Bytes aus dem Large Object fd in buf. auf . int mode). int fd. auf. Schreiben (INV_WRITE) oder zu beidem geöffnet wird. Im Falle eines Fehlers ist der Rückgabewert negativ.3. Die Anzahl der Bytes. Die Bits in mode kontrollieren. 28. rufen Sie int lo_lseek(PGconn *conn.7 In einem Large Object suchen Um die aktuelle Lese.3.6 Daten aus einem Large Object lesen Die Funktion int lo_read(PGconn *conn.Large Objects 28. Ein Large Object kann nicht geöffnet werden.5 Daten in ein Large Object schreiben Die Funktion int lo_write(PGconn *conn. size_t len). const char *buf. auf. rufen Sie int lo_export(PGconn *conn. int offset. Das Argument fd muss vorher von lo_open erhalten worden sein. lo_write.

raster oid ). wie sie verwendet werden: CREATE TABLE image ( name text. 28. rufen Sie int lo_unlink(PGconn *conn. auf .3. raster) VALUES ('beautiful image'. Oid lobjId). Bei einem Fehler ist der Rückgabewert negativ. Bei einem Fehler ist der Rückgabewert negativ. die von offset angegeben wird. Der Rückgabewert ist die neue aktuelle Position.oder Schreibposition in einem Large Object zu erhalten.Kapitel 28 Diese Funktion bewegt den aktuellen Positionszeiger des von fd identifizierten Large Object an die neue Position.3. geschlossen werden. Die gültigen Werte für whence sind SEEK_SET (vom Objektanfang zählen). welche zur Verwendung in SQL-Befehlen gedacht sind. 28. SEEK_CUR (von der aktuellen Position zählen) und SEEK_END (vom Objektende zählen).3. lo_import('/etc/motd')). INSERT INTO image (name. Im Falle eines Fehlers ist der Rückgabewert negativ. Bei Erfolg gibt lo_close null zurück. wobei fd der von lo_open erhaltene Large-Object-Deskriptor ist.10 Ein Large Object entfernen Um ein Large Object aus der Datenbank zu entfernen. rufen Sie int lo_tell(PGconn *conn. auf.9 Einen Large-Object-Deskriptor schließen Ein Large Object kann mit int lo_close(PGconn *conn. int fd).8 Die aktuelle Schreibposition eines Large Object ermitteln Um die aktuelle Lese. int fd). 28. 28. lo_import und lo_export. 368 .4 Serverseitige Funktionen Für den Zugriff auf Large Objects gibt es zwei eingebaute serverseitige Funktionen. Das Argument lobjId gibt die OID des zu löschenden Large Object an. Hier ist ein Beispiel.

1 ist ein Beispielprogramm. tmp.c in der Quelltext-Distribution gefunden werden. wie die Large-Object-Schnittstelle in libpq verwendet werden kann.Large Objects SELECT lo_export(image. int nbytes.raster. int lobj_fd.c-* test using large objects with libpq * * Copyright (c) 1994. /* * open the file to be read in 369 . das zeigt.h> #include "libpq-fe. char *filename) { Oid lobjId.5 Beispielprogramm Beispiel 28.1: Beispielprogramm für Large Objects mit libpq /*-------------------------------------------------------------* * testlo. int fd. Beispiel 28. Teile des Programms sind auskommentiert. Regents of the University of California * *-------------------------------------------------------------*/ #include <stdio.h" #include "libpq/libpq-fs. char buf[BUFSIZE].h" #define BUFSIZE 1024 /* * importFile * import file "in_filename" into database as large object "lobjOid" * */ Oid importFile(PGconn *conn. Dieses Programm kann auch in src/test/examples/testlo. '/tmp/motd') FROM image WHERE name = 'beautiful image'. 28. aber im Quellcode belassen um dem Leser zu helfen.

0666). } 370 . buf. filename). lobj_fd. lobj_fd = lo_open(conn. char *buf. } /* * create the large object */ lobjId = lo_creat(conn. int nbytes. INV_READ). "can't create large object\n"). BUFSIZE)) > 0) { tmp = lo_write(conn.Kapitel 28 */ fd = open(filename. (void) lo_close(conn. "error while reading large object\n"). int len) { int lobj_fd. lobj_fd). INV_READ | INV_WRITE). Oid lobjId. } void pickout(PGconn *conn. lobjId). nbytes). lobjId. if (lobj_fd < 0) { fprintf(stderr. int nread. INV_WRITE). O_RDONLY. "can't open large object %d\n". buf. if (lobjId == 0) fprintf(stderr. /* * read in from the Unix file and write to the inversion file */ while ((nbytes = read(fd. if (tmp < nbytes) fprintf(stderr. if (fd < 0) { /* error */ fprintf(stderr. int start. "can't open unix file %s\n". return lobjId. lobj_fd = lo_open(conn. } (void) close(fd). lobjId.

for (i = 0. lobj_fd. } lo_lseek(conn. nread += nbytes. nread = 0. fprintf(stderr. int nwritten. int nbytes. lobj_fd.nwritten > 0) { nbytes = lo_write(conn. SEEK_SET). "\n"). buf[i] = ' '. if (lobj_fd < 0) { fprintf(stderr. buf = malloc(len + 1). buf. lo_close(conn. lobj_fd = lo_open(conn. SEEK_SET). nwritten = 0. } free(buf). len . start.nread). while (len . int len) { int lobj_fd. lobj_fd). start. len .nwritten). char *buf. lobj_fd. buf + nwritten.nread > 0) { nbytes = lo_read(conn. INV_READ). buf = malloc(len + 1). lobjId. int start. while (len . } 371 . } void overwrite(PGconn *conn. "can't open large object %d\n". i < len. lobj_fd. i++) buf[i] = 'X'. buf). fprintf(stderr. nwritten += nbytes.Large Objects lo_lseek(conn. int i. lobjId). ">>> %s". Oid lobjId. buf[nbytes] = ' '.

/* * create an inversion "object" */ lobj_fd = lo_open(conn. Oid lobjId. lo_close(conn. O_CREAT | O_WRONLY. int nbytes.Kapitel 28 free(buf). lobjId. 0666). "can't open large object %d\n". lobjId). "\n"). int fd. lobj_fd. } /* * open the file to be written to */ fd = open(filename. if (lobj_fd < 0) { fprintf(stderr. lobj_fd). } /* * read in from the Unix file and write to the inversion file */ while ((nbytes = lo_read(conn. "can't open unix file %s\n". if (tmp < nbytes) { 372 . BUFSIZE)) > 0) { tmp = write(fd. filename). char buf[BUFSIZE]. INV_READ). buf. fprintf(stderr. nbytes). char *filename) { int lobj_fd. if (fd < 0) { /* error */ fprintf(stderr. tmp. buf. } /* * exportFile * export large object "lobjOid" to file "out_filename" * */ void exportFile(PGconn *conn.

Large Objects fprintf(stderr. lobj_fd). char **argv) { char *in_filename. NULL. exit(1). if (argc != 4) { fprintf(stderr. out_filename = argv[3]. "Usage: %s database_name in_filename out_filename\n". PGresult *res. database). NULL. /* * set up the connection */ conn = PQsetdb(NULL. "error while writing %s\n". /* check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) 373 . filename). } void exit_nicely(PGconn *conn) { PQfinish(conn). (void) close(fd). *out_filename. argv[0]). char *database. } } (void) lo_close(conn. Oid lobjOid. exit(1). return. } int main(int argc. NULL. PGconn *conn. in_filename = argv[2]. } database = argv[1].

lobjOid. pickout(conn. PQclear(res). PQfinish(conn). lobjOid = importFile(conn. "end"). 1000. lobjOid. in_filename). */ lobjOid = lo_import(conn. out_filename).\n". lobjOid. 1000). */ lo_export(conn. printf("importing file %s\n". printf("picking out bytes 1000-2000 of the large object\n"). "Connection to database '%s' failed. exit(0). PQerrorMessage(conn)). in_filename). lobjOid). /* /* /* } 374 . printf("as large object %d. overwrite(conn.\n". lobjOid. exportFile(conn. "%s". PQclear(res). printf("overwriting bytes 1000-2000 of the large object with X's\n"). */ printf("exporting large object to file %s\n". database). in_filename). out_filename). 1000.Kapitel 28 { fprintf(stderr. fprintf(stderr. exit_nicely(conn). } res = PQexec(conn. "begin"). 1000). out_filename). res = PQexec(conn.

29 29 pgtcl: Die TclBindungsbibliothek pgtcl ist ein Tcl-Paket. Es stellt die meisten Funktionen von libpq für Tcl-Skripts zur Verfügung. 29.1 Überblick Tabelle 29. Diese Befehle sind im Einzelnen auf den folgenden Seiten beschrieben. Befehl pg_connect pg_disconnect pg_conndefaults pg_exec pg_result pg_select pg_execute pg_listen pg_on_connection_loss pg_lo_creat pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_lseek Beschreibung eine Verbindung zum Server öffnen eine Verbindung zum Server schließen Verbindungsparameter und ihre Vorgabewerte ermitteln einen Befehl an den Server senden Informationen über ein Befehlsergebnis ermitteln eine Schleife über ein Anfrageergebnis ausführen eine Anfrage senden und wahlweise eine Schleife über das Ergebnis ausführen einen Befehl für asynchrone Benachrichtigungsmitteilungen einsetzen oder ändern einen Befehl für unerwarteten Verbindungsverlust einsetzen oder ändern ein Large Object erzeugen ein Large Object öffnen ein Large Object schließen aus einem Large Object lesen in ein Large Object schreiben den Positionszeiger eines Large Object setzen Tabelle 29. mit dem Clientprogramme mit dem PostgreSQL-Server kommunizieren können.1 gibt einen Überblick über die in pgtcl verfügbaren Befehle.1: pgtcl-Befehle 375 .

info sharedlibextension zu verwenden. aber in einigen Konfigurationen könnte dies eine Hürde sein. 29. müssen Sie libpgtcl in Ihre Tcl-Anwendung laden.) Die pg_lo_*-Befehle sind Schnittstellen zur Large-Object-Funktionalität PostgreSQL. die Umgebungsvariable LD_LIBRARY_PATH setzen oder eine ähnliche Methode auf Ihrer Plattform finden. Sehen Sie sich die PostgreSQL-Installationsanweisungen an. Schauen Sie sich den Quellcode von pgtclsh als Beispiel an.so oder . In der Praxis ist das selten ein Problem. anstatt . 29. wo es nach der dynamischen Bibliothek libpgtcl suchen soll. wenn das dynamische Ladeprogramm des System nicht weiß.2 pgtcl in eine Anwendung laden Bevor Sie pgtcl-Befehle verwenden können. Diese Funktionen wurden den analogen Funktionen in der Unix-Dateisystemschnittstelle nachempfunden. da beide diese Bibliotheken normalerweise im selben Verzeichnis abgelegt sind.1: pgtcl-Befehle (Forts. Die pg_lo_*Befehle sollten innerhalb eines BEGIN /COMMIT-Transaktionsblocks verwendet werden.eine Verbindung zum Server öffnen 376 .Kapitel 29 Befehl pg_lo_tell pg_lo_unlink pg_lo_import pg_lo_export Beschreibung den aktuellen Positionszeiger eines Large Object zurückgeben ein Large Object löschen ein Large Object aus einer Datei importieren ein Large Object in eine Datei exportieren Tabelle 29. Die Befehle pg_lo_import und pg_lo_export müssen in einem BEGIN /COMMIT-Transaktionsblock verwendet werden. libpgtcl hängt wiederum von libpq ab.3 pgtcl-Befehlsreferenz pg_connect Name pg_connect -.sl direkt in die Anwendung zu schreiben. um weitere Informationen zu erhalten. Das wird normalerweise mit dem Tcl-Befehl load gemacht. Wenn Sie eine eigene Programmdatei für Ihre Anwendung bauen. Sie müssen womöglich mit ldconfig arbeiten. Hier ist ein Beispiel: load libpgtcl[info sharedlibextension] Es wird empfohlen. Der Befehl load wird fehlschlagen. könnten Sie libpgtcl auch statisch in die Programmdatei einbinden und so den load-Befehl und die ganzen möglichen Probleme beim dynamischen Linken vermeiden. also muss das Ladeprogramm auch die dynamische Bibliothek libpq finden können. weil die von pg_lo_open zurückgegebenen Deskriptoren nur in der aktuellen Transaktion gültig sind.

mit dem verbunden werden soll. Alter Stil dbName Der Name der Datenbank. Zwei Syntaxen stehen zur Verfügung. um Informationen über die in der neueren Syntax verfügbaren Optionen zu erhalten. jeder in der Form schlüssel = wert geschrieben. mit der verbunden werden soll. Handles haben den Präfix pgsql. an den Server zu übergebende Konfigurationsoptionen. Argumente Neuer Stil verbindungsparameter Eine Zeichenkette mit Verbindungsparametern. -options serveroptionen Zusätzliche. -host hostname Der Hostname des Datenbankservers. pg_conndefaults kann verwendet werden. -port portnummer Die TCP-Portnummer des Datenbankservers. mit dem verbunden werden soll. wird eine Handle für die Datenbankverbindung zurückgegeben.pgtcl: Die Tcl. Eine Liste der gültigen Parameter kann in der Beschreibung der libpq-Funktion PQconnectdb gefunden werden.Bindungsbibliothek Synopsis pg_connect -conninfo verbindungsparameter pg_connect dbName ?-host hostname? ?-port portnummer? ?-tty tty? ?-options serveroptionen? Beschreibung pg_connect öffnet eine Verbindung zum PostgreSQL-Server. Rückgabewert Wenn erfolgreich. In der älteren hat jeder mögliche Parameter einen getrennten Optionsschalter im pg_connect-Befehl. die mehrere Parameterwerte enthalten kann. -tty tty Eine Datei oder ein TTY für zusätzliche Debugausgaben vom Server. In der neueren Form wird eine einzige Zeichenkette angegeben. 377 .

Rückgabewert Keiner pg_conndefaults Name pg_conndefaults -.Kapitel 29 pg_disconnect Name pg_disconnect -.Verbindungsparameter und ihre Vorgabewerte ermitteln Synopsis pg_conndefaults Beschreibung pg_conndefaults gibt Informationen über die für pg_connect -conninfo zur Verfügung stehenden Verbindungsparameter und deren aktuelle Vorgabewerte zurück. Argumente verbindung Die Handle der zu schließenden Verbindung. Argumente Keine 378 .eine Verbindung zum Server schließen Synopsis pg_disconnect verbindung Beschreibung pg_disconnect schließt eine Verbindung zum PostgreSQL-Server.

Bindungsbibliothek Rückgabewert Das Ergebnis ist eine Liste. Diese Handle kann an pg_result übergeben werden. dass das Wegbleiben eines Tcl-Fehlers nicht anzeigt. 379 . Rückgabewert Eine Ergebnishandle. pg_exec Name pg_exec -. Ein Tcl-Fehler wird erzeugt.einen Befehl an den Server senden Synopsis pg_exec verbindung befehlstext Beschreibung pg_exec schickt einen Befehl an den PostgreSQL-Server und gibt ein Ergebnis zurück. Ansonsten wird ein Ergebnisobjekt erzeugt und eine Handle dafür zurückgegeben. Die Handles für Befehlsergebnisse bestehen aus der Verbindungshandle gefolgt von einem Punkt und der Ergebnisnummer. aber keinen Tcl-Fehler in pg_exec. um die Ergebnisse des Befehls zu ermitteln. auf der der Befehl ausgeführt werden soll. Jeder Eintrag ist wiederum eine Liste im folgenden Format: {name beschriftung ausgzeichen ausggröße wert} wobei name als Parameter in pg_connect -conninfo verwendet werden kann. befehlstext Der auszuführende SQL-Befehl. dass der SQL-Befehl erfolgreich war. Eine vom Server zurückgegebene Fehlermeldung ergibt ein Ergebnisobjekt mit einem Fehlerstatus. Beachten Sie. wenn pgtcl keine Antwort vom Server erhalten konnte. Argumente verbindung Die Handle der Verbindung.pgtcl: Die Tcl. die die möglichen Verbindungsparameter und deren aktuelle Vorgabewerte beschreibt.

dann die OID der eingefügten Zeile.Informationen über ein Befehlsergebnis ermitteln Synopsis pg_result ergebnishandle ergebnisoption Beschreibung pg_result gibt Informationen aus einem Befehlsergebnisobjekt zurück. -numAttrs Die Anzahl der Spalten (Attribute) in jeder Zeile. -numTuples Die Anzahl der von der Anfrage zurückgegebenen Zeilen (Tupel). sollten Sie es mit pg_result -clear freigeben. welcher Teil der Ergebnisinformationen zurückgegeben werden soll: -status Der Status des Ergebnisses. Ansonsten haben Sie ein Speicherleck und pgtcl wird sich irgendwann beschweren. -assign arrayname 380 . -conn Die Verbindung. -oid Wenn der Befehl ein INSERT war. ansonsten eine leere Zeichenkette. solange Sie wollen. dass Sie zu viele Ergebnisobjekte erzeugt haben. -error Die Fehlermeldung. auf der dieses Ergebnis erzeugt wurde. wenn der Status einen Fehler anzeigt. welches vorher durch pg_exec erzeugt wurde. die angibt. Sie können das Befehlsergebnis behalten.Kapitel 29 pg_result Name pg_result -. aber wenn Sie damit fertig sind. ergebnisoption Eine der folgenden Optionen. Argumente ergebnishandle Die Handle des Befehlsergebnisses. ansonsten 0.

Wenn anhang angegeben wird. Für jede Zeile wird arrayvar mit den Spaltenwerten gefüllt. Kurz gesagt. Der befehlstext muss ein SELECT-Befehl sein. Zeilennummern beginnen bei null. spaltennummer). -getTuple zeilennummer Gibt die Spalten der angegebenen Zeile als Liste zurück. der in der Schleife verwendet wird.pgtcl: Die Tcl. -lAttributes Gibt eine Liste von Listen der Form {name typoid typgröße} für jede Spalte zurück. mit den Spaltennamen als Arrayindizes. mit den Werten der ersten Spalte und den Namen der übrigen Spalten als Indizes. mit Indizes der Form (zeilennummer. Zeilennummern beginnen bei null. -assignbyidx arrayname [anhang] Legt die Ergebnisse in einem Array ab. indiziert nach Spaltennamen. alles andere ist ein Fehler. spaltennameAnhang).Bindungsbibliothek Legt die Ergebnisse in einem Array ab. Die Variable arrayvar ist ein Arrayname. Dann wird die prozedur ausgeführt. -attributes Gibt eine Liste der Namen der Spalten im Ergebnis zurück. wie oben beschrieben. werden alle Spalten außer der ersten in jeder Zeile im Array gespeichert. 381 . -clear Gibt das Ergebnisobjekt wieder frei. -tupleArray zeilennummer arrayname Speichert die Spalten der Zeile im Array arrayName. pg_select Name pg_select – eine Schleife über ein Anfrageergebnis ausführen Synopsis pg_select verbindung befehlstext arrayvar prozedur Beschreibung lpg_select schickt eine Anfrage (SELECT-Befehl) an den PostgreSQL-Server und führt für jede Zeile im Ergebnis ein angegebenes Stück Code aus. dann wird es an jeden Indexwert angehängt. mit Indizes der Form (ersterSpaltenwert. Rückgabewert Das Ergebnis hängt von der gewählten Option ab.

Argumente verbindung Die Handle der Verbindung. prozedur Eine Prozedur. beginnend bei null und bei jedem Schleifendurchlauf um eins erhöht.eine Anfrage senden und wahlweise eine Schleife über das Ergebnis ausführen 382 . . auf der die Anfrage ausgeführt werden soll.headers Eine Liste der von der Anfrage zurückgegebenen Spaltennamen. befehlstext Die auszuführende SQL-Anfrage.tupno Die aktuelle Zeilennummer. arrayvar Eine Arrayvariable für die Ergebniszeilen. dass die Tabelle tabelle1 Spalten namens nummer und name (und möglicherweise weitere) hat: pg_select $pgconn "SELECT * FROM tabelle1.Kapitel 29 Zusätzlich zu den Spaltenwerten werden die folgenden besonderen Einträge in das Array eingefügt: . . die für jede Ergebniszeile ausgeführt wird. Rückgabewert Keiner Beispiele Dieses Beispiel geht davon aus." array { puts [format "%5d %s" $array(nummer) $array(name)] } pg_execute Name pg_execute -.numcols Die Anzahl der von der Anfrage zurückgegebenen Spalten.

Das erste Element ist ein Fehlercode. mit den Spaltennamen als Arrayindizes. wenn angegeben. dann wird die OID der eingefügten Zeile in der Variable oidvar gespeichert. wird die Anzahl der von dem Befehl betroffenen Zeilen zurückgegeben. Für Fehler vom Server wird pg_execute einen Tcl-Fehler erzeugen und eine Liste mit zwei Elementen zurückgeben. die für jede Ergebniszeile eines SELECT-Befehls ausgeführt wird. (prozedur wegzulassen ist wahrscheinlich nur sinnvoll. und das zweite Element ist der Fehlertext vom Server. wie zum Beispiel PGRES_FATAL_ERROR. wird zurückgegeben. wenn prozedur return ausführt. Wenn befehlstext kein SELECT ist. Wenn der Befehl kein SELECT ist.Bindungsbibliothek Synopsis pg_execute ?-array arrayvar? ?-oid oidvar? verbindung befehlstext ?prozedur? Beschreibung pg_execute schickt einen Befehl an den PostgreSQL-Server. wenn die Anfrage nur eine einzige Zeile ergibt. Bei ernsthafteren Fehlern. 383 . pg_execute ist eine neuere Funktion. die mehr Fähigkeiten als pg_select bietet und in vielen Fällen pg_exec ersetzen kann. wird pg_execute einen Tcl-Fehler erzeugen und nur den Fehlertext zurückgeben. werden. dass. wie zum Beispiel einen Fehler bei der Kommunikation mit dem Server. Beachten Sie. die prozedur ausgeführt. und dann wird. continue und return mit dem zu erwartenden Verhalten verwenden. pg_execute nicht die Anzahl der betroffenen Zeilen zurückgibt. -oid oidvar Gibt den Namen einer Variable an. indiziert nach Spaltennamen. die die Anfrage liefert. auf der der Befehl ausgeführt werden soll. wenn angegeben. Wenn der Befehl ein INSERT ist und eine einzige Zeile eingefügt wird. befehlstext Der auszuführende SQL-Befehl. Die prozedur kann die Tcl-Befehle break. Argumente -array arrayvar Gibt den Namen einer Arrayvariablen an.pgtcl: Die Tcl. Wenn der Befehl ein SELECT ist. wenn die wahlfreie Option -oid angegeben wurde. prozedur Eine Prozedur. wo die Ergebniszeilen abgelegt werden. wenn kein Zugriff auf die Ergebnishandle benötigt wird. die von dem Befehl betroffen oder zurückgegeben wurden. Rückgabewert Die Anzahl der Zeilen.) Die Anzahl der Zeilen. in die die OID aus einem INSERT-Befehl gespeichert werden wird. dann wird diese Option ignoriert. die Zeilenwerte in der Variable arrayvar gespeichert. verbindung Die Handle der Verbindung. für jede Zeile im Ergebnis. ansonsten in nach den Spalten benannten Variablen.

Der eingesetzte Befehl wird in der Idle-Schleife von Tcl ausgeführt. um die Klarheit zu bewahren. wert FROM meinetabelle. In anderen Tcl-Shells können Sie update oder vwait aufrufen.einen Befehl für asynchrone Benachrichtigungsmitteilungen einsetzen oder ändern Synopsis pg_listen verbindung notifyName ?befehl? Beschreibung pg_listen setzt einen Befehl ein. Das geschieht. wird der angegebene Befehlstext immer ausgeführt. Nachdem ein Befehl mit pg_listen registriert worden ist. 384 . Bei einer mit Tk geschriebenen Anwendung wird diese Schleife im Leerlauf automatisch aufgerufen." pg_listen Name pg_listen -." Finde die Maximal. min(value) AS min FROM meinetabelle. Mit dem Parameter befehl wird ein Befehl eingesetzt oder der Text eines bestehenden Befehls ersetzt. wenn eine Benachrichtigungsmitteilung mit dem angegebenen Namen vom Server eintrifft.und Minimalwerte und speichere sie in $max und $min: pg_execute $pgconn "SELECT max(value) AS max. der bei Ankunft einer asynchronen Benachrichtigungsmitteilung vom PostgreSQL-Server aufgerufen werden soll." Gebe die Spalten nummer und wert aus jeder Zeile aus: pg_execute -array d $pgconn "SELECT nummer. Füge eine Zeile ein und speichere die OID in result_oid: pg_execute -oid result_oid $pgconn "INSERT INTO meinetabelle VALUES (1)." { puts "Nummer=$d(nummer) Wert=$d(wert)" } Finde die Maximal. min(value) AS min FROM meinetabelle. um in die Idle-Schleife einzutreten.und Minimalwerte und speichere sie in $s(max) und $s(min): pg_execute -array s $pgconn "SELECT max(value) AS max. wenn eine beliebige PostgreSQL-Clientanwendung den Befehl NOTIFY mit Verweis auf den entsprechenden Namen ausführt.Kapitel 29 Beispiele In den folgenden Beispielen wurde die Fehlerprüfung mit catch weggelassen. Ohne den Parameter befehl wird ein schon registrierter Befehl widerrufen.

auf die geachtet werden soll. wenn ein unerwarteter Verlust der Verbindung geschieht. der Befehlstext.einen Befehl für unerwarteten Verbindungsverlust einsetzen oder ändern Synopsis pg_on_connection_loss verbindung ?befehl? Beschreibung pg_on_connection_loss setzt einen Befehl ein. der aufgerufen werden soll. sollten Sie die SQL-Befehle LISTEN und UNLISTEN nicht direkt aufrufen. Ohne den Parameter befehl wird ein schon registrierter Befehl widerrufen. wenn eine passende Benachrichtigung eintrifft. notifyName Der Name der Benachrichtigung . Mit dem Parameter befehl wird ein Befehl eingesetzt oder der Text eines bestehenden Befehls wird ersetzt. Rückgabewert Keiner pg_on_connection_loss Name pg_on_connection_loss -.pgtcl: Die Tcl. Aber wenn Sie selbst eine Benachrichtigungsmitteilung senden wollen. der ausgeführt werden soll. um in die Idle-Schleife einzutreten. bei der auf Benachrichtigungen geachtet werden soll. dann führen Sie den SQL-Befehl NOTIFY mit pg_exec aus. pgtclübernimmt das für Sie. 385 . Der eingesetzte Befehl wird in der Idle-Schleife von Tcl ausgeführt. Argumente verbindung Die Handle. In anderen Tcl-Shells können Sie update oder vwait aufrufen. bei der auf Verbindungsverlust geachtet werden soll. befehl Wenn angegeben. Bei einer mit Tk geschriebenen Anwendung wird diese Schleife im Leerlauf automatisch aufgerufen.Bindungsbibliothek Wenn Sie pg_listen verwenden. Argumente verbindung Die Handle.

Zum Beispiel: [pg_lo_creat $conn "INV_READ|INV_WRITE"] Rückgabewert Die OID des erzeugten Large Object.ein Large Object öffnen 386 . in der das Large Object erzeugt werden soll. der Befehlstext.Kapitel 29 befehl Wenn angegeben. Rückgabewert Keiner pg_lo_creat Name pg_lo_creat -. wenn ein Verbindungsverlust entdeckt wird. modus Der Zugriffsmodus für das Large Object. Er kann INV_READ (lesen) oder INV_WRITE (schreiben) oder beides mit “oder” verknüpfen.ein Large Object erzeugen Synopsis pg_lo_creat verbindung modus Beschreibung pg_lo_creat erzeugt ein Large Object. Der Verknüpfungsoperator ist |. der ausgeführt werden soll. pg_lo_open Name pg_lo_open -. Argumente verbindung Die Handle einer Datenbankverbindung.

pg_lo_close Name pg_lo_close -. loid Die OID des Large Object. Argumente verbindung Die Handle einer Datenbankverbindung. in der das zu öffnende Large Object liegt. w (schreiben) oder rw (beides). Rückgabewert Ein Deskriptor zur späteren Verwendung in Large-Object-Befehlen. in der das Large Object liegt. Der Modus kann sein: r (lesen). 387 .pgtcl: Die Tcl. Argumente verbindung Die Handle einer Datenbankverbindung.Bindungsbibliothek Synopsis pg_lo_open verbindung loid modus Beschreibung pg_lo_open öffnet ein Large Object. modus Gibt den Zugriffsmodus für das Large Object an.ein Large Object schließen Synopsis pg_lo_close verbindung deskriptor Beschreibung pg_lo_close schließt ein Large Object.

Rückgabewert Keiner 388 . in der das Large Object liegt.Kapitel 29 deskriptor Ein Deskriptor für das Large Object von pg_lo_open. länge Die Höchstzahl der zu lesenden Bytes. Argumente verbindung Die Handle einer Datenbankverbindung. deskriptor Ein Deskriptor für das Large Object von pg_lo_open. Rückgabewert Keiner pg_lo_read Name pg_lo_read – aus einem Large Object lesen Synopsis pg_lo_read verbindung deskriptor bufVar länge Beschreibung pg_lo_read liest höchstens länge Bytes aus einem Large Object in eine Variable namens bufVar. bufVar Der Name einer Puffervariablen. die das Large-Object-Segment enthalten soll.

deskriptor Ein Deskriptor für das Large Object von pg_lo_open.pgtcl: Die Tcl. buf Eine Zeichenkette (kein Variablenname). Argumente verbindung Die Handle einer Datenbankverbindung.Bindungsbibliothek pg_lo_write Name pg_lo_write -. in der das Large Object liegt. Rückgabewert Keiner pg_lo_lseek Name pg_lo_lseek – den Positionszeiger eines Large Object setzen Synopsis pg_lo_lseek verbindung deskriptor offset whence 389 . die die zu schreibenden Daten enthält. länge Die Höchstzahl der zu schreibenden Bytes.in ein Large Object schreiben Synopsis pg_lo_write verbindung deskriptor buf länge Beschreibung _pg_lo_write schreibt höchstens länge Bytes aus der Variablen buf in ein Large Object.

und Schreibposition in Bytes vom Anfang des Large Objects zurück. in der das Large Object liegt. offset Die neue Position in Bytes. whence Gibt an. Argumente verbindung Die Handle einer Datenbankverbindung. 390 . SEEK_END (vom Ende) oder SEEK_SET (vom Start).und Schreibposition offset Bytes von der durch whence ange- gebenen Position. Rückgabewert Keiner pg_lo_tell Name pg_lo_tell -. deskriptor Ein Deskriptor für das Large Object von pg_lo_open.den aktuellen Positionszeiger eines Large Object zurückgeben Synopsis pg_lo_tell verbindung deskriptor Beschreibung pg_lo_tell gibt die aktuelle Lese. Argumente verbindung Die Handle einer Datenbankverbindung. von wo die neue Position berechnet werden soll: SEEK_CUR (von der aktuellen Position). in der das Large Object liegt. deskriptor Ein Deskriptor für das Large Object von pg_lo_open.Kapitel 29 Beschreibung pg_lo_lseek bewegt die aktuelle Lese.

Rückgabewert Keiner pg_lo_import Name pg_lo_import -. geeignet zur Übergabe an pg_lo_lseek.pgtcl: Die Tcl.Bindungsbibliothek Rückgabewert Der aktuelle Positionszeiger in Bytes. Argumente verbindung Die Handle einer Datenbankverbindung. loid Die OID des Large Object.ein Large Object löschen Synopsis pg_lo_unlink verbindung loid Beschreibung pg_lo_unlink löscht das angegebene Large Object.ein Large Object aus einer Datei importieren Synopsis pg_lo_import verbindung dateiname 391 . in der das Large Object liegt. pg_lo_unlink Name pg_lo_unlink -.

ein Large Object in eine Datei exportieren Synopsis pg_lo_export verbindung loid dateiname Beschreibung pg_lo_export schreibt das angegebene Large Object in eine Datei. loid Die OID des Large Object. Hinweise pg_lo_import muss in einem BEGIN /COMMIT-Transaktionsblock aufgerufen werden. Argumente verbindung Die Handle einer Datenbankverbindung. in der das Large Object liegt. in der das Large Object erzeugt werden soll. dateiname 392 . Rückgabewert Die OID des erzeugten Large Objects. dateiname Gibt an. aus welcher Datei die Daten importiert werden sollen. pg_lo_export Name pg_lo_export -. Argumente verbindung Die Handle einer Datenbankverbindung.Kapitel 29 Beschreibung pg_lo_import liest die angegebene Datei und legt den Inhalt in einem neuen Large Object ab.

1 zeigt ein kleines Beispiel.Bindungsbibliothek Gibt an.1: pgtcl-Beispielprogramm # getDBs : # get the names of all the databases at a given host and port number # with the defaults being the localhost and port 5432 # return them in alphabetical order proc getDBs { {host "localhost"} {port "5432"} } { # datnames is the list to be result set conn [pg_connect template1 -host $host -port $port] set res [pg_exec $conn "SELECT datname FROM pg_database ORDER BY datname."] set ntups [pg_result $res -numTuples] for {set i 0} {$i < $ntups} {incr i} { lappend datnames [pg_result $res -getTuple $i] } pg_result $res -clear pg_disconnect $conn return $datnames } 393 .4 Beispielprogramm Beispiel 29. in welche Datei die Daten exportiert werden sollen.pgtcl: Die Tcl. wie die pgtcl-Befehle verwendet werden. 29. Rückgabewert Keiner Hinweise pg_lo_export muss in einem BEGIN /COMMIT-Transaktionsblock aufgerufen werden. Beispiel 29.

.

und nachher kann er mit den C-Compilerwerkzeugen verarbeitet werden. Die Befehle nehmen syntaktisch den Platz einer C-Anweisung ein.. können weitere Informationen in vielen Quellen über SQL gefunden werden. Dieser besondere Code hat die Form EXEC SQL . Eingebettete SQL-Befehle folgen den Regeln zur Groß. 30. wird der Quellcode zuerst dem Präprozessor für eingebettetes SQL übergeben. und es ist normalerweise möglich. in diesem Fall C. die für normalen SQL-Code gelten. sind Programme.. die für die eingebettete SQL-Schnittstelle geschrieben sind. Eingebettetes SQL hat Vorteile gegenüber anderen Methoden zum Umgang mit SQL-Befehlen in C-Programmen. vermischt mit SQL-Befehlen in besonders markierten Abschnitten.und Kleinschreibung. 395 . Wie angedeutet. Es funktioniert mit C und C++. Zweitens ist in C eingebettetes SQL im SQL-Standard definiert und wird von vielen anderen SQL-Datenbanken unterstützt. Aber da diese Schnittstelle standardisiert ist. Erstens wird das lästige Umherreichen von Informationen an und von Variablen aus dem CProgramm übernommen. Es ist beabsichtigt.. Diese Dokumentation ist zugegebenermaßen ziemlich unvollständig.1 Das Konzept Ein Eingebettetes-SQL-Programm besteht aus Code in einer gewöhnlichen Programmiersprache. normale CProgramme mit besonderem Code. Je nach dem Befehl im Einzelnen können sie im globalen Kontext oder innerhalb einer Funktion auftreten. für andere Datenbanken geschriebene eingebettete SQL-Programme relativ einfach auf PostgreSQL zu portieren. dass die Implementierung in PostgreSQL diesem Standard soweit wie möglich entspricht. welcher ihn in ein gewöhnliches C-Programm umwandelt.30 10 3 ECPG: Eingebettetes SQL in C Dieses Kapitel beschreibt das PostgreSQL-Paket für eingebettetes SQL. und nicht denen von C. Um das Programm zu bauen. Die folgenden Abschnitte beschreiben alle eingebetteten SQL-Befehle. der Datenbankaktionen durchführt.

Unten sind einige Beispiele dafür.3 Eine Verbindung schließen Um eine Verbindung zu schließen. 30.4 SQL-Befehle ausführen Jeder beliebige SQL-Befehl kann aus einer eingebetteten SQL-Anwendung ausgeführt werden. Der verbindungsname wird verwendet. Die verbindung kann auf folgende Arten angegeben werden: ❏ ❏ ❏ ❏ verbindungsname DEFAULT CURRENT ALL 30. Zeichenkettenvariablen oder Zeichenkonstanten sein. den Benutzernamen anzugeben: benutzername benutzername/passwort benutzername IDENTIFIED BY passwort benutzername USING passwort Der benutzername und das passwort können SQL-Namen. Wenn ein Programm nur eine Verbindung verwendet. dann kann er ausgelassen werden. Das ziel kann auf folgende Arten angegeben werden: ❏ ❏ ❏ ❏ ❏ ❏ ❏ ❏ ❏ ❏ dbname[@hostname][:port] tcp:postgresql://hostname[:port][/dbname][?optionen] unix:postgresql://hostname[:port][/dbname][?optionen] zeichenvariable zeichenkette DEFAULT Es gibt auch verschiedene Arten. 396 . um mehrere Verbindungen in einem Programm zu verwalten.2 Zum Datenbankserver verbinden Man verbindet zu einer Datenbank mit dem folgenden Befehl: EXEC SQL CONNECT TO ziel [AS verbindungsname] [USER benutzername]. verwenden Sie den folgenden Befehl: EXEC SQL DISCONNECT [verbindung]. ascii char(16)).Kapitel 30 30. Eine Tabelle erzeugen: EXEC SQL CREATE TABLE foo (number integer. EXEC SQL CREATE UNIQUE INDEX num1 ON foo(number).

müssen die C-Variablen. ascii FROM foo ORDER BY ascii. Zeilen einfügen: EXEC SQL INSERT INTO foo (number.. ascii) VALUES (9999. EXEC SQL FETCH foo_bar INTO :FooBar. oder um Daten aus der Datenbank zurück an das Programm zu übergeben.ECPG: Eingebettetes SQL in C EXEC SQL COMMIT. EXEC SQL COMMIT. außer wenn ein expliziter Transaktionsblock verwendet wird. Aktualisieren: EXEC SQL UPDATE foo SET ascii = 'foobar' WHERE number = 9999.5 Daten übergeben Um Daten aus dem Programm an die Datenbank zu übergeben. EXEC SQL COMMIT. Tokens der Form :irgendwas sind Hostvariablen. Im Autocommit-Modus wird die automatische Transaktion um jeden Befehl automatisch abgeschlossen. . auch bekannt von anderen Schnittstellen. EXEC SQL COMMIT. EXEC SQL CLOSE foo_bar. zum Beispiel als Parameter in einer Anfrage. 'doodad'). EXEC SQL COMMIT. Zeilen löschen: EXEC SQL DELETE FROM foo WHERE number = 9999. Sie werden im nächsten Abschnitt erklärt. in speziell markierten Abschnitten deklariert werden. Die eingebettete SQL-Schnittstelle unterstützt auch das automatische Abschließen von Transaktionen (Autocommit). die diese Daten enthalten sollen. DooDad. wenn EXEC SQL COMMIT ausgeführt wird. Eine Zeile auswählen: EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad'. 30. 397 . mit der Kommandozeilenoption -t von ecpg (siehe unten) oder dem Befehl EXEC SQL SET AUTOCOMMIT TO ON. das heißt. Auswählen mit einem Cursor: EXEC SQL DECLARE foo_bar CURSOR FOR SELECT number.. In der Standardeinstellung werden Transaktionen nur abgeschlossen. damit der SQL-Präprozessor sie erkennen kann. sie verweisen auf Variablen im C-Programm. Dieser Modus kann mit EXEC SQL SET AUTOCOMMIT TO OFF ausdrücklich ausgeschaltet werden.

um Ausnahmebedingungen in einem Programm zu behandeln. Ansonsten kann der Präprozessor diese Typen nicht verarbeiten.Kapitel 30 Dieser Abschnitt fängt mit EXEC SQL BEGIN DECLARE SECTION. Die Definition einer Struktur oder Union muss ebenso innerhalb eines DECLARE-Abschnitts stehen. Die besonderen Typen VARCHAR und VARCHAR2 werden für jede Variable in ein benanntes struct umgewandelt. können noch einmal außerhalb dieser speziellen Abschnitte deklariert werden. Siehe im vorigen Abschnitt für Beispiele. an und endet mit EXEC SQL END DECLARE SECTION. Diese Struktur ist passend als Schnittstelle zu SQL-Werten vom Typ varchar. wo ein Ausdruck erwartet wird. Eine Deklaration wie VARCHAR var[180]. Um eine ordnungsgemäß deklarierte C-Variable in einem SQL-Befehl zu verwenden. wie zum Beispiel int x. bei denen keine Verwendung mit SQL-Befehlen beabsichtigt ist. char foo[16]. schreiben Sie :varname. Die erste Methode gibt eine Nachricht aus.6 Fehlerbehandlung Die eingebettete SQL-Schnittstelle bietet einen einfachen und einen komplexen Weg. Die Deklarationen werden in die Ausgabedatei als normale C-Variablen übertragen und müssen also nicht nochmal deklariert werden. Zwischen diesen Zeilen müssen normale C-Variablendeklarationen stehen. wird umgewandelt in struct varchar_var { int len. Weitere Beispiele finden Sie in SQL-Büchern. Zum Beispiel: EXEC SQL WHENEVER sqlerror sqlprint. Variablen. 398 . oder EXEC SQL WHENEVER not found sqlprint. Anmerkung Dies ist kein erschöpfendes Beispiel der Verwendung des Befehls EXEC SQL WHENEVER. char arr[180]. weil er die Definition nicht kennt. 30. wenn eine bestimmte Voraussetzung eintritt. Diese Fehlerbehandlung bleibt im gesamten Programm eingeschaltet. bar[16]. } var.

UPDATE /* oder DELETE Befehl /* 3: leer /* 4: leer /* 5: leer char sqlwarn[8].sqlcode kleiner als null ist. struct { int sqlerrml. wie eine Datenbankdefinition. der den Fehler beschreibt. /* 0: 'W' wenn mindestens ein weiteres Feld 'W' ist /* 1: wenn 'W' dann wurde mindestens eine Zeichen/* kette beim Speichern in eine Hostvariable /* abgeschnitten /* 2: leer /* 3: leer /* 4: leer /* 5: leer /* 6: leer /* 7: leer char sqlext[8]. Der Text endet mit der Zeilennummer in der Quelldatei. Wenn es größer als null ist.sqlerrmc wird den Text enthalten. ist das ein ernster Fehler. wird sqlca. long sqlerrd[6]. } sqlerrm. die nicht mit der Anfrage übereinstimmt. */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ (Viele der leeren Felder könnten in einer zukünftigen Version verwendet werden. char sqlerrmc[70].) Wenn beim letzten SQL-Befehl kein Fehler auftrat.sqlcode 0 sein (ECPG_NO_ERROR). sqlca.sqlerrm. long sqlcode.ECPG: Eingebettetes SQL in C Für eine mächtigere Fehlerbehandlung bietet die eingebettete SQL-Schnittstelle ein struct und eine Variable namens sqlca wie folgt: struct sqlca { char sqlcaid[8]. /* 0: leer /* 1: OID der aktuellen Zeile. wenn angebracht /* 2: Anzahl betroffener Zeilen bei INSERT. Wenn sqlca. long sqlabc. } sqlca. 399 . ist das ein normaler Fehler. char sqlerrp[8]. als wenn eine Tabelle die gewünschte Zeile nicht enthält.

Die Bibliothek verwendet strtoul() für diese Umwandlung. als wir passende Variablen haben. :var2 vergessen. dass die Bibliothek nicht kennt. dass der Server mehr Argumente zurückgegeben hat. Die Datenbank gab eine normale Variable zurück. Sollte normalerweise nicht auftreten. Die Bibliothek verwendet strtod() für diese Umwandlung. Ein NULL-Wert wurde zurückgegeben und keine NULL-Indikatorvariable angegeben.Kapitel 30 Dies sind die Fehler. aber die angegebenen Variablen keine Arrays sind. Die Anfrage war leer. dass die Hostvariable vom Typ int ist und das Feld in der PostgreSQL-Datenbank einen anderen Typ hat und einen Wert enthält. wo ein Array erforderlich ist. dass der Präprozessor etwas erzeugt hat. der nicht als unsigned int interpretiert werden kann. Dies bedeutet. Das Programm versuchte auf eine Verbindung zuzugreifen. Gibt an. wo ein Array erforderlich ist. -220 (ECPG_NO_CONN): No such connection %s in line %d. -210 (ECPG_NO_ARRAY): Variable is not an array in line %d. -206 (ECPG_FLOAT_FORMAT): Not correctly formatted floating-point type: %s line %d. -200 (ECPG_UNSUPPORTED): Unsupported type %s on line %d. Vielleicht haben Sie inkompatible Versionen von Präprozessor und Bibliothek verwendet. die nicht existiert. 400 . die auftreten können: -12: Out of memory in line %d. :var2. Die Bibliothek verwendet strtol() für diese Umwandlung. dass der Server weniger Argumente zurückgegeben hat. -211 (ECPG_DATA_NOT_ARRAY): Data read from backend is not an array in line %d. dass die Anfrage mehrere Zeilen ergab. der nicht als float interpretiert werden kann. dass die Hostvariable vom Typ float ist und das Feld in der PostgreSQL-Datenbank einen anderen Typ hat und einen Wert enthält. Eine normale Variable wurde verwendet. -201 (ECPG_TOO_MANY_ARGUMENTS): Too many arguments line %d. als wir Hostvariablen haben. -207 (ECPG_CONVERT_BOOL): Unable to convert %s to bool on line %d. dass die Hostvariable vom Typ bool ist und das Feld in der PostgreSQL-Datenbank weder 't' noch 'f' ist. Dies bedeutet. Dies bedeutet. Vielleicht haben Sie ein paar Hostvariablen in der Liste INTO :var1. Dies bedeutet. -205 (ECPG_UINT_FORMAT): Not correctly formatted unsigned type: %s line %d. Dies bedeutet. Der SELECT-Befehl sollte nur eine Zeile ergeben. -204 (ECPG_INT_FORMAT): Not correctly formatted int type: %s line %d. dass der virtuelle Speicher aufgebraucht ist. Vielleicht haben Sie zu viele Hostvariablen in der Liste INTO :var1. Zeigt an. dass die Hostvariable vom Typ unsigned int ist und das Feld in der PostgreSQLDatenbank einen anderen Typ hat und einen Wert enthält. -202 (ECPG_TOO_FEW_ARGUMENTS): Too few arguments line %d. Dies bedeutet. der nicht als int interpretiert werden kann. -203 (ECPG_TOO_MANY_MATCHES): Too many matches line %d. Sollte normalerweise nicht auftreten. (Das kann in einem eingebetteten SQL-Programm normalerweise nicht passieren und könnte daher einen internen Fehler aufzeigen. Dies bedeutet. -208 (ECPG_EMPTY): Empty query line %d.) -209 (ECPG_MISSING_INDICATOR): NULL value without indicator in line %d.

den Sie versuchen zu verwenden. verwenden Sie: EXEC SQL INCLUDE dateiname. dass dies nicht das Gleiche ist wie #include <dateiname. Der Verbindungsversuch zur Datenbank ist fehlgeschlagen. nicht gefunden werden kann oder dass Sie am Ende des Cursors sind. wurde nicht vorbereitet. 100 (ECPG_NOT_FOUND): Data not found line %d. Irgendein PostgreSQL-Fehler. -241 (ECPG_INVALID_DESCRIPTOR_INDEX): Descriptor index out of range in line %d. abschließen oder zurückrollen können. Der angegebene Deskriptorindex ist außerhalb des gültigen Bereichs. 30. -400 (ECPG_PGSQL): '%s' in line %d. Das Programm versuchte auf eine Verbindung zuzugreifen. -240 (ECPG_UNKNOWN_DESCRIPTOR): Descriptor %s not found in line %d. dass das. Natürlich können Sie die CDirektive #include weiterhin für andere Headerdateien verwenden. wurde nicht vorbereitet. -243 (ECPG_VAR_NOT_NUMERIC): Variable is not a numeric type in line %d. den Sie versuchen zu verwenden. den Sie versuchen zu verwenden. Der PostgreSQL-Server hat signalisiert. -244 (ECPG_VAR_NOT_CHAR): Variable is not a character type in line %d. Der angegebene Deskriptor wurde nicht gefunden. der aussagt. Der Befehl. -401 (ECPG_TRANS): Error in transaction processing line %d. Der Text enthält die Fehlermeldung vom PostgreSQL-Server.h suchen.h> weil diese Datei nicht vom SQL-Präprozessor verarbeitet werden würde. dass wir die Transaktion nicht starten. die existier. -230 (ECPG_INVALID_STMT): Invalid statement name %s in line %d. Der Präprozessor für das eingebettete SQL wird nach einer Datei namens dateiname.ECPG: Eingebettetes SQL in C -221 (ECPG_NOT_CONN): Not connected in line %d.7 Dateien einbinden Um eine externe Datei in Ihr eingebettetes SQL-Programm einzubinden. Die Datenbank gab einen nichtnumerischen Wert zurück und die Variable war numerisch. Die Datenbank gab einen numerischen Wert zurück und die Variable war nicht numerisch.t aber nicht geöffnet ist. Eingebettete SQL-Befehle in der eingebundenen Datei werden also richtig verarbeitet. sie verarbeiten und das Ergebnis in die C-Ausgabe einfügen. -402 (ECPG_CONNECT): Could not connect to database %s in line %d. Beachten Sie. Dies ist ein “normaler” Fehler. Der angegebene Deskriptor wurde nicht gefunden. -242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM): Unknown descriptor item %s in line %d. Der Befehl. Der Befehl. 401 . was sie abfragen wollen. wurde nicht vorbereitet.

. da Sie eine Vorstellung haben.pgc verarbeiten. wollen Sie sicher wissen. Vor dem Compilieren schicken Sie die Datei durch den Präprozessor für eingebettetes SQL in C. welcher die SQL-Befehle.. Die verarbeitete Datei kann normal compiliert werden.und Kleinschreibung folgt.c Die erzeugte C-Quelldatei verwendet Headerdateien aus der PostgreSQL-Installation.c erzeugen. wie C-Programme mit eingebettetem SQL geschrieben werden. Das wird eine Datei mit Namen prog1. der normalerweise nicht durchsucht wird.c: %. also wenn Sie PostgreSQL an einem Ort installiert haben.und Kleinschreibung geachtet. wie Sie sie compilieren sollen. obwohl der Rest des Befehls EXEC SQL INCLUDE den normalen SQL-Regeln für Groß. 30.o prog2. Das Präprozessorprogramm heißt ecpg und ist in einer normalen PostgreSQL-Installation enthalten.o . Um ein eingebettetes SQL-Programm zu linken. führen den SQL-Befehl mit der libpq-Schnittstelle aus und legen die Ergebnisse in den zur Ausgabe bestimmten Argumenten ab. etwa so: cc -o meinprog prog1. Diese Funktionen holen sich Informationen aus den Argumenten.8 Eingebettete SQL-Programme verarbeiten Jetzt. Wenn Sie eine Programmdatei namens prog1. Wenn Ihre Eingabedateien nicht dem empfohlenen Namensmuster folgen. Nach dem Compilieren müssen Sie eine besondere Bibliothek einlinken.pgc $(ECPG) $< Die komplette Syntax von ecpg steht auf Seite 801. kann es praktisch sein. dann können Sie sie einfach mit ecpg prog1. -lecpg Wiederum müssen Sie vielleicht eine Option wie -L/usr/local/pgsql/lib zur Kommandozeile hinzufügen.pgc haben. die Sie verwendet haben. 402 . müssen Sie eine Option wie -I/usr/local/pgsql/include zur Kommandozeile bei der Compilierung hinzufügen. zum Beispiel: cc -c prog1. die die benötigten Funktionen enthält.pgc. müssen Sie die Bibliothek libecpg einbinden. können Sie die Ausgabedatei ausdrücklich mit der Option -o angeben. folgende implizite Regel in die make-Steuerdateien einzufügen: ECPG = ecpg %. in besondere Funktionsaufrufe umwandelt. Eingebettete SQL-Programme haben typischerweise die Erweiterung .Kapitel 30 Anmerkung Beim Namen der eingebundenen Datei wird auf Groß. Wenn Sie den Bauvorgang eines größeren Projekts mit make verwalten.

um die Schnittstelle zur Bibliothek herzustellen. stehen fest. (Siehe unten. Ausgabevariablen Für jede Ausgabevariable werden zehn Argumenet erzeugt. um Fehler in Ihren SQL-Befehlen zu suchen. Wenn er einen EXEC SQL-Befehl sieht. Die Argumente sind: eine Zeilennummer Dies ist die Zeilennummer der ursprünglichen Zeile. Alles dazwischen wird als SQL-Befehl behandelt und nach Variablen.h. eine Zeichenkette Dies ist der SQL-Befehl.9 Bibliotheksfunktionen Die Bibliothek libecpg enthält hauptsächlich “versteckte” Funktionen. Eingabevariablen Für jede Eingabevariable werden zehn Argumente erzeugt. wie man ECPG verwendet. sie übernimmt die Ausführung der meisten Befehle. und hoffentlich ist das kein Problem auf irgendeiner Plattform. aber in den Befehl eingesetzt werden sollen. wenn ein Symbol mit einem Doppelpunkt (:) anfängt. Zwei sind Kommentare und zwei binden Headerdateien ein. die Variablen. Dort. wo die Variablen hin sollen. dass das Ihren Code unportierbar macht.) Diese Variablen werden von der Funktion gefüllt.10 Interna Dieser Abschnitt erklärt. und falsch. d. Die Variable mit diesem Namen wird unter den Variablen. um die Funktionalität der eingebetteten SQL-Befehle umzusetzen. der ausgeführt werden soll. ECPGt_EORT Ein enum. die verwendet werden. Aber es gibt einige Funktionen. wenn das erste Argument von null verschieden ist. Das kann leicht 50 oder mehr Argumente ergeben. die auch direkt aufgerufen werden können. Der Log wird in den angegebenen Strom geschrieben.. der das Ende der Eingabevariablen anzeigt. Danach liest der Präprozessor die Datei und schreibt die Ausgabe. steht im Text ein ?. ❏ ECPGdebug(int an. (Siehe unten. FILE *strom) schaltet das Debugloggen ein. Die wichtigste Bibliotheksfunktion ist ECPGdo. die zuvor in EXEC SQL DECLARE-Abschnitten deklariert wurden. wenn nicht. Die ersten vier Zeilen. die von ecpg in die Ausgabe geschrieben werden. wenn man mit der Datenbank verbunden ist. Dies kann nützlich sein. Sie hat eine variable Zahl von Argumenten. gesucht. 403 . Der Befehl beginnt mit EXEC SQL und endet mit . Variablenersetzung tritt auf. der das Ende der Variablen anzeigt. Der Log enthält alle SQLBefehle mit den eingesetzten Eingabevariablen und die Ergebnisse vom PostgreSQL-Server. Beachten Sie. 30. die ersetzt werden müssen. damit Benutzer besser verstehen. greift er ein und ändert ihn.ECPG: Eingebettetes SQL in C 30. nur für Fehlermeldungen. Normalerweise wird einfach alles unverändert an die Ausgabe weitergeleitet.) ECPGt_EOIT Ein enum. wie ECPG intern funktioniert. Er wird durch die Eingabevariablen verändert. Diese Informationen können gelegentlich helfen. ❏ ECPGstatus() ergibt wahr. die bei der Compilierung noch nicht feststanden. durchsucht.

ECPGt_NO_INDICATOR. Der Offset zum nächsten Element im Array (für Arraydaten).. falls sie ein char oder varchar ist. 0L.. #include <ecpglib. #line 147 "foo.Kapitel 30 Für jede Variable. /* exec sql begin declare section */ #line 1 "foo. ECPGt_EORT). /* exec sql end declare section */ . 7. ECPGdo(__LINE__. wird umgewandelt in: /* Processed by ecpg (2. Die Anzahl der Elemente im Array (für Arraydaten). 6. Ein Zeiger auf die Indikatorvariable. 9. Zum Beispiel ein OPEN-Befehl wie EXEC SQL OPEN cursor. Hier ist ein vollständiges Beispiel.h>. .0) */ /* These two include files are added by the preprocessor */ #include <ecpgtype.&(result).. NULL. Ein Zeiger auf den Wert oder ein Zeiger auf den Zeiger. NULL .1L. 2.1L. wird nicht in die Ausgabe kopiert. (Die Einrückung hier wurde der Lesbarkeit halber hinzugefügt und stammt nicht vom Präprozessor. 0L. 4. NULL . int result. Anstelle dessen wird der DECLARE-Befehl des Cursors verwendet. ECPGt_NO_INDICATOR.pgc" ". Der Typ als spezielles Symbol. 0L. EXEC SQL END DECLARE SECTION. 0L. int index. EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index.pgc beschreibt (Einzelheiten könnten je nach der genauen Version des Präprozessors variieren): EXEC SQL BEGIN DECLARE SECTION.1L.h>.&(index). 10.sizeof(int).6. das die Ausgabe des Präprozessors bei einer Datei foo.) 404 . ECPGt_int. 0L.sizeof(int). 3. 5. ECPGt_EOIT. dass nicht alle SQL-Befehle so behandelt werden. Der Offset zum nächsten Element im Indikatorarray (für Arraydaten). int result.pgc" int index.. 0L. 8. die Teil eines SQL-Befehls ist. "SELECT res FROM mytable WHERE index = ? ECPGt_int. Der Typ der Indikatorvariable als spezielles Symbol. Beachten Sie. erhält die Funktion zehn Argumente: 1. weil er den Cursor auch mit öffnet. Die Größe der Variable. 0 Die Anzahl der Elemente im Indikatorarray (für Arraydaten).1L.

erhalten Sie einen Treiber. indem man die Umgebungsvariable CLASSPATH anpasst oder die entsprechende Kom405 . aber das müssen Sie eigentlich nur. der die JDBC-1-Spezifikation unterstützt. wenn er einmal kompiliert wurde.jar. 31.1. Weitere Informationen finden Sie in der offiziellen Dokumentation zur JDBCAPI. schreiben oder ausführen können. Wenn Sie mit einer JDK der Version 1. der die JDBC-2-Spezifikation unterstützt.2 oder JDK 1. Andererseits können Sie den Treiber selbst aus den Quellen bauen. erhalten Sie einen Treiber. wenn Sie am Quellcode Veränderungen vorgenommen haben. die die JDBCSchnittstelle verwenden. 31.1 bauen.B. dass der Treiber in reinem Java geschrieben ist und über das datenbankeigene Netzwerkprotokoll mit dem Datenbanksystem kommuniziert. aber es sollte Ihnen beim Einstieg helfen können. die Sie bewältigen müssen. Typ 4 heißt. Der Treiber wird für die Java-Version gebaut. PostgreSQL stellt einen JDBC-Treiber vom Typ 4 zu Verfügung. Dieses Kapitel ist keine vollständige Anleitung zum Programmieren mit JDBC. bevor Sie Programme.1.3). Einzelheiten dazu finden Sie in den PostgreSQL-Installationsanweisungen. Nach der Installation finden Sie den Treiber in PRÄFIX/share/java/ postgresql. Der Quellcode enthält auch einige Beispiele.1.1 Einrichtung des JDBC-Treibers Dieser Abschnitt beschreibt die Schritte. wenn Sie mit einer Java-2-JDK bauen (z.31 31 Die JDBC-Schnittstelle Die JDBC-API ist ein fester Bestandteil der Java-Plattform seit Version 1.1 Den Treiber besorgen Vorkompilierte Versionen des Treibers können von der PostgreSQL JDBC Website heruntergeladen werden. Daher ist der Treiber plattformunabhängig.2 Den Klassenpfad einrichten Um den Treiber verwenden zu können. 31. kann er auf jedem beliebigen System verwendet werden. die Sie gerade verwenden. entweder. Sie bietet eine standardisierte Schnittstelle für den Zugriff auf SQL-kompatible Datenbanken. JDK 1. muss das JAR-Archiv in den Klassenpfad (classpath) eingefügt werden.

Welche davon die bessere ist. Es gibt zwei mögliche Methoden. und diese Anwendung ist als /usr/local/lib/myapp. Um das zu erreichen. wie Sie den JDBC-Treiber in Ihren Programmen laden und initialisieren können. müssen Sie den Treiber laden. 31. wenn Sie es selbst gebaut haben. Der JDBC-Treiber unterstützt die Authentifizierungsmethoden trust. können Sie in der Datei postgresql. 31. die JDBC-2-Version.jar für die JDBC1. Der PostgreSQLJDBC-Treiber ist als /usr/local/pgsql/share/java/postgresql.sql importieren: import java.2 Den Treiber laden Bevor Sie mit einer Datenbank verbinden können.jar:/usr/local/pgsql/share/java/ postgresql.1. die den JDBC-Treiber verwendet. Für den PostgreSQL-Treiber würden Sie Folgendes verwenden: Class.forName("org.*.Driver"). ansonsten wahrscheinlich jdbc-1. Um die Anwendung auszuführen.jar installiert. 31.postgresql. (Das JAR-Archiv heißt postgresql. 31. die JDBC verwendet.2. Die Clientauthentifizierungs-Einstellungen in der Datei pg_hba. um auf eine Datenbank zuzugreifen.2 Initialisierung des Treibers Dieser Abschnitt beschreibt. steht in Abschnitt 31. Einzelheiten dazu finden Sie in Kapitel 19.2. hängt von Ihrem Code ab. md5 und crypt.Kapitel 31 mandozeilenoption beim Programm java verwendet. würden wir die folgenden Befehle verwenden: export CLASSPATH=/usr/local/lib/myapp.jar installiert.postgresql. ident.sql.) Nehmen wir an. Anmerkung Importieren Sie nicht das Paket org.jar oder jdbc-1. Wenn Sie es doch tun.bzw.3 Den Datenbankserver auf JDBC vorbereiten Weil Java nur TCP/IP-Verbindungen verwendet. dass er TCP/IP-Verbindungen annimmt.1. muss der PostgreSQL-Server so konfiguriert werden.conf müssen möglicherweise ebenfalls konfiguriert werden. werden Sie Ihre Quellen nicht kompilieren können.forName(). wir haben eine Anwendung.jar.2. Bei der ersten Methode lädt Ihr Code den Treiber implizit mit der Methode Class. 406 .java MyApp Wie Sie den Treiber innerhalb der Anwendung laden.jar:.conf tcpip_socket = true setzen oder die Option -i angeben.1 JDBC importieren Jede Quellcodedatei. wenn Sie postmaster starten. password. weil der Compiler verwirrt sein wird.2. muss das Paket java.

ImageViewer In diesem Beispiel wird die JVM versuchen.Die JDBC-Schnittstelle Damit wird der Treiber geladen und beim Laden automatisch im JDBC-System registriert. dann liegt das wahrscheinlich daran. ohne neu kompiliert werden zu müssen. den Treiber bei ihrer Initialisierung zu laden. 31. wenn die JVM gestartet wird. was Sie noch ändern müssten. wenn der Treiber nicht verfügbar ist. Um zu verbinden. Eine Sache noch zum Schluss: Wenn Ihr Code eine neue Verbindung (Klasse Connection) öffnet und Sie eine SQLException mit der Fehlermeldung No driver available erhalten. welche als nächstes besprochen wird.2. port Die Portnummer auf der der Server auf Verbindungen wartet.3 Mit der Datenbank verbinden Innerhalb JDBC wird eine Datenbank durch eine URL (Uniform Resource Locator) dargestellt. In PostgreSQL nimmt diese eine der folgenden Formen an: ❏ jdbc:postgresql:datenbank ❏ jdbc:postgresql://host/datenbank ❏ jdbc:postgresql://host:port/datenbank Die Parameter haben die folgenden Bedeutungen: host Der Hostname des Servers.getConnection(url. Dazu rufen Sie die Methode DriverManager. Anmerkung Die Methode forName() kann die Exception ClassNotFoundException erzeugen. Die Voreinstellung ist die Standardportnummer von PostgreSQL (5432).postgresql. passwort). aber damit legen Sie Ihren Code auf PostgreSQL fest. Das Einzige. benutzername. 407 . müssen die eine Instanz der Klasse Connection von JDBC erhalten. Danach wird ImageViewer gestartet. dann ist die zweite Methode zu empfehlen.drivers=org. Diese Methode ist besser. ist die Verbindungs-URL. und zwar mit der Option -D. Diese Methode ist die am häufigsten verwendete.Driver example.getConnection() auf: Connection db = DriverManager. datenbank Der Datenbankname. Zum Beispiel: java -Djdbc. Wenn Ihr Code in der Zukunft eventuell auch auf ein anderes Datenbanksystem zugreifen soll und Sie keine PostgreSQL-spezifische Funktionalität verwenden. Bei der zweiten Methode wird der Treiber als Parameter übergeben. Die Voreinstellung ist localhost. dass der Treiber nicht im Klassenpfad ist oder der übergebene Parameter nicht richtig war. weil Ihr Code damit andere Datenbanksysteme verwenden kann.

Dieses Beispiel führt die gleiche Anfrage wie oben aus.out.out.2. können Sie eine Anfrage ausführen. ResultSet rs = st. st.next()) { System. PreparedStatement st = db. System. int wert = 500.next()) { System.executeQuery(). Beispiel 31.executeQuery("SELECT * FROM meinetabelle WHERE x = 500"). wenn Sie einen SQL-Befehl an die Datenbank schicken wollen.close().4 Die Verbindung schließen Um die Datenbankverbindung zu schließen.print("Spalte 1 ergab ").out. 408 . while (rs.1: Eine einfache Anfrage mit JDBC verarbeiten Dieses Beispiel verwendet die Klasse Statement. Wenn Sie eine Instanz von Statement oder PreparedStatement haben. welche das komplette Ergebnis enthält. benötigen Sie eine Instanz der Klasse Statement oder PreparedStatement.println(rs. Statement st = db.print("Spalte 1 ergab "). rufen Sie einfach die Methode close() des ConnectionObjekts auf: db.close(). System. st. st.close().out.close().Kapitel 31 31. 31.prepareStatement("SELECT * FROM meinetabelle WHERE x = ?").close(). Beispiel 31.createStatement(). ResultSet rs = st. und gibt die erste Spalte jeder Zeile aus. while (rs. Als Ergebnis erhalten Sie eine Instanz der Klasse ResultSet.getString(1)).1 illustriert diesen Vorgang. wert). um eine einfache Anfrage auszuführen. } rs.println(rs.getString(1)). aber verwendet PreparedStatement und bindet einen Wert in die Anfrage ein.3 Ausführung von Anfragen und Verarbeitung der Ergebnisse Jedes Mal. } rs.setInt(1.

Diese Methode ist ähnlich der Methode executeQuery(). Threads zu verwenden. ❏ Laut JDBC-Spezifikation sollten Sie auf jedes Feld nur einmal zugreifen. zurück. PreparedStatement st = db. welche nicht verlangt. st. Das ergibt true. UPDATE bzw. es bereitet die Zeile auf die Verarbeitung vor. 31.7. sollten Sie es schließen. wird die aktuelle Instanz von ResultSet automatisch geschlossen.3. Lesen Sie auch Abschnitt 31. UPDATE oder DELETE auszuführen). Beispiel 31. 31. Am sichersten ist es. muss jeder Thread ein eigenes Statement-Objekt verwenden. dass pro Statement oder PreparedStatement nur ein ResultSet auf einmal existieren kann. dass Treiber aktualisierbare Ergebnismengen anbieten müssen.4 Ausführung von Aktualisierungen Um Daten zu verändern (ein INSERT. müssen Sie next() aufrufen. wenn Sie darüber nachdenken. was noch wichtiger ist.setInt(1.2: Zeilen löschen mit JDBC Dieses Beispiel führt einen einfachen DELETE-Befehl aus und gibt die Anzahl der gelöschten Zeilen aus. int wert = 500. Sie könnten eine erzeugen. ❏ Wenn Sie mit dem Statement-Objekt.1 Verwendung der Interfaces Statement oder PreparedStatement Folgendes muss bei der Verwendung der Interfaces Statement und PreparedStatement beachtet werden: ❏ Sie können eine Instanz von Statement so oft verwenden. können Sie einfach ein neues Statement-Objekt erzeugen und verwenden. auf jedes Feld so oft Sie wollen zuzugreifen.Die JDBC-Schnittstelle 31. die vom INSERT.prepareStatement("DELETE FROM meinetabelle WHERE x = ?"). weil dort einige wichtige Punkte besprochen werden. und sie für die Dauer der Verbindung verwenden. obwohl der PostgreSQL-Treiber Ihnen gegenwärtig erlaubt. sobald Sie die Verbindung geöffnet haben. ❏ Wenn Sie ein ResultSet nicht mehr benötigen. und. wenn Sie diese Regel befolgen. ❏ Wenn Sie Threads verwenden und mehrere Threads die Datenbank verwenden. Aber Sie müssen bedenken.2 illustriert die Verwendung. DELETE betroffen waren. während Sie ein ResultSet verarbeiten. ❏ Wenn Sie ein Statement oder PreparedStatement nicht mehr benötigen. ❏ Wenn Sie eine Anfrage ausführen müssen. aber sie gibt kein ResultSet zurück. wert). müssen Sie es mit close() schließen.2 Verwenden des Interface ResultSet Folgendes muss bei dem Verwenden des Interface ResultSet beachtet werden: ❏ Bevor Sie irgendwelche Werte lesen können. Sie können durch ein ResultSet keine Daten aktualisieren. Beispiel 31. Das ist in Übereinstimmung mit der JDBC-Spezifikation. müssen Sie es auf die normale Art und Weise mit dem SQL-Befehl UPDATE tun. wie Sie wollen. verwenden Sie die Methode executeUpdate(). ❏ ResultSet ist gegenwärtig eine Konstante. Wenn Sie Daten aktualisieren wollen. eine neue Anfrage ausführen.3. stattdessen gibt sie die Anzahl der Zeilen. aus dem das ResultSet erzeugt wurde. wenn ein Ergebnis vorhanden ist. mit der wir den SELECTBefehl ausgeführt haben. 409 .

31.createStatement().println(rowsDeleted + " Zeilen gelöscht"). müssen Sie die Beschränkungen jeder Methode verstehen. dass er sich wieder wie in Version 7. getBinaryStream() oder setBinaryStream() anwenden. setBytes(). wenn man sehr große Mengen binärer Daten speichern will.close(). Die LargeObjects-Methode ist besser geeignet. Large Objects haben auch einige Sicherheitsprobleme. setBytes(). hat aber ihre eigenen Beschränkungen.executeUpdate(). st. verwenden Sie die Methode execute(). weil jeder. welche Methode für Sie passend ist.close().out. Insbesondere wird beim Löschen einer Zeile mit einem Verweis auf ein Large Object nicht das Large Object selbst gelöscht. wodurch binäre Daten in einer getrennten Tabelle gespeichert werden und wobei man auf diese Daten durch einen Wert des Typs oid zugreifen kann. würde man eine riesige Menge Arbeitsspeicher benötigen.execute("DROP TABLE meinetabelle"). der mit der Datenbank verbunden ist. Diese Methode ist ähnlich der Methode executeQuery().2 verarbeiten die Methoden getBytes(). Der Datentyp bytea ist nicht besonders gut geeignet.5 Erzeugung und Modifizierung von Datenbankobjekten Um Datenbankobjekte wie Tabelle oder Sichten zu erzeugen. Um den Datentyp bytea zu verwenden. um sehr große Werte zu speichern. Um zu entscheiden.3: Eine Tabelle mit JDBC löschen Dieses Beispiel wird eine Tabelle löschen. 410 .1 setzen. getBinaryStream() und setBinaryStream() Werte des Datentyps bytea. um binäre Daten zu speichern. selbst wenn er keinen Zugriff auf die Zeile mit dem Verweis auf das Large Object hat. System.1 verarbeiteten diese Methoden Werte des Datentyps oid.1 verhält. Statement st = db. st. Das Löschen des Large Objects muss als separate Operation durchgeführt werden. Obwohl eine Spalte vom Typ bytea bis zu 1 GB Daten speichern kann. Sie können den Treiber so einstellen. Beispiel 31. In und vor 7.3 illustriert die Verwendung. indem Sie die Eigenschaft (property) compatible im ConnectionObjekt auf den Wert 7. Seit 7. um einen so großen Wert zu verarbeiten. Beispiel 31.Kapitel 31 int rowsDeleted = st. Version 7. 31. die auf Large Objects verwiesen haben. st. aber sie gibt kein Ergebnis zurück.2 war die erste Version des JDBC-Treibers. sollten Sie einfach die Methoden getBytes(). modifizieren oder löschen. die den Datentyp bytea unterstützt hat. jedes Large Object ansehen oder verändern kann.2 wurden einige Verhaltensweisen gegenüber früheren Versionen verändert. Bei der Einführung dieser Funktionalität in 7.6 Speicherung binärer Daten PostgreSQL bietet zwei verschiedene Methoden. Man kann binäre Daten in einer Tabelle mit dem Datentypen bytea speichern oder die Large-Objects-Funktionalität verwenden.

Beispiel 31. wenn die Bilddaten bereits in einem byte[]-Array vorliegen. Es ist also zu empfehlen.length()).prepareStatement("SELECT bild FROM bilder WHERE name = ?"). Das Auslesen des Bilds ist noch einfacher. // verwenden Sie die Daten hier irgendwie } rs. Hier überträgt setBinaryStream() die angegebene Anzahl von Bytes aus dem Datenstrom in die Spalte vom Typ bytea. file. wie Sie mit dem PostgreSQL-JDBC-Treiber binäre Daten verarbeiten können. Anmerkung In einer zukünftigen Version des JDBC-Treibers könnte es sein.4 enthält einige Beispiele.setString(1. die vom PostgreSQL-JDBC-Treiber zur Verfügung gestellt wird. "meinbild. 411 . ps.next()) { byte[] imgBytes = rs. wenn Sie Large Objects verwenden wollen.setBinaryStream(2. aber Statement könnte genauso gut verwendet werden. Sie haben eine Tabelle. können Sie entweder die Klasse LargeObject verwenden. Um ein Bild einzufügen.) PreparedStatement ps = con. (Wir verwenden hier die Klasse PreparedStatement.getBytes(1).prepareStatement("INSERT INTO bilder VALUES (?. ps.executeQuery(). die die Namen von Bilddateien enthält und Sie wollen das Bild in einer Spalte vom Typ bytea speichern: CREATE TABLE bilder (name text. dass Sie die LargeObject-Schnittstelle verwenden. fis.executeUpdate(). ?)").getName()). ps. PreparedStatement ps = conn. bild bytea).4: Binäre Daten mit JDBC verarbeiten Nehmen wir zum Beispiel an. dass die Methoden getBLOB() und setBLOB() nicht mehr mit Large Objects funktionieren.close(). Wichtig Zugriffe auf Large Objects müssen innerhalb eines SQL-Transaktionsblocks geschehen. könnten Sie folgenden Code verwenden: File file = new File("meinbild. FileInputStream fis = new FileInputStream(file).gif"). Einen Transaktionsblock können Sie mit setAutoCommit(false) starten. ResultSet rs = ps. Sie könnten das auch mit der Methode setBytes() machen. file. sondern dann mit dem Datentyp bytea. fis. ps.close(). ps.close().Die JDBC-Schnittstelle Um die Large-Objects-Funktionalität zu verwenden. if (rs != null) { while (rs. Beispiel 31.gif"). oder die Methoden getBLOB() ud setBLOB( ).setString(1.

// Erzeuge ein neues Large Object int oid = lobj.PGConnection)conn). while ((s = fis.read(buf.executeUpdate().postgresql. 412 . LargeObjectManager. fis.gif"). verwenden Sie: // Alle LargeObject-Aufrufe müssen in einem Transaktionsblock stehen conn. Wenn Sie eine sehr große Datei speichern müssen und die LargeObject-Schnittstelle verwenden wollen.Kapitel 31 } ps.getName()). ps.write(buf.setAutoCommit(false).prepareStatement("INSERT INTO bilder VALUES (?.create(LargeObjectManager.close().close(). ps.WRITE). } // Schließe das Large Object obj. bildoid oid). 2048)) > 0) { obj. // Kopiere die Daten aus der Datei in das Large Object byte buf[] = new byte[2048]. oid). tl += s.READ | LargeObjectManager. int s.setString(1. 0.open(oid. file. FileInputStream fis = new FileInputStream(file). tl = 0. Stattdessen könnten Sie auch ein InputStream-Objekt verwenden. // Öffne das Large Object zum Schreiben LargeObject obj = lobj.close(). Um das Bild einzufügen. ?)"). // Erzeuge einen Large-Object-Manager LargeObjectManager lobj = ((org. Hier haben wir die Daten als byte[] ausgelesen.setInt(2. könnten Sie Folgendes machen: CREATE TABLE bilder (name text. // Füge die Zeile in die Tabelle ein PreparedStatement ps = conn. ps. s). ps.WRITE). 0.getLargeObjectAPI(). // Öffne die Datei File file = new File("myimage.close().

getLargeObjectAPI(). 413 . ps. LargeObjectManager.open(oid. Der PostgreSQL-JDBC-Treiber ist Thread-sicher.setString(1. ansonsten könnte ein Thread eine Anfrage senden.close(). während ein anderer gerade Ergebnisse empfängt.prepareStatement("SELECT bildoid FROM bilder WHERE name = ?").Die JDBC-Schnittstelle Zum Auslesen des Large Objects aus der Datenbank könnten Sie folgenden Code verwenden: // Alle LargeObject-Aufrufe müssen in einem Transaktionsblock stehen conn.close(). Wenn ein Thread versucht. if (rs != null) { while (rs. obj.setAutoCommit(false). } ps. // Verwenden Sie die Daten hier irgendwie // Schließe das Objekt obj. dann wartet er. obj. besteht sie aus dem Senden und Empfangen der entsprechenden Daten.close(). ResultSet rs = ps.getInt(1). bis der andere seine aktuelle Operation abgeschlossen hat.postgresql. besteht die Operation aus dem Senden des Befehls und dem Empfangen des vollständigen ResultSet.size()). "meinbild. Sie müssen in Ihre Anwendungen also keine komplexen Algorithmen einbauen. dass nur ein Thread ein Connection-Objekt auf einmal verwenden kann.7 Verwendung des Treibers in einer Multithreadoder Servlet-Umgebung Ein Problem bei vielen JDBC-Treibern ist.size()]. die Verbindung zu verwenden.executeQuery().read(buf.gif"). während sie gerade von einem anderen verwendet wird. und das könnte ziemlich große Verwirrung stiften.PGConnection)conn). Wenn die Operation ein normaler SQL-Befehl ist. 0. } rs.READ). // Lese die Daten byte buf[] = new byte[obj.next()) { // Öffne das Large Object zum Schreiben int oid = rs. 31. // Erzeuge einen Large-Object-Manager LargeObjectManager lobj = ((org. dass mehr als ein Thread auf einmal auf die Datenbank zugreift. LargeObject obj = lobj. um zu verhindern. Wenn sie ein Fastpath-Aufruf ist (zum Beispiel das Lesen eines Blocks aus einem Large Object). PreparedStatement ps = con.

Der PostgreSQL-JDBC-Treiber unterstützt diese Funktionalität. 31. wie in Tabelle 31. der sie entweder schließt oder im Pool speichert.8. ob die Verbindung noch fehlerfrei ist. wenn er mit JDK 1. ist zu empfehlen einen Verbindungspool zu erzeugen.0 Optional Package (auch bekannt unter dem Namen JDBC 2. Seit JDBC 3 ist diese Funktionalität fester Bestandteil der JDBC-Schnittstelle.postgresql. hängt von den Anforderungen Ihrer Anwendungen ab. während der Anwendungscode die DataSource-Implementierung des Anwendungsservers (nicht die von PostgreSQL) verwendet. Um dieses Problem zu lösen.1 gezeigt.Jdbc3ConnectionPool Tabelle 31. Die Clientschnittstelle ist javax. Für eine Umgebung ohne Anwendungsserver bietet PostgreSQL zwei Implementierungen von DataSource.sql. sie wird in der Regel von normalem Anwendungscode verwendet um eine gepoolte Datenbankverbindung zu erhalten. Nochmal sei gesagt. Die meisten Anwendungsserver enthalten das JDBC 2.sql. Wenn keine freie Verbindung zur Verfügung steht. dann bittet er eine Verwaltungsklasse um ein Connection-Objekt.1 Überblick JDBC bietet eine Client. Wenn Sie mehrere Threads haben. die von einer Anwendung direkt verwendet werden können. sie wird von den meisten Anwendungsservern verwendet.ConnectionPoolDataSource. wenn nicht.8 Verbindungspools und Data Sources In JDBC 2 wurde ein standardisierter Verbindungspoolmechanismus in einer Zusatz-API namens JDBC 2. weil für jedes Connection-Objekt eine neue Sitzung gestartet wird.0 Optional Package. 31. es sei denn der Anwendungsserver unterstützt das ConnectionPoolDataSource-Interface nicht. diese Implementierungen sollten nicht in einer Anwendungsserverumgebung verwendet werden. gibt er sie dem Verwalter zurück. um auf den PostgreSQL-JDBCTreiber zuzugreifen.postgresql. Wie Sie sich entscheiden. und würde Sie schließen. 31. die Anfragen ausführen. dass es die Belastung des Servers vergrößert. Die Serverschnittstelle ist javax.2 Anwendungsserver: ConnectionPoolDataSource PostgreSQL enthält eine Implementierung von ConnectionPoolDataSource für JDBC 2 und eine für JDBC 3. Wenn ein Thread die Datenbank verwenden will.Kapitel 31 Dieses Verhalten ist vertretbar in normalen Anwendungen und Applets.0 Standard Extension) eingeführt.0 Optional Package aber man kann es auch separat von Sun über die JDBC Download-Site beziehen.ConnectionPool org.3. dann werden alle außer einem warten müssen.DataSource. oder mit JDK 1.jdbc2. Der Verwalter übergibt dem Thread eine freie Verbindung und markiert sie als in Benutzung.optional.8.x in Kombination mit dem JDBC 2. dann wird eine neue geöffnet. In einer Anwendungsserverumgebung wird die Konfiguration des Anwendungsservers normalerweise auf die ConnectionPoolDataSource-Implementierung von PostgreSQL verweisen. kann aber bei Servlets Leistungsprobleme verursachen. Eine Implementierung richtet einen Verbindungspool ein und die andere bietet einfach einen Zugang zu einer normalen Datenbankverbindung ohne Pool durch das DataSource-Interface.4 oder höher ( JDBC 3) kompiliert wurde. Der Verwalter würde auch prüfen.und eine Server-Schnittstelle für Verbindungspools.jdbc3.1: Implementierungen von ConnectionPoolDataSource 414 . Der Nachteil eines Verbindungspools ist. JDBC 2 3 Implementierungsklasse org. Wenn der Thread mit der Verbindung fertig ist.

user=testbenutzer. Die hier angebotene Verbindungspool-Implementierung hat nicht besonders viele Funktionen. 415 . könnte es so aussehen: serverName=localhost. Tabelle 31. Außerdem werden Verbindungen. die nicht den eingestellten Standardbenutzer verwenden. sondern speichern die Verbindung im Pool. wenn Sie an ein Programm übergeben werden. wenn das Pool selbst geschlossen wird.2 gezeigt werden. Wenn der Anwendungsserver alle Propertys in einem einzigen Bereich eingeben lässt. Viele Anwendungsserver bieten eine bessere Verbindungspool-Funktionalität und verwenden dafür stattdessen die Implementierung von ConnectionPoolDataSource. könnte das so aussehen: serverName=localhost databaseName=test user=testbenutzer password=testpasswort Oder wenn Semikolons anstelle von Zeilenumbrüchen als Trennzeichen verwendet werden.2: Konfigurations-Propertys von ConnectionPoolDataSource Viele Anwendungsserver verwenden eine Syntax im Property-Stil. welche in Tabelle 31. Die Voreinstellung ist false. dass ständig Verbindungen geöffnet und geschlossen werden müssen und es ermöglicht. Die Pool-Varianten schließen eine Verbindung nicht.Die JDBC-Schnittstelle Beide Implementierungen verwenden das gleiche Konfigurationsschema.password=testpasswort 31. wie in Tabelle 31.3 Anwendungen: DataSource PostgreSQL enthält zwei Implementierungen von DataSource für JDBC 2 und zwei für JDBC 3. Property serverName databaseName portNumber user password defaultAutoCommit Typ String String int String String boolean Beschreibung Hostname des PostgreSQL-Datenbankservers PostgreSQL-Datenbankname TCP-Port des PostgreSQL-Datenbankservers (oder 0. sondern direkt aufgebaut. also gibt es für jede dieser Propertys eine Get. um diese Einstellungen zu konfigurieren. dass eine großen Anzahl von Clients eine kleine Anzahl von Datenbankverbindungen unter sich aufteilen. nicht durch das Pool bedient. wo sie auf die Verwendung durch andere Clients wartet. JDBC verlangt.databaseName=test. wenn der Client die Methode close aufruft. also kein Autocommit. Dadurch wird vermieden. Daher ist es nicht ungewöhnlich.3 gezeigt wird. diese Propertys als einen Textblock einzugeben. um den Standardport zu verwenden) Benutzername für Datenbankverbindungen Passwort für Datenbankverbindungen Ob Autocommit auf Verbindungen an oder aus sein soll. dass ConnectionPoolDataSource-Objekte über JavaBean-Propertys konfiguriert werden. man kann das Pool nicht schrumpfen lassen.und eine Set-Methode. Unter anderem werden Verbindungen erst geschlossen.8.

setUser("testbenutzer"). source.setServerName("localhost").5: DataSource-Codebeispiel Der Code zum Initialisieren der DataSource mit Poolfunktion könnte so aussehen: Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource(). Beispiel 31. bis eine Verbindung an das Pool zurückgegeben wird.jdbc3.optional.optional. source. source. Die erlaubte Höchstzahl offener Datenbankverbindungen. dass DataSource-Objekte über JavaBean-Propertys konfiguriert werden. Die Anzahl der zu erzeugenden Datenbankverbindungen. source.5 zeigt ein Beispiel einer typischen Anwendung.4: Konfigurations-Propertys von DataSource Die Pool-Implementierungen haben einige zusätzliche Konfigurations-Propertys.PoolingDataSource org.3: Implementierungen von DataSource Alle Implementierungen verwenden das gleiche Konfigurationsschema. welche in Tabelle 31. welche in Tabelle 31.setDatabaseName("test"). Property dataSourceName initialConnectio ns maxConnections Typ String int int Beschreibung Jede DataSource mit Poolfunktion muss einen eindeutigen Namen haben. source.5 gezeigt werden. JDBC verlangt.Kapitel 31 JDBC 2 2 3 3 Pool Nein Ja Nein Ja Implementierungsklasse org.jdbc2. Wenn mehr Verbindungen verlangt werden. wenn das Pool initialisiert wird.postgresql.jdbc2. wird das Programm so lange blockiert. source.postgresql. also gibt es für jede dieser Propertys eine Get.jdbc3.postgresql. Tabelle 31.setMaxConnections(10).SimpleDataSource org. 416 .postgresql.5: Zusätzliche Pool-Konfigurations-Propertys von DataSource Beispiel 31.setPassword("testpasswort").setDataSourceName("Test-DataSource").4 gezeigt werden.Jdbc3PoolingDataSource Tabelle 31.und eine Set-Methode. die eine DataSource-Implementierung mit Poolfunktion verwendet. Property serverName databaseName portNumber user password Typ String String int String String Beschreibung PostgreSQL-Datenbankname PostgreSQL-Datenbankname TCP-Port des PostgreSQL-Datenbankservers (oder 0 um den Standardport zu verwenden) Benutzername für Datenbankverbindungen Passwort für Datenbankverbindungen Tabelle 31.Jdbc3SimpleDataSource org.

der dann eine Verbindung aus dem Pool verwendet. wie sie verfügbar ist (so lange zum Beispiel keine andere JVM das Pool aus dem JNDI abruft).8. // Verbindung verwenden } catch (SQLException e) { // Fehler loggen } finally { if (con != null) { try { con.Die JDBC-Schnittstelle Der Code. Beispiel 31. Beachten Sie.setServerName("localhost"). der eine DataSource-Instanz mit Poolfunktion initialisiert und sie im JNDI-System ablegt. source). source. Im Falle einer Implementierung ohne Poolfunktionen wird jedes Mal.6 gezeigt. In einer Anwendungsumgebung kann die Anwendung die DataSource-Instanz im JNDI speichern. try { con = source. könnte so aussehen: Connection con = null. new InitialContext(). der eine Verbindung aus dem Pool verwendet. source. source. Bei Implementierungen mit Poolfunktion wird die selbe Instanz so lange verwendet.setPassword("testpasswort").setMaxConnections(10). ansonsten wird eine neue Instanz mit den gleichen Einstellungen erzeugt. Ein Beispiel dafür wird in Beispiel 31. verfügbar machen muss. damit sie den Verweis auf die DataSource nicht für alle Anwendungskomponenten. nicht die ConnectionPoolDataSource-Implementierung von PostgreSQL. Der Code.getConnection(). try { DataSource source = (DataSource)new InitialContext().rebind("DataSource". dass es äußert wichtig ist.setUser("testbenutzer").6: DataSource-Codebeispiel mit JNDI Anwendungscode. dass alle Verbindungen irgendwann geschlossen werden. eine neue Instanz erzeugt. 417 .setDatabaseName("test"). con = source.4 Data Sources und JNDI Alle Implementierungen von ConnectionPoolDataSource und DataSource können im JNDI-System gespeichert werden. source. welche dieselben Einstellungen hat wie die gespeicherte Instanz. die ihn benötigen.lookup("DataSource").getConnection(). Connection con = null. könnte so aussehen: Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource().close(). wenn ein Objekt aus dem JNDI abgerufen wird. source. Ansonsten wird das Pool Verbindungen verlieren und früher oder später alle Clients blockieren. } catch (SQLException e) {} } 31. In einer Anwendungsserverumgebung wird normalerweise die DataSource-Instanz des Anwendungsservers im JNDI gespeichert. könnte wie folgt aussehen.setDataSourceName("Test-DataSource"). source.

org enthält aktuelle Informationen.html erhältlich.sun. und bietet außerdem vorkompilierte Treiber an. sollten Sie unbedingt die JDBC-API-Dokumentation (in der JDK von Sun enthalten) und die JDBC-Spezifikation lesen.close().9 Weitere Informationsquellen Fall Sie sie noch nicht gelesen haben. die noch nicht in diesem Kapitel enthalten sind. http://jdbc.Kapitel 31 // Verbindung verwenden } catch (SQLException e) { // Fehler loggen } catch (NamingException e) { // DataSource wurde nicht im JNDI gefunden } finally { if (con != null) { try { con. } catch (SQLException e) {} } } 31. 418 .com/products/jdbc/ index. Beide sind von http://java.postgresql.

verwendet von (pgobject.python. Wenn Sie einige einfache Beispiele für die Verwendung dieses Moduls sehen wollen. wo Sie unten auf der Seite eine Verknüpfung zum eigentlichen PythonCode der Seite finden werden.html. welches Zugriffe auf PostgreSQL-Large-Objects verwaltet. welche dem von der Python DB-SIG-Gruppe entwickelten DB-API 2. INV_WRITE Zugriffsmodi für Large Objects. als Parameter für Methodenaufrufe verwendet zu werden. welches Verbindungen mit der Datenbank verwaltet.)open SEEK_SET.linuxjournal. 32.org/topics/database/DatabaseAPI-2. Hier wird nur die ältere pg-Schnittstelle beschrieben.0.html finden. Weitere Informationen über sie finden Sie in der Anleitung zu libpq (Kapitel 27).0 Standard entspricht.net/rides an.1 Das pg-Modul Das Modul pg definiert drei Objekte: ❏ pgobject. Informationen über DB-API finden Sie auf der Seite http://www. Diese Konstanten sind: INV_READ. Diese sind dazu gedacht. 419 . SEEK_CUR. Eine Tutorial-ähnliche Einführung in DBAPI können Sie auf der Seite http://www2. ❏ pglargeobject. Konstanten Im Dictionary des pg-Moduls sind einige Konstanten definiert. und ❏ pgqueryobject.)locreate und (pglarge.druid. schauen Sie sich die Seite http://www. welches Anfrageergebnisse verwaltet. ausgereifte Schnittstelle im Modul pg und eine neuere Schnittstelle im Modul pgdb.32 32 PyGreSQL: Die Python-Schnittstelle PyGreSQL bietet eine alte.com/lj-issues/issue49/2605.

was heißt. die von dieser Einstellung abhängig sind. Diese Vorgabewerte wurden entworfen. sind mit [DV] markiert. um mit der Datenbank zu verbinden und um einige Vorgabewerte einzustellen. [passwd]) Parameter dbname Name der Datenbank. [tty]. [port]. __version__ Konstanten. Sie können den Benutzer nach einem Wert fragen. [opt]. Alle Vorgabewerte werden bei der Initialisierung des Moduls auf None gesetzt. [user].2 Funktionen im pg-Modul Das Modul pg definiert nur ein paar Methoden. ebenso müssen Sie nicht Ihre Umgebungsvariablen verändern. die die von PostgreSQL verwendeten Umgebungsvariablen übergehen. die die aktuelle Version enthalten 32. dass die Umgebungsvariablen verwendet werden sollen.)seek version. Die Unterstützung dieser Vorgabewerte kann beim Compilieren mit der Option DNO_DEF_VAR in der Datei Setup abgeschaltet werden.Kapitel 32 SEEK_END Positionszeiger für (pglarge. Die Methoden. [host]. damit Sie in Ihrem Code die Verbindungsparameter einfacher handhaben können. die Eingabe im Vorgabewert ablegen und müssen sich danach nicht mehr darum kümmern. mit der Verbunden werden soll (Zeichenkette/None) host Name des Serverhosts (Zeichenkette/None) port Port des Datenbankservers (ganze Zahl/-1) opt Optionen für den Server (Zeichenkette/None) 420 . connect Name connect – öffnet eine Verbindung zum Datenbankserver Synopsis connect([dbname].

die beim Alloziieren eines Objekts auftreten können) Beschreibung Diese Methode öffnet eine Verbindung zur angegebenen Datenbank auf dem angegebenen PostgreSQLServer. das eine Handle für die Datenbankverbindung ist.connect(dbname='testdb'. Die Argumente können auch mit Schlüsselwörtern angegeben werden. die in der Syntaxzeile stehen. Beispiele import pg con1 = pg. 'myhost'. user='bob') get_defhost Name get_defhost – ermittelt den Standardhostnamen [DV] 421 .connect('testdb'. None. (zuzüglich aller Exceptions. None. host='localhost'. Eine Beschreibung der genauen Bedeutung der Parameter finden Sie in Kapitel 27.PyGreSQL: Die Python-Schnittstelle tty Datei oder TTY für Debugausgaben vom Server (Zeichenkette/None) user PostgreSQL-Benutzer (Zeichenkette/None) passwd Passwort des Benutzers (Zeichenkette/None) Rückgabetyp pgobject Wenn erfolgreich. 'bob'.error Ein Fehler geschah während des Verbindungsaufbaus durch pg. pg. 5432. None) con2 = pg. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. dann wird ein Objekt zurückgegeben. SyntaxError Doppelt angegebenes Argument. Die Namen der Schlüsselwörter sind die.

422 . wenn Umgebungsvariab- len verwendet werden sollen. oder None. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. Beschreibung get_defhost() gibt den aktuell eingestellten Standardhost zurück. Rückgabetyp Zeichenkette oder None Vorheriger Standardhost. set_defhost Name set_defhost – setzt den Standardhostnamen [DV] Synopsis set_defhost(host) Parameter host Neuer Standardhost (Zeichenkette/None). Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht.Kapitel 32 Synopsis get_defhost() Parameter __¨`y_keine Rückgabetyp Zeichenkette oder None Standardhostangabe Exceptions SyntaxError Zu viele Argumente.

werden für zukünfige Verbindungen Umgebungsvariablen verwendet.PyGreSQL: Die Python-Schnittstelle Beschreibung set_defhost() setzt den Standardhost für neue Verbindungen. Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht. set_defport Name set_defport – setzt den Standardport [DV] 423 . Wenn None als Parameter angegeben wird. Beschreibung get_defport() gibt den aktuell eingestellten Standardport zurück oder None. wenn Umgebungsvariab- len verwendet werden sollen. Der vorherige Standardhost wird zurückgegeben. get_defport Name get_defport – ermittelt den Standardport [DV] Synopsis get_defport() Parameter keine Rückgabetyp ganze Zahl oder None Standardportangabe Exceptions SyntaxError Zu viele Argumente.

Der vorherige Standardport wird zurückgegeben. get_defopt Name get_defopt – ermittelt die Standardoptionsangabe [DV] Synopsis get_defopt() Parameter Keine Rückgabetyp Zeichenkette oder None Standardoptionsangabe Exceptions SyntaxError Zu viele Argumente. Wenn -1 als Parameter angegeben wird. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.Kapitel 32 Synopsis set_defport(port) Parameter port Neuer Standardport (ganze Zahl/-1). 424 . Rückgabetyp Ganze Zahl oder None Vorheriger Standardport. Beschreibung set_defport() setzt den Standardport für neue Verbindungen. dann werden für zukünfige Verbindungen Umgebungsvariablen verwendet.

get_deftty Name get_deftty – ermittelt das Standardterminal für Debugausgaben [DV] 425 . Wenn None als Parameter angegeben wird. werden für zukünftige Verbindungen Umgebungsvariablen verwendet. wenn Umgebungsvariablen verwendet werden sollen. Die vorherigen Standardoptionen werden zurückgegeben. set_defopt Name set_defopt – setzt die Standardoptionsangabe [DV] Synopsis Parameter options Die neue Standardoptionen-Zeichenkette (Zeichenkette/None).PyGreSQL: Die Python-Schnittstelle Beschreibung get_defopt() gibt die aktuell eingestellten Standardoptionen zurück oder None . Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. Beschreibung set_defopt() setzt die Standardoptionen für neue Verbindungen. Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht. Rückgabetyp Zeichenkette oder None Vorherige Standardoptionsangabe.

Beschreibung get_deftty() gibt das aktuell eingestellte Standard-TTY für Debugausgaben zurück. 426 . set_deftty Name set_deftty – setzt das Standardterminal für Debugausgaben [DV] Synopsis set_deftty(terminal) Parameter terminal Neues Standard-Debug-Terminal (Zeichenkette/None) Rückgabetyp Zeichenkette oder None Vorheriges Standard-Debug-Terminal. Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht.Kapitel 32 Synopsis get_deftty() Parameter Keine Rückgabetyp Zeichenkette oder None Standard-Debug-Terminal Exceptions SyntaxError Zu viele Argumente. oder None wenn Umgebungsvariablen verwendet werden sollen. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.

dann werden für zukünftige Verbindungen Umgebungsvariablen verwendet. get_defbase Name get_defbase – ermittelt die Standarddatenbank [DV] Synopsis get_defbase( Parameter Keine Rückgabetyp Zeichenkette oder None Standarddatenbankname Exceptions SyntaxError Zu viele Argumente. set_defbase Name set_defbase – setzt die Standarddatenbank [DV] 427 .wenn Umgebungsva- riablen verwendet werden sollen. Beschreibung get_defbase() gibt die aktuell eingestellte Standarddatenbank zurück oder None . Wenn None als Parameter angegeben wird. Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht. Das vorherige Standard-TTY wird zurückgegeben.PyGreSQL: Die Python-Schnittstelle Beschreibung set_defhost() setzt das Standard-Debug-TTY für neue Verbindungen.

Verwenden Sie diese Methoden nur. setzen Sie beim Compilieren die Option -DNO_DIRECT in der Datei Setup. dann werden für zukünftige Verbindungen Umgebungsvariablen verwendet.3 Verbindungsobjekt: pgobject Das Objekt pgobject verwaltet eine Verbindung mit einer PostgreSQL-Datenbank. was Sie tun. die den Status der Verbindung beschreiben. 32. Wenn Sie den Zugriff auf diese Methoden vom Modul aus verbieten wollen. Wenn Sie diese Methoden lieber deaktivieren wollen. db Die gewählte Datenbank (Zeichenkette). Diese Attribute sind: host Der Hostname des Servers (Zeichenkette). Rückgabetyp Zeichenkette oder None Vorheriger Standarddatenbankname Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.Kapitel 32 Synopsis set_defbase(database) Parameter database Neuer Standarddatenbankname (Zeichenkette/None). Es enthält und versteckt alle Parameter dieser Verbindung und erlaubt nur durch Funktionen Zugriff auf die wichtigen Parameter. Wenn None als Parameter angege- ben wird. dann setzen Sie die Option -DNO_LARGE in der Datei Setup. Diese sind mit [DA] markiert. port Der Port des Servers (ganze Zahl). wenn Sie ganz genau wissen. options 428 . Jedes pgobject-Objekt definiert einige konstante Attribute. Diese Methoden sind mit [LO] markiert. Einige andere Methoden bieten Zugriff auf Large Objects. Die vorherige Standarddatenbank wird zurückgegeben. Beschreibung set_defbase() setzt die Standarddatenbank für neue Verbindungen. Einige Methoden geben Ihnen direkten Zugriff auf die Verbindungssocket.

pg. status Der Zustand der Verbindung (ganze Zahl: 1 = in Ordnung. Rückgabetyp pgqueryobject oder None Ergebnis des Befehls. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. user Der Datenbankbenutzername (Zeichenkette). query Name query – führt einen SQL-Befehl aus Synopsis query(command) Parameter command Der SQL-Befehl (Zeichenkette). error Die letzte Warn.oder Fehlermeldung vom Server (Zeichenkette). 429 .PyGreSQL: Die Python-Schnittstelle Die Verbindungsoptionen (Zeichenkette). tty Das Terminal für Debugausgaben (Zeichenkette). ValueError Leerer SQL-Befehl. 0 = fehlerhaft).error Ein Fehler bei der Verarbeitung des Befehls oder eine ungültige Verbindung.

ist der Rückgabewert die OID der neu eingefügten Zeile.h. aus dem man die Anfrageergebnisse mit dem Methoden getresult() oder dictresult() abrufen kann oder das man einfach ausdrucken kann. kein SELECT). Beschreibung Die Methode reset() setzt die aktuelle Verbindung zur Datenbank zurück. der kein Ergebnis liefert (d.Kapitel 32 Beschreibung Die Methode query() sendet einen SQL-Befehl an die Datenbank. Wenn der Befehl ein anderer ist. dann wird None zurückgegeben. reset Name reset – setzt die Verbindung zurück Synopsis reset( Parameter Keine Rückgabetyp Keiner Exceptions TypeError Zu viele Argumente. Ansonsten wird ein Objekt vom Typ pgqueryobject zurückgegeben. Wenn der Befehl ein INSERT-Befehl ist. close Name close – schließt die Datenbankverbindung 430 .

damit die DB-SIG-Schnittstelle ihre entsprechende close-Funktion implementieren kann. 431 . Hauptsächlich ist diese Funktion vorhanden. Exceptions TypeError Zu viele Argumente. Beschreibung Die Methode close() schließt die Datenbankverbindung. Die Verbindung wird sowieso geschlossen. fileno Name fileno – gibt die Socketnummer der Datenbankverbindung zurück Synopsis fileno() Parameter Keine Rückgabetyp Socketnummer Die Socketnummer. wenn das Verbindungsobjekt gelöscht wird. aber mit dieser Methode können Sie sie ausdrücklich schließen.PyGreSQL: Die Python-Schnittstelle Synopsis close() Parameter keine Rückgabetyp Keiner Exceptions TypeError Zu viele Argumente. über die mit der Datenbank verbunden wurde.

dass zuerst LISTEN ausführen müssen. die die Benachrichtigung ausgelöst hat. pg.) Wenn der Server keine Benachrichtigung liefert. Exceptions TypeError Zu viele Argumente.Kapitel 32 Beschreibung Die Methode fileno() gibt die Socketnummer zurück.error Ungültige Verbindung. über die mit der Datenbank verbunden wurde. gibt die Methode None zurück. Diese Information kann zum Beispiel für select verwendet werden. Ansonsten ergibt Sie ein Tupel (ein Paar) (name. None Die letzte Benachrichtigung vom Server. Beschreibung Die Methode getnotify() versucht vom Server eine Benachrichtigung abzuholen. weil ansonsten getnotify immer None zurückgibt. (Benachrichtigungen werden mit dem SQL-Befehl NOTIFY erzeugt. getnotify Name getnotify – gibt die letzte Benachrichtigung vom Server zurück Synopsis getnotify( Parameter Keine Rückgabetyp Tupel. pid). wobei name der Name der Benachrichtigung ist und pid die Prozess-ID der Sitzung. inserttable Name inserttable – fügt eine Liste in eine Tabelle ein 432 . Denken Sie daran.

Die Liste ist eine Liste von Tupeln oder Listen. putline Name putline – schreibt eine Zeile für die Serversocket [DA] Synopsis putline(line) Parameter line Zu schreibende Zeile (Zeichenkette). 433 . long oder double sein.PyGreSQL: Die Python-Schnittstelle Synopsis inserttable(table. values Die Liste der einzufügenden Zeilenwerte (Liste). Achtung: Diese Methode prüft nicht. integer. die die Werte jeder einzufügenden Zeile bestimmen.error Ungültige Verbindung. values) Parameter table Der Tabellenname (Zeichenkette). sie prüft nur. Die Zeilenwerte können vom Typ string. Beschreibung Mit der Methode inserttable() können Sie schnell große Mengen Daten in eine Tabelle einfügen: Sie fügt die gesamte Werteliste in die Tabelle ein. pg. Rückgabetyp Keiner Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. ob die Felder mit der Tabellendefinition übereinstimmen. ob sie selbst die Typen verarbeiten kann.

pg. pg. 434 .error Ungültige Verbindung. Beschreibung Mit der Methode putline() können Sie eine Zeichenkette direkt zur Serversocket schreiben.Kapitel 32 Rückgabetyp keiner Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. getline Name getline – liest eine Zeile von der Serversocket [DA] Synopsis getline() Parameter Keine Rückgabetyp Zeichenkette Die gelesene Zeile.error Ungültige Verbindung. Beschreibung Mit der Methode getline() können Sie eine Zeichenkette direkt von der Serversocket lesen. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.

könnten Client und Server desynchronisiert werden.PyGreSQL: Die Python-Schnittstelle endcopy Name endcopy – synchronisiert Client und Server [DA] Synopsis endcopy() Parameter Keine Rückgabetyp Keiner Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. die direkt auf die Socket zugreifen. Beschreibung Durch die Verwendung der Methoden. pg.error Ungültige Verbindung. locreate Name locreate – erzeugt ein Large Object in der Datenbank [LO] Synopsis locreate(mode) Parameter mode Erzeugungsmodus 435 . Mit dieser Methode wird die Synchronisierung zwischen Client und Server wiederhergestellt.

pg. Der Modus kann durch eine “Oder”-Verknüpfung der im Modul pg definierten Konstanten INV_READ (lesen) und INV_WRITE (schreiben) angegeben werden. getlo Name getlo – öffnet ein Large Object [LO] Synopsis getlo(oid) Parameter oid OID eines bestehenden Large Object (ganze Zahl) Rückgabetyp pglarge Eine Handle für das Large Object Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.error Ungültige Verbindung. Beschreibung Die Methode locreate() erzeugt ein Large Object in der Datenbank. das eine Handle für ein PostgreSQL-Large-Object darstellt.Kapitel 32 Rückgabetyp pglarge Ein Objekt.error Ungültige Verbindung oder Fehler bei der Erzeugung des Objekts. 436 . pg. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.

Eine Reihe zusätzlicher Methoden wird unten beschrieben. pg. 32. diese Klasse zu verwenden. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. Beschreibung Mit der Methode loimport() können Sie ein Large Object ganz einfach erzeugen. Rückgabetyp pglarge Eine Handle für das Large Object. die Sie verwenden wollen. Die beste Art und Weise. ist wie folgt: import pg 437 .4 Datenbank-Wrapper-Klasse: DB Das Modul pg enthält eine Klasse namens DB. Alle Methoden der Klasse pgobject sind auch in diesem Objekt enthalten.PyGreSQL: Die Python-Schnittstelle Beschreibung Mit der Methode getlo() können Sie auf ein früher erzeugtes Large Object durch die Klasse pglarge zugreifen.error Ungültige Verbindung oder Fehler beim Importieren. wenn Sie die OID kennen. die die Daten enthält. Geben Sie einfach den Namen der Datei an. loimport Name loimport – importiert ein Large Object aus einer Datei [LO] Synopsis loimport(filename) Parameter filename Der Name der zu importierenden Datei (Zeichenkette).

Beschreibung Die Methode pkey() gibt den Primärschlüssel einer Tabelle zurück.."). dass diese Methode eine Exception auslöst.) for r in db.. Beachten Sie. Die Initialisierung der Klasse DB erfolgt mit den gleichen Argumenten wie die Methode pg.dictresult(): print '%(foo)s %(bar)s' % r Im Folgenden werden die Methoden und Variablen dieser Klasse beschrieben. die der Primärschlüssel der Tabelle ist.Kapitel 32 db = pg. wenn die Tabelle keinen Primärschlüssel hat. Außerdem werden dabei einige interne Variablen initialisiert. genau wie es pg. Rückgabetyp Zeichenkette Name der Spalte.connect.connect() tut. get_databases Name get_databases – ermittelt eine Liste der Datenbanken im System 438 . bar FROM foo_bar_table WHERE foo !~ bar. Die Anweisung db = DB() öffnet eine Verbindung zu einem lokalen Datenbankserver mit allen Vorgabeeinstellungen. pkey Name pkey – gibt den Primärschlüssel einer Tabelle zurück Synopsis pkey(table) Parameter table Name der Tabelle.DB(.query("SELECT foo.

ist die Verwendung dieser Methode bequemer. 439 . get_tables Name get_tables – ermittelt eine Liste aller Tabellen in der aktuellen Datenbank Synopsis get_tables() Parameter Keine Rückgabetyp Liste Liste aller Tabellen in der aktuellen Datenbank.PyGreSQL: Die Python-Schnittstelle Synopsis get_databases() Parameter Keine Rückgabetyp Liste Liste der Datenbanken im System . Beschreibung Obwohl Sie diese Informationen auch mit einer direkten Anfrage ermitteln können. Beschreibung Obwohl Sie diese Informationen auch mit einer direkten Anfrage ermitteln können. ist die Verwendung dieser Methode bequemer.

der gesucht werden soll.Kapitel 32 get_attnames Name get_attnames – gibt die Spaltennamen einer Tabelle zurück Synopsis get_attnames(table) Parameter tabelle Name der Tabelle. Rückgabetyp Dictionary Die Schlüssel des Dictionary sind die Spaltennamen. arg Ein Dictionary oder ein Wert. keyname Name einer Spalte. 440 . Beschreibung Diese Methode ermittelt für die angegebene Tabelle die Namen der Spalten und deren Typen. arg. die als Schlüssel verwendet werden soll (optional). get Name get – liest eine Zeile aus einer Datenbanktabelle Synopsis get(table. [keyname]) Parameter table Name der Tabelle. die Werte sind die Typennamen der Spalten.

um ihn eindeutig zu machen: Er besteht aus der Zeichenkette oid_ gefolgt vom Namen der Tabelle.PyGreSQL: Die Python-Schnittstelle Rückgabetyp Dictionary Ein Dictionary mit Spaltennamen als Schlüssel und Zeilenwerten als Werte. wenn nötig durch Ersetzen der alten Werte. a) Parameter table Name der Tabelle. wird daraus der Wert des Schlüssels entnommen und es wird um die gelesenen Werte ergänzt. dass sie sehr groß werden könnte. 441 . a Ein Dictionary mit Werten. Wenn keyname nicht angegeben ist. Die OID wird ebenso in das Dictionary aufgenommen. Um dieses Problem zu überwinden. Danach lädt es die Werte aus der Datenbank zurück in das Dictionary. dass die Einfügeoperationen länger und länger dauern. wie diese Funktion implementiert ist. je größer die Tabelle wird. Rückgabetyp ganze Zahl Die OID der neu eingefügten Zeile. wird der Spaltenname verändert. von der Sie denken. aber damit man das Dictionary mit mehreren Tabellen verwenden kann. Beschreibung Diese Methode fügt Werte aus dem Dictionary in die angegebene Tabelle ein. Wegen der Art. werden Sie feststellen. wenn die Werte durch Regeln. um eine einzelne Zeile zu lesen. wird der Primärschlüssel der Tabelle verwendet. verändert worden sind. Trigger usw. Dadurch wird das Dictionary aktuell gehalten. Der Suchschlüssel muss eine eindeutige Zeile auswählen. erzeugen Sie einfach einen Index für die OID-Spalte jeder Tabelle. Wenn arg ein Dictionary ist. insert Name insert – fügt eine Zeile in eine Datenbanktabelle ein Synopsis insert(table. Beschreibung Diese Methode ist ein einfacher Mechanismus.

aber aktualisiert eine vorhandene Zeile. wobei der Name der OID-Spalte wie bei get verändert wird. Beschreibung Ähnlich wie insert. a) Parameter table Name der Tabelle. Vorgabewerte usw. 442 . Rückgabetyp ganze Zahl Die OID der aktualisierten Zeile. [a]) Parameter table Name der Tabelle. mit eventuellen Veränderungen durch Trigger. clear Name clear – setzt die Werte einer Datenbanktabelle zurück Synopsis clear(table. a Ein Dictionary mit Werten. Das zurückgegebene Dictionary ist das gleiche wie das übergebene. Die Aktualisierung wird auf Basis der OID vorgenommen. Regeln.Kapitel 32 update Name update – aktualisiert eine Datenbanktabelle Synopsis update(table.

Numerische Typen werden auf 0 gesetzt. und alle anderen werden nicht verändert. wie oben beschrieben. werden nur die Spalten zurückgesetzt. Wenn das DictionaryArgument vorhanden ist. Rückgabetyp Dictionary Ein Dictonary mit einer leeren Zeile. Die Löschoperation verwendet die OID aus dem Dictionary. delete Name delete – löscht eine Zeile aus einer Datenbanktabelle Synopsis delete(table. Rückgabetyp Keiner Beschreibung Diese Methode löscht eine Zeile aus einer Tabelle. a Ein Dictionary mit Werten. Datumstypen auf 'today'. [a]) Parameter table Name der Tabelle. Beschreibung Diese Methode setzt die Spalten einer Tabelle auf typabhängige Werte zurück. die im Dictionary vorkommen. alles andere auf eine leere Zeichenkette.PyGreSQL: Die Python-Schnittstelle a Ein Dictionary mit Werten. 443 .

5 Anfrageergebnisobjekt: pgqueryobject Das Objekt pgqueryobject enthält ein Anfrageergebnis und bietet Methoden um dieses Anfragergebnis auszuwerten.query() erzeugt. Objekte dieses Typs werden von der Methode pgobject. die durch die Anfrage ausgewählt wurden. pg. Beschreibung Die Methode getresult() gibt eine Liste von Werten zurück.Kapitel 32 32. Weitere Informationen über das Anfrageergebnis können mit den Methoden listfields.error Das Anfrageergebnis ist ungültig. dictresult Name dictresult – gibt die von einer Anfrage ermittelten Werte als Dictionary zurück 444 . Exceptions SyntaxError Zu viele Argumente. fieldname und fieldnum ermittelt werden. getresult Name getresult – gibt die von einer Anfrage ermittelten Werte zurück Synopsis getresult() Parameter Keine Rückgabetyp Liste Eine Liste von Tupeln.

listfields Name listfields – gibt die Spaltennamen des Anfrageergebnisses zurück Synopsis listfields() Parameter Keine Rückgabetyp Liste Liste der Spaltennamen Exceptions SyntaxError 445 . Beschreibung Die Methode dictresult() gibt eine Liste der von der Anfrage ermittelten Werte zurück.error Das Anfrageergebnis ist ungültig. Exceptions SyntaxError Zu viele Argumente.PyGreSQL: Die Python-Schnittstelle Synopsis dictresult() Parameter Keine Rückgabetyp Liste Eine Liste von Dictionaries. pg. wobei jede Zeile als Dictionary mit den Spaltennamen als Schlüssel dargestellt wird.

wenn Sie die Ergebnisse tabellarisch darstellen wollen. Die Spaltennamen sind in derselben Reihenfolge wie die Ergebniswerte.error Ungültiges Anfrageergebnis oder ungültige Verbindung. pg.error Ungültiges Anfrageergebnis oder ungültige Verbindung. Beschreibung Die Methode listfields() ergibt eine Liste der Spaltennamen im Anfrageergebnis. Beschreibung Mit der Methode fieldname() können Sie den Spaltennamen aus einer Spaltennummer ermitteln. Das kann zum Beispiel nützlich sein.Kapitel 32 Zu viele Argumente. fieldname Name fieldname – ermittelt den Spaltennamen für eine Spaltennummer Synopsis fieldname(i) Parameter i Spaltennummer (ganze Zahl) Rückgabetyp Zeichenkette Spaltenname Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. pg. Die Spalten sind in derselben Reihenfolge wie die Ergebniswerte. 446 . ValueError Ungültige Spaltennummer.

ntuples Name ntuples – gibt die Anzahl der Ergebniszeilen in einem Ergebnisobjekt zurück 447 .error Ungültiges Anfrageergebnis oder ungültige Verbindung. ValueError Unbekannter Spaltenname. Damit kann man zum Beispiel eine Funktion schreiben. die die Werte eines Anfrageergebnisses anhand einer dem Programm bekannten Tabellendefinition in ihre korrekten Typen umwandelt. Die zurückgegebene Nummer zählt in der Reihenfolge der Ergebniswerte.PyGreSQL: Die Python-Schnittstelle fieldnum Name fieldnum – ermittelt die Spaltennummer für einen Spaltennamen Synopsis fieldnum(name) Parameter name Spaltenname (Zeichenkette) Rückgabetyp ganze Zahl Spaltennummer Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. pg. Beschreibung Die Methode fieldnum() ermittelt die Spaltennummer für einen Spaltennamen.

error Die letzte Warn. pgcnx Das zugehörige pgobject-Objekt. was der genaue Fehler war. wodurch nur die wichtigen Parameter in Funktionsaufrufen angegeben werden müssen. genauso wie pgobject-Objekte es tun. pglarge-Objekte definieren einige konstante Attribute. Das OID-Attribut ist sehr interessant. Exceptions SyntaxError Zu viele Argumente. Diese Attribute sind: oid Die OID des Objekts. Alle Funktionen geben bei einem Fehler eine allgemeine Fehlermeldung zurück. aus dem es erzeugt wurde. Python gibt den Speicher des pgobject-Objekts erst frei. Es speichert einen Verweis auf das pgobject-Objekt. 32. Es speichert und versteckt alle “wiederkehrenden” Variablen (Objekt-ID und Verbindung). wenn alle daraus erzeugten pglarge-Objekte auch freigegeben wurden. weil Sie damit später ein pglarge-Objekt mit der Methode getlo() der Klasse pgobject erzeugen können. egal. Jede Veränderung am pgobject-Objekt wirkt sich daher auf das pglarge-Objekt aus. die Informationen über das Objekt enthalten.6 Large Object: pglarge Das Objekt pglarge verwaltet alle Operationen mit PostgreSQL-Large-Objects. und leitet die eigenen Aufrufe an dieses weiter. 448 . Weitere Informationen über die Large-Object-Schnittstelle in PostgreSQL finden Sie in Kapitel 28.oder Fehlermeldung auf der Verbindung.Kapitel 32 Synopsis ntuples() Parameter Keine Rückgabetyp ganze Zahl Anzahl der Zeilen im Ergebnisobjekt. Das Attribut error des Objekts enthält die genaue Fehlermeldung. Beschreibung Die Methode ntuples() gibt die Anzahl der von der Anfrage ermittelten Zeilen zurück.

wenn Sie in solchen Situationen die Fehlermeldung prüfen wollen. müssen Sie selbst Sperren einrichten.PyGreSQL: Die Python-Schnittstelle Wichtig In Multithread-Umgebungen kann error durch einen anderen Thread. IOError Schon geöffnet oder Fehler beim Öffnen. pg. der dasselbe pgobject-Objekt verwendet. verändert werden. 449 . Rückgabetyp Keiner Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. Der Modus kann durch eine “Oder”-Verknüpfung der im Modul pg definierten Konstanten INV_READ (lesen) und INV_WRITE (schreiben) angegeben werden. Beachten Sie. ähnlich wie die Unix-Funktion open(). open Name open – öffnet das Large Object Synopsis open(mode) Parameter mode Zugriffsmodus (ganze Zahl). Beschreibung Die Methode open() öffnet ein Large Object zum Lesen oder Schreiben. dass diese Objekte geteilt sind und nicht dupliziert werden.error Ungültige Verbindung.

ähnlich wie die Unix-Funktion close(). read Name read – liest aus dem Large Object 450 . pg.error Ungültige Verbindung.Kapitel 32 close Name close – schließt das Large Object Synopsis close() Parameter Keine Rückgabetyp Keiner Exceptions SyntaxError Zu viele Argumente. IOError Objekt ist nicht geöffnet oder Fehler beim Schließen. Beschreibung Die Methode close() schließt ein vorher geöffnetes Large Object.

write Name write – schreibt in das Large Object Synopsis write(string) Parameter string Zu schreibende Daten (Zeichenkette). pg. ausgehend von der aktuellen Position. Rückgabetyp Zeichenkette Die gelesenen Daten.error Ungültige Verbindung oder ungültiges Objekt. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. Beschreibung Die Methode read() liest Daten aus dem Large Object. IOError Objekt ist nicht geöffnet oder Fehler beim Schreiben.PyGreSQL: Die Python-Schnittstelle Synopsis read(size) Parameter size Maximal zu lesende Daten (ganze Zahl). Rückgabetyp Keiner 451 .

Beschreibung Die Methode write() schreibt Daten in das Large Object. whence) Parameter offset Neue Position (ganze Zahl). pg.Kapitel 32 Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. pg.error Ungültige Verbindung oder ungültiges Objekt. IOError Objekt ist nicht geöffnet oder Fehler beim Schreiben. ausgehend von der aktuellen Position. IOError Objekt ist nicht geöffnet oder Fehler beim Positionieren. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. whence Ausgangspunkt für die neue Position (ganze Zahl). 452 . Rückgabetyp ganze Zahl Die neue aktuelle Position im Objekt. seek Name seek – ändert die aktuelle Position im Large Object Synopsis seek(offset.error Ungültige Verbindung oder ungültiges Objekt.

Der Parameter whence kann durch eine der im Modul pg definierten Konstanten SEEK_SET (zählt vom Anfang des Objekts). Exceptions SyntaxError Zu viele Argumente. Beschreibung Die Methode tell() gibt die aktuelle Lese.PyGreSQL: Die Python-Schnittstelle Beschreibung Die Methode seek() bewegt die aktuelle Lese. pg. tell Name tell – gibt die aktuelle Position im Large Object zurück Synopsis tell() Parameter Keine Rückgabetyp ganze Zahl Aktuelle Position im Objekt. SEEK_CUR (zählt von der aktuellen Position aus) und SEEK_END (zählt vom Ende des Objekts) angegeben werden.und Schreibposition im Large Object.und Schreibposition im Large Object zurück. 453 . IOError Objekt ist nicht geöffnet oder Fehler beim Positionieren.error Ungültige Verbindung oder ungültiges Objekt.

error Ungültige Verbindung oder ungültiges Objekt. Beschreibung Die Methode unlink() löscht ein Large Object. IOError Objekt ist nicht geschlossen oder Fehler beim Löschen. size Name size – gibt die Größe des Large Object zurück Synopsis size() Parameter Keine 454 . pg.Kapitel 32 unlink Name unlink – löscht das Large Object Synopsis unlink() Parameter Keine Rückgabetyp Keiner Exceptions SyntaxError Zu viele Argumente.

Gegenwärtig müssen Sie das Large Object erst öffnen.PyGreSQL: Die Python-Schnittstelle Rückgabetyp Ganze Zahl Die Größe des Large Object. IOError Objekt ist nicht geschlossen oder Fehler beim Exportieren. pg. weil Sie für Web-Anwendungen sehr nützlich ist. pg. Rückgabetyp Keiner Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.error Ungültige Verbindung oder ungültiges Objekt.error 455 . Beschreibung Mit der Methode size() können Sie die Größe des Large Objects ermitteln. IOError Objekt ist nicht geöffnet oder Fehler beim Positionieren. Exceptions SyntaxError Zu viele Argumente. export Name export – speichert das Large Object in einer Datei Synopsis export(filename) Parameter filename Name der zu erzeugenden Datei. Sie wurde implementiert.

456 . Beschreibung Mit der Methode export() können Sie den Inhalt eines Large Objects auf eine ganze einfache Art und Weise in einer Datei abspeichern. nicht auf dem Serverrechner. erzeugt.Kapitel 32 Ungültige Verbindung oder ungültiges Objekt. Die Exportdatei wird auf dem Rechner des Programms.

Diese Informationen sind wahrscheinlich nur für die Leser nützlich. die zumindest die ersten paar Kapitel dieses Teils gelesen haben. Trigger usw. 457 . wenn Sie die gesamte restliche Benutzerdokumentation zu PostgreSQL verstanden haben. Dieser Teil beschreibt auch die in der PostgreSQL-Distribution verfügbaren serverseitigen Programmiersprachen und allgemeine einige allgemeine Themen über Serverprogrammiersprachen. denen Sie sich wahrscheinlich erst widmen sollten. Das sind fortgeschrittene Themen.3 Teil V Server-Programmierung In diesem Teil geht es um die Erweiterung der Serverfunktionalität durch benutzerdefinierte Funktionen. Datentypen.

VAKAT VAKAT .

(Manche Systeme nennen dies auch Data Dictionary. und zwar mit benutzerdefinierten ❏ ❏ ❏ ❏ Funktionen (ab Abschnitt 33. wissen Sie. Im Gegensatz dazu können herkömmliche Datenbanksysteme nur erweitert werden. die einen neuen Typ oder eine neue Funktion implementiert.3) Datentypen (ab Abschnitt 33. weil seine Operation von Systemkatalogen gesteuert wird. die Operation im laufenden Betrieb verändern zu können. Ein wichtiger Unterschied zwischen PostgreSQL und normalen relationalen Datenbanksystemen ist. wie man die SQL-Sprache in PostgreSQL erweitern kann. Der PostgreSQL-Server kann außerdem Anwendercode durch dynamisches Laden aufnehmen. sondern auch Informationen über Datentypen. der in SQL geschrieben ist.13) 33. und da die Operation von PostgreSQL von diesen Tabellen gesteuert wird.1 Wie die Erweiterbarkeit funktioniert PostgreSQL ist erweiterbar. macht PostgreSQL auf einzigartige Weise geeignet für schnelles Prototyping von neuen Anwendungen und Speicherstrukturen. Code. Spalten in so genannten Systemkatalogen speichern. kann sogar noch einfacher in den Server integriert werden. dass diese die Informationen über Datenbanken.) Die Kataloge erscheinen für den Benutzer als normale Tabellen. Tabellen. und PostgreSQL wird diese bei Bedarf laden. Diese Tabellen können vom Benutzer verändert werden. Diese Fähigkeit. dass PostgreSQL von Benutzern erweitert werden kann. Das heißt. der Benutzer kann eine Objektdatei (zum Beispiel eine dynamische Bibliothek) angeben. 459 . Zugriffsmethoden und so weiter. bedeutet das.10) Operatoren (ab Abschnitt 33. indem der Quellcode selbst verändert wird oder indem spezielle Module vom DBMS-Hersteller geladen werden.33 33 SQL erweitern In den folgenden Abschnitten besprechen wir. Funktionen.11) Aggregatfunktionen (ab Abschnitt 33. Wenn Sie sich mit normalen relationalen Datenbanksystemen auskennen. aber das Datenbanksystem speichert darin seine internen Informationen. dass PostgreSQL viel mehr Informationen in seinen Katalogen speichert: nicht nur Informationen über Tabellen und Spalten.

Der Körper einer SQL-Funktion sollte eine Liste aus einem oder mehreren SQL-Befehlen.Kapitel 33 33. durch Semikolons getrennt. z. Zusammengesetzte Typen entstehen immer. die Referenzseite des Befehls CREATE FUNCTION parat zu haben. die in einer Sprache wie C implementiert sind. 33.name. Die Beispiele in diesem Abschnitt finden Sie auch in funcs. Basistypen sind die. kann die Punktschreibweise. Diese entsprechen im Allgemeinen so genannten abstrakten Datentypen. $2 ist das zweite und so weiter. kann es nützlich sein. dass die Syntax von CREATE FUNCTION erfordert. entweder durch zwei Apostrophe ('') oder einen Backslash vor dem Apostroph (\'). Auf die Argumente einer SQL-Funktion kann im Funktionskörper mit der Syntax $n verwiesen werden: $1 ist das erste Argument. sein. 33.2 Das PostgreSQL-Typensystem Ein Datentyp ist entweder ein Basis. Wenn ein Argument einen zusammengesetzten Typ hat. verwendet werden. Der Benutzer kann auf die Attribute dieser Typen durch die Anfragesprache zugreifen.6) ❏ in C geschriebene Funktionen (Abschnitt 33.3 Benutzerdefinierte Funktionen PostgreSQL stellt vier Arten von Funktionen zur Verfügung: ❏ in SQL geschriebene Funktionen (Abschnitt 33.5) ❏ interne Funktionen (Abschnitt 33. dass der Körper der Funktion von Apostrophen eingeschlossen wird und dass daher Apostrophe im Funktionskörper durch Fluchtfolgen ersetzt werden müssen. um die Beispiele besser verstehen zu können. Einzelheiten dazu folgen weiter unten. zusammengesetzte Typen oder beide als Argumente haben. ist das Ergebnis der Funktion der NULLWert. (Die Anfrage muss ein SELECT-Befehl sein. wenn der Rückgabetyp der Funktion als SETOF typ angegeben wurde.4 SQL-Funktionen SQL-Funktionen führen eine beliebige Liste von SQL-Befehlen aus und geben das Ergebnis der letzten Anfrage in der Liste zurück. (Bedenken Sie.B. 460 . Am einfachsten sind in SQL geschriebene Funktionen. dass “die erste Zeile” eines mehrzeiligen Ergebnisses nur genau bestimmbar ist. wenn Sie ORDER BY verwenden.7) Jede Art von Funktion kann Basistypen.c im Tutorialverzeichnis. Andererseits kann eine SQL-Funktion auch eine Ergebnismenge zurückgeben.) Im einfachen Fall (ohne Ergebnismenge) wird die erste Zeile aus dem Ergebnis der letzten Anfrage zurückgegeben.) Wenn die letzte Anfrage zufällig keine Zeilen zurückgibt. daher fangen wir mit denen an. wie der Benutzer es beschreibt. wenn der Benutzer eine Tabelle erzeugt.sql und funcs. Außerdem kann jede Art von Funktion einen Basistyp oder einen zusammengesetzten Typ zurückgeben. $1.4) ❏ in einer prozeduralen Sprache geschriebene Funktionen (zum Beispiel PL/Tcl oder PL/pgSQL) (Abschnitt 33.oder ein zusammengesetzter Typ. In dem Fall werden alle Ergebniszeilen der letzten Anfrage zurückgegeben. um auf die Attribute des Arguments zuzugreifen. PostgreSQL kann mit diesen Typen nur durch vom Benutzer zur Verfügung gestellte Methoden umgehen und versteht das Verhalten dieser Typen nur so weit. Während Sie dies lesen. wie zum Beispiel int4. Beachten Sie.

integer) RETURNS integer AS ' SELECT $1 + $2. SELECT eins(). eins -----1 Wie Sie sehen. anstatt einfach immer 1. Eine bessere Definition wäre daher: CREATE FUNCTION tf1 (integer.$2 461 . antwort --------3 Hier ist eine etwas nützlichere Funktion. die Basistypen als Argumente verwenden. SELECT ad