P. 1
pg-handbuch

pg-handbuch

|Views: 497|Likes:
Published by userXXL

More info:

Published by: userXXL on Jul 30, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

03/21/2013

pdf

text

original

Sections

  • 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
  • 1.2 Grundlagen der Architektur
  • 1.3 Eine Datenbank erzeugen
  • 1.4 Auf eine Datenbank zugreifen
  • 2.3 Eine neue Tabelle erzeugen
  • 0.1 Eine neue Tabelle erzeugen
  • 2.4 Eine Tabelle mit Zeilen füllen
  • 2.5 Eine Tabelle abfragen
  • 2.6 Verbunde zwischen Tabellen
  • 2.7 Aggregatfunktionen
  • 2.8 Daten aktualisieren
  • 2.9 Daten löschen
  • 3.3 Fremdschlüssel
  • 3.4 Transaktionen
  • 3.5 Vererbung
  • 3.6 Schlussfolgerung
  • 4.1 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
  • 4.2 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
  • 5.1 Tabellengrundlagen
  • 5.2 Systemspalten
  • 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
  • 5.5 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
  • 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
  • 5.8 Andere Datenbankobjekte
  • 5.9 Verfolgung von Abhängigkeiten
  • 6.1 Daten einfügen
  • 6.2 Daten aktualisieren
  • 6.3 Daten löschen
  • 7.1Überblick
  • 7.2 Tabellenausdrücke
  • 7.2.1 Die FROM-Klausel
  • 7.2.2 Die WHERE-Klausel
  • 7.2.3 Die GROUP BY- und HAVING-Klauseln
  • 7.3 Select-Listen
  • 7.3.1 Elemente der Select-Liste
  • 7.3.2 Ergebnisspaltennamen
  • 7.3.3 DISTINCT
  • 7.4 Anfragen kombinieren
  • 7.5 Zeilen sortieren
  • 7.6 LIMIT und OFFSET
  • 8.1 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
  • 8.3 Zeichenkettentypen
  • 8.4 Typen für binäre Daten
  • 8.5 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
  • 8.6 Der Typ boolean
  • 8.7 Geometrische Typen
  • 8.7.2 Strecken
  • 8.7.3 Rechtecke
  • 8.7.5 Polygone
  • 8.8 Typen für Netzwerkadressen
  • 8.8.3 inet vs. cidr
  • 8.8.4 macaddr
  • 8.9 Bitkettentypen
  • 8.10 Objekt-Identifikator-Typen
  • 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
  • 9.1 Logische Operatoren
  • 9.2 Vergleichsoperatoren
  • 9.3 Mathematische Funktionen und Operatoren
  • 9.4 Zeichenkettenfunktionen und -operatoren
  • 9.5 Funktionen und Operatoren für binäre Daten
  • 9.6 Mustervergleiche
  • 9.6.2 SIMILAR TO und reguläre Ausdrücke nach SQL99
  • 9.6.3 Reguläre Ausdrücke nach POSIX
  • 9.7 Datentyp-Formatierungsfunktionen
  • 9.8 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
  • 9.9 Geometrische Funktionen und Operatoren
  • 9.10 Funktionen für Netzwerkadresstypen
  • 9.11 Funktionen zur Bearbeitung von Sequenzen
  • 9.12 Konditionale Ausdrücke
  • 9.12.2 COALESCE
  • 9.12.3 NULLIF
  • 9.13 Diverse Funktionen
  • 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.8 Zeilenweiser Vergleich
  • 10.1Überblick
  • 10.2 Operatoren
  • 10.3 Funktionen
  • 10.4 Wertspeicherung
  • 10.5 UNION- und CASE-Konstruktionen
  • 11.2 Indextypen
  • 11.3 Mehrspaltige Indexe
  • 11.4 Indexe für Unique Constraints
  • 11.5 Funktionsindexe
  • 11.6 Operatorklassen
  • 11.7 Partielle Indexe
  • 11.8 Indexverwendung überprüfen
  • 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
  • 13.1 EXPLAIN verwenden
  • 13.2 Vom Planer verwendete Statistiken
  • 13.3 Den Planer mit expliziten JOIN-Klauseln kontrollieren
  • 13.4 Eine Datenbank füllen
  • 13.4.1 Autocommit ausschalten
  • 13.4.2 COPY FROM verwenden
  • 13.4.3 Indexe entfernen
  • 13.4.4 Danach ANALYZE ausführen
  • 14.1 Kurzversion
  • 14.2 Voraussetzungen
  • 14.3 Die Quellen erhalten
  • 14.4 Wenn Sie eine alte Version aktualisieren
  • 14.5 Installationsvorgang
  • 14.6 Einrichtung nach der Installation
  • 14.6.1 Dynamische Bibliotheken
  • 14.6.2 Umgebungsvariablen
  • 14.7 Unterstützte Plattformen
  • 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.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
  • 17.1 Datenbankbenutzer
  • 17.2 Benutzerattribute
  • 17.4 Privilegien
  • 17.5 Funktionen und Trigger
  • 18.1Überblick
  • 18.2 Eine Datenbank erzeugen
  • 18.3 Template-Datenbanken
  • 18.4 Datenbankkonfiguration
  • 18.5 Alternativer Speicherplatz
  • 18.6 Eine Datenbank zerstören
  • 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
  • 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
  • 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
  • 22.1 SQL-Dump
  • 22.1.1 Den Dump wiederherstellen
  • 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
  • 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
  • 24.1 Ermittlung des Festplattenplatzverbrauchs
  • 24.2 Verhalten bei voller Festplatte
  • 25.1 Nutzen aus WAL
  • 25.2 Zukünfiger Nutzen
  • 25.3 WAL-Konfiguration
  • 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
  • 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
  • 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
  • 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.10 Ein Large Object entfernen
  • 28.4 Serverseitige Funktionen
  • 28.5 Beispielprogramm
  • 29.1Überblick
  • 29.2 pgtcl in eine Anwendung laden
  • 29.3 pgtcl-Befehlsreferenz
  • 29.4 Beispielprogramm
  • 30.1 Das Konzept
  • 30.2 Zum Datenbankserver verbinden
  • 30.3 Eine Verbindung schließen
  • 30.4 SQL-Befehle ausführen
  • 30.5 Daten übergeben
  • 30.6 Fehlerbehandlung
  • 30.7 Dateien einbinden
  • 30.8 Eingebettete SQL-Programme verarbeiten
  • 30.9 Bibliotheksfunktionen
  • 30.10 Interna
  • 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
  • 32.1 Das pg-Modul
  • 32.2 Funktionen im pg-Modul
  • 32.3 Verbindungsobjekt: pgobject
  • 32.4 Datenbank-Wrapper-Klasse: DB
  • 32.5 Anfrageergebnisobjekt: pgqueryobject
  • 32.6 Large Object: pglarge
  • 33.1 Wie die Erweiterbarkeit funktioniert
  • 33.2 Das PostgreSQL-Typensystem
  • 33.3 Benutzerdefinierte Funktionen
  • 33.4 SQL-Funktionen
  • 33.4.1 SQL-Funktionen mit Basistypen
  • 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.10 Benutzerdefinierte Datentypen
  • 33.11 Benutzerdefinierte Operatoren
  • 33.12 Operator-Optimierungsinformationen
  • 33.12.1COMMUTATOR
  • 33.12.2 NEGATOR
  • 33.12.3 RESTRICT
  • 33.12.4JOIN
  • 33.12.5 HASHES
  • 33.12.6 MERGES (SORT1, SORT2, LTCMP, GTCMP)
  • 33.13 Benutzerdefinierte Aggregatfunktionen
  • 33.14 Erweiterungen für Indexe vorbereiten
  • 33.14.1Indexmethoden und Operatorklassen
  • 33.14.2 Indexmethodenstrategien
  • 33.14.3Indexmethoden-Unterstützungsroutinen
  • 33.14.4 Ein Beispiel
  • 33.14.5 Optionale Merkmale von Operatorklassen
  • 34.1 Schnittstellenfunktionen
  • 34.2 Schnittstellenunterstützungsfunktionen
  • 34.3 Speicherverwaltung
  • 34.4 Sichtbarkeit von Datenveränderungen
  • 35.1 Triggerdefinition
  • 35.2 Umgang mit dem Triggermanager
  • 35.3 Sichtbarkeit von Datenveränderungen
  • 35.4 Ein vollständiges Beispiel
  • 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
  • 37.1 Installation von prozeduralen Sprachen
  • 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.1 Cursorvariablen deklarieren
  • 38.8.2 Cursor öffnen
  • 38.8.3 Cursor verwenden
  • 38.9 Fehler und Meldungen
  • 38.10 Triggerprozeduren
  • 38.11 Portieren von Oracle PL/SQL
  • 38.11.1Portierungsbeispiele
  • 38.11.2Andere zu beachtende Dinge
  • 38.11.3Anhang
  • 39.1Überblick
  • 39.2 PL/Tcl-Funktionen und Argumente
  • 39.3 Datenwerte in PL/Tcl
  • 39.4 Globale Daten in PL/Tcl
  • 39.5 Datenbankzugriff aus PL/Tcl
  • 39.6 Triggerprozeduren in PL/Tcl
  • 39.7 Module und der Befehl unknown
  • 39.8 Tcl-Prozedurnamen
  • 40.1 PL/Perl-Funktionen und Argumente
  • 40.2 Datenwerte in PL/Perl
  • 40.3 Datenbankzugriff aus PL/Perl
  • 40.4 Trusted und Untrusted PL/Perl
  • 40.5 Fehlende Funktionalität
  • 41.1 PL/Python-Funktionen
  • 41.2 Triggerfunktionen
  • 41.3 Datenbankzugriff
  • 41.4 Eingeschränkte Umgebung
  • I. SQL-Befehle
  • II. PostgreSQL-Clientanwendungen
  • III. PostgreSQL-Serveranwendungen
  • A.1 Eingabeinterpretation von Datum und Zeit
  • A.2 Schlüsselwörter in Datums- und Zeitangaben
  • A.3 Geschichte der Kalendersysteme
  • C.1 Unterstützte Leistungsmerkmale
  • C.2 Nicht unterstützte Leistungsmerkmale
  • 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.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.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
  • D.25 Version 6.3.1
  • D.26 Version 6.3
  • D.27 Version 6.2.1
  • D.28 Version 6.2
  • D.29 Version 6.1.1
  • D.30 Version 6.1
  • D.31 Version 6.0
  • E.1Überblick
  • E.5 pg_amproc
  • E.6 pg_attrdef
  • E.10 pg_constraint
  • E.11 pg_conversion
  • E.12 pg_database
  • E.13 pg_depend
  • E.14 pg_description
  • E.15 pg_group
  • E.16 pg_index
  • E.17 pg_inherits
  • E.18 pg_language
  • E.19 pg_largeobject
  • E.20 pg_listener
  • E.21 pg_namespace
  • E.22 pg_opclass
  • E.23 pg_operator
  • E.25 pg_rewrite
  • E.26 pg_shadow
  • E.27 pg_statistic
  • E.28 pg_trigger
  • Literaturverzeichnis

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 .

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

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

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

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

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

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

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

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

um die Sprache SQL genauer kennen zu lernen. wenn Sie mit einem dieser Bereiche noch nicht vertraut sind. Die folgenden Kapitel sollen Ihnen eine Einführung in PostgreSQL. Sie sollten nicht davon ausgehen. wie man Computer verwendet.3 Teil I Tutorial Willkommen zum PostgreSQL-Tutorial. 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. Dieser Teil soll Ihnen vor allem praktische Erfahrung mit den wichtigen Teilen des PostgreSQL-Systems geben. relationale Datenbanken und die Sprache SQL geben. oder Teil IV um zu erfahren. Sie benötigen nur etwas allgemeines Wissen. wie Sie Anwendungen für PostgreSQL entwickeln können. können Sie Teil II lesen. 29 . Wenn Sie dieses Tutorial durchgearbeitet haben. dann sollten Sie auch Teil III lesen.

VAKAT VAKAT .

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

.

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

VAKAT VAKAT .

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

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

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

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

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

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

IS UNKNOWN. 61 . Subtraktion IS TRUE. dass die Operatorvorrangsregeln auch für benutzerdefinierte Operatoren gelten.SQL-Syntax Manchmal werden Sie auch Klammern hinzufügen müssen. Division.1: Operatorvorrang (abnehmend) Beachten Sie.6). Diesen Preis zahlt man für die Erweiterbarkeit. 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. größer als rechts rechts links links Gleichheit. die die gleichen Namen haben wie die eingebauten Operatoren. Operator/Element . Um das gewünschte Verhalten in diesem Fall zu erreichen. müssen Sie SELECT (5 !) .6.6. weil der Parser keine Ahnung hat – bevor es zu spät ist -. 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. dann hat er den gleichen Vorrang wie der eingebaute »+«-Operator. was Ihrer tut. ganz gleich. wenn Sie Kombinationen von binären und unären Operatoren verwenden. Zum Beispiel: SELECT 5 ! . IS FALSE. schreiben. Wenn Sie zum Beispiel einen Operator »+« für einen eigenen Datentyp definieren. wird verarbeitet als SELECT 5 ! (. dass ! als Postfixoperator und nicht als Infixoperator definiert ist. Modulus Addition.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

num.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.num. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 3 | c | 3 | yyy (2 rows) => SELECT * FROM t1 INNER JOIN t2 USING (num).Kapitel 7 Um all das zusammenzufassen. nehmen wir an. num | name | wert -----+------+-----1 | a | xxx 3 | c | yyy (2 rows) => SELECT * FROM t1 LEFT JOIN t2 ON t1. num | name | wert -----+------+-----1 | a | xxx 3 | c | yyy (2 rows) => SELECT * FROM t1 NATURAL INNER JOIN t2.num = t2. num | name | num | wert -----+------+-----+-----1 | a | 1 | xxx 94 . 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.

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

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

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

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

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

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

p65 Schwarz 101 28.02...up . 101. 12:07 .08.

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

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

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

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

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

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

.

8 8 Datentypen PostgreSQL stellt seinen Benutzern eine reichhaltige Menge eingebauter Datentypen zur Verfügung. zur allgemeinen Verwendung gedachten Datentypen. Monat. 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: Datentypen 109 . Benutzer können weitere Typen mit CREATE TYPE zu PostgreSQL hinzufügen. Die meisten alternativen Namen in der Spalte “Alias” sind interne Namen. Darüber hinaus gibt es einige für interne Zwecke gebrauchte und einige veraltete Typen. 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. die hier nicht gezeigt sind.1 zeigt alle eingebauten. Tabelle 8. die von PostgreSQL aus historischen Gründen verwendet werden. 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.

character.und Ausgabefunktionen bestimmt wird. character varying. double precision. decimal. Einige Eingabe. bit varying. 8. s) ] path point polygon real smallint serial text time [ (p) ] [ without time zone ] Alias Beschreibung Geldbetrag decimal [ (p.und Zeittypen. Jeder Datentyp hat eine externe Darstellung. um die Geschwindigkeit zu verbessernAuf einigen Systemen können die numerischen Operationen bei einigen Datentypen zum Beispiel ohne Benachrichtigung Überlauf oder Unterlauf verursachen. real. wie zum Beispiel die Datums. 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. time. numeric.Kapitel 8 Name money numeric [ (p. 4. Viele eingebaute Datentypen haben offensichtliche externe Formate. dass das Ergebnis einer Ausgabefunktion gegenüber dem ursprünglichen Wert an Genauigkeit verlieren kann. die von seinen Eingabe. varchar. Einige Typen sind allerdings nur in PostgreSQL vorhanden.1 Numerische Typen Numerische Typen bestehen aus 2-. interval. Tabelle 8. Einige Operatoren und Funktionen (z.B.2 listet die verfügbaren Typen.und 8-Byte-Ganzzahlen (englisch integer).und 8-Byte-Fließkommazahlen (floating point) und Zahlen mit Dezimalbrüchen mit fester Präzision. boolean. 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. wie zum Beispiel offene oder geschlossene Pfade.) Kompatibilität: Die folgenden Typen (oder deren Schreibweisen) sind von SQL vorgesehen: bit. timestamp (beide mit und ohne with time zone). smallint. char.und Ausgabefunktionen sind nicht umkehrbar.1: Datentypen (Forts. date. 4. integer.2: Numerische Typen 110 . Das heißt. Addition und Multiplikation) führen zur Laufzeit keine Fehlerprüfung durch. oder haben mehrere mögliche Eingabeformate.

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

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

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

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

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

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

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

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

Tag ISO-8601.12 gezeigt.13. alles wahlweise gefolgt von einer Zeitzonenangabe.)ltige Eingabewerte für den Typ time. 99 BC Tabelle 8.008 99008 J2451187 January 8. Tag Jahr und Tag innerhalb des Jahres Jahr und Tag innerhalb des Jahres Julianischer Tag Jahr 99 vor unserer Zeitrechnung time-Werte Tabelle 8. wie in Tabelle 8. Jahr. Stunde muss <= 12 sein identisch mit 00:00:00 Tabelle 8.) Also sind 1999-01-08 04:05:06 119 . Januar in jedem Modus ISO-8601. 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). AM hat keinen Einfluss identisch mit 16:05. Januar im US-Modus.10: Datumseingabe (Forts. August im europäischen Modus) US-Schreibweise. gefolgt von einer gültigen Zeitzonenangabe. Monat. Jahr. 18.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.) Beschreibung zweideutig (8. (Siehe Tabelle 8.12: Zeiteingabe mit Zeitzone Mehr Beispiele für Zeitzonen finden Sie in Tabelle 8. Beispiel 04:05:06. Beispiel 04:05:06.13. Monat.11 zeigt gü (Forts. die für time gültig sind. 1.Datentypen Beispiel 1/8/1999 1/18/1999 19990108 990108 1999.789-8 04:05:06-08:00 04:05-08:00 040506-08 Beschreibung ISO 8601 ISO 8601 ISO 8601 ISO 8601 Tabelle 8.11: Zeiteingabe Der Typ time with time zone akzeptiert alle Eingabewerte.

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

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

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

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

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

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

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

0/25 192.128/25 192.1.0/16 128.1.0.3 inet vs.168/25 192.x/y.128/25 192.2 10.x/ y.2 cidr Der Typ cidr speichert die Identität eines IP-Netzwerks. Als Eingabe werden verschiedene gebräuchliche Formate akzeptiert. um alle Oktetts im Eingabewert einzuschließen.x. wenn die Netzmaske 32 ist.1.1 128 128. Das Format. wobei x. dann ist die Netzmaske 32 und der Wert steht für einen einzelnen Host.168. cidr-Eingabe 192.x. 8.0/24 192.168.2.100. dass inet gesetzte Bits rechts von der Netzmaske zulässt und cidr nicht. um ein Netzwerk anzugeben.0/8 abbrev(cidr) 192. cidr Der Hauptunterschied zwischen den Datentypen inet und cidr ist.8.1 10 cidr-Ausgabe 192.0/24 128.1.168.2/24 10.0/16 128.1.1.x.Datentypen Das Eingabeformat für diesen Typ ist x. Es ist ein Fehler. eine Netzwerkadresse anzugeben. dann versuchen Sie die Funktionen host.8.168.0/24 10.0. mit der Ausnahme.0/24 192.0/16 128.0.0/24 192.168.0/24 10.0/16 10.0.0. die Bits rechts von der angegebenen Netzmaske gesetzt hat.168/24 192.19: Eingabebeispiele für den Typ cidr 8.2.100.168.168.100.168.168 128.x eine IP-Adresse ist und y die Anzahl der Bits in der Netzmaske.0. Wenn y ausgelassen wird. dass die Bitmaske mindestens groß genug sein muss. wobei x.2/24 10.x.128/25 192.1.x. das heißt die Hardwareadressen von Ethernetkarten (obwohl MAC-Adressen auch für andere Zwecke verwendet werden).0/25 192.und Ausgabeformate folgen den Vorgaben des Classless Internet Domain Routing Systems. Wenn /y ausgelassen wird.x. Bei der Ausgabe wird der /y-Teil weggelassen.x.x ein Netzwerk und y die Anzahl von Bits in der Netzmaske ist.1/16 10/8 Tabelle 8. dann wird es aus den Annahmen des alten klassen-orientierten Netzwerknummerierungssystems errechnet.1. text und abbrev.168.2 10.0. 8.0.8. einschließlich 127 .0.168.0/24 128. ist x. Tipp Wenn Sie die Ausgabeformate von inet oder cidr nicht mögen.1.x. Eingabe.4 macaddr Der Typ macaddr speichert MAC-Adressen.168.1 192.168.19 zeigt einige Beispiele. Tabelle 8.0.1/16 128.1/24 192.

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

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

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

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

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

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

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

mit Ausnahme der einfachsten arithmetischen und Vergleichsoperatoren und einiger ausdrücklich markierter Funktionen. 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. Die Befehle \df und \do in psql können verwendet werden. Wenn Sie auf Portierbarkeit Wert legen.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. wobei der NULL-Wert den Zustand “unbekannt” darstellt.9 9 Funktionen und Operatoren PostgreSQL bietet eine große Zahl Funktionen und Operatoren für die eingebauten Datentypen. wie in Teil V beschrieben wird. sollten Sie beachten. Operatoren anzuzeigen. dass die meisten hier beschriebenen Funktionen und Operatoren. um alle tatsächlich vorhandenen Funktionen bzw. 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 . Benutzer können auch eigene Funktionen und Operatoren definieren. 9. nicht im SQL-Standard definiert sind.

ob ein Wert NULL ist. Neben den Vergleichsoperatoren gibt es die spezielle Klausel BETWEEN. um die erste Form intern in die zweite Form umzuschreiben. 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. Alle Vergleichsoperatoren sind binäre Operatoren (mit zwei Operanden) und haben ein Ergebnis vom Typ boolean. Um zu prüfen. die sich verschieden verhalten. verwenden Sie die Klauseln 136 .1 gelistet. Es ist nicht möglich. Ausdrükke wie 1 < 2 < 3 sind ungültig (weil es keinen Operator < zum Vergleichen eines Werts vom Typ boolean mit 3 gibt). außer der CPU-Leistung. wo dies sinnvoll ist.1: Vergleichsoperatoren Anmerkung Der Operator != wird vom Parser in <> umgewandelt. die aufgewendet werden muss. Vergleichsoperatoren gibt es für alle Datentypen.2 Vergleichsoperatoren Die gewöhnlichen Vergleichsoperatoren sind vorhanden und werden in Tabelle 9. Operatoren mit den Namen != und <> zu erzeugen. 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.

Funktionen und Operatoren ausdruck IS NULL ausdruck IS NOT NULL oder die gleichbedeutenden.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.B.0 Ergebnis 5 -1 6 2 1 8 5 Tabelle 9. Ein NULL-Wert wird als der logische Wert “unbekannt” (unknown) behandelt.0 |/ 25.). Für Typen ohne weithin bekannte mathematische Definitionen für alle Varianten (z. dass ausdruck = NULL wahr ist. ob zwei unbekannte Werte gleich sind. aber nicht standardisierten Formen ausdruck ISNULL ausdruck NOTNULL Verwenden Sie nicht ausdruck = NULL. Das war das voreingestellte Verhalten in PostgreSQL 6. 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. weil NULL nicht “gleich” NULL ist. Tabelle 9. wenn ausdruck den NULL-Wert ergibt. Datum und Zeit) beschreiben wir das Verhalten in den folgenden Abschnitten.0 ^ 3. In dem Fall wird PostgreSQL Ausdrücke der Form x = NULL in x IS NULL umwandeln. 9.5 bis 7. selbst wenn ein Operand NULL ist.1. Um diese Anwendungen zu unterstützen.B. SET transform_null_equals TO ON. (Der NULL-Wert stellt einen unbekannten Wert dar und man kann nicht bestimmen.) Einige Anwendungen gehen (fälschlicherweise) davon aus. kann man den Konfigurationsparameter transform_null_equals anstellen (z.2: Mathematische Operatoren 137 .3 Mathematische Funktionen und Operatoren Mathematische Operatoren stehen für viele PostgreSQLPostgreSQL-Typen zur Verfügung. dass sie immer wahr oder falsch ergeben und niemals den NULL-Wert.

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.5) exp(1. ist der Rückgabewert von jeder Variante dieser Funktionen derselbe wie der Argumentdatentyp.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. Die Bitkettenoperanden von &.0 5! !! 5 @ -5. 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.2: Mathematische Operatoren (Forts. die mit dem Datentyp double precision umgehen.0) ceil(-42. Viele dieser Funktionen gibt es in mehreren Formen mit unterschiedlichen Argumentdatentypen.6478897565412 2.3: Bitweise Operatoren für Bitketten Tabelle 9. wie in der Tabelle gezeigt. die Genauigkeit und das Verhalten in Grenzfällen kann daher vom System abhängen.8) Ergebnis 17.4: Mathematische Funktionen 138 . In der Tabelle steht dp für double precision. Die Funktionen.0) 28.3 gezeigt. die nicht kleiner als das Argument ist Radiant in Grad umwandeln Potenzierung Beispiel abs(-17.4 zeigt die verfügbaren mathematischen Funktionen. sind meistens mit den Funktionen der C-Bibliothek des Betriebssystems implementiert. Wenn nichts anderes angegeben wurde.4 3 -42 dp dp degrees(0. | und # müssen jeweils die gleiche Länge haben.) Die bitweisen Operatoren gibt es auch für die Bitkettentypen bit und bit varying. 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.4) cbrt(27.71828182845905 Tabelle 9. wie in Tabelle 9. Beim Bitschieben wird die ursprüngliche Länge der Bitkette erhalten.

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

Diese Funktionen gibt es auch mit der normalen Syntax für Funktionsaufrufe. SQL definiert einige Funktionen mit spezieller Syntax. 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. Wenn nicht anders angegeben.Kapitel 9 9. character varying und text gemeint.6: SQL-Zeichenkettenfunktionen und -operatoren 140 . Es gibt auch vordefinierte Konversionen. 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.6.4 Zeichenkettenfunktionen und -operatoren Dieser Abschnitt beschreibt Funktionen und Operatoren zur Auswertung und Manipulation von Zeichenketten.$') 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. Im Allgemeinen kann man die hier beschriebenen Funktionen auch mit anderen Datentypen verwenden. (Siehe Tabelle 9. Einzelheiten sehen Sie in Tabelle 9. die nur aus zeichen (als Vorgabe ein Leerzeichen) besteht.8. sind alle gelisteten Funktionen für alle Typen verfügbar. wo bestimmte Schlüsselwörter anstatt Kommas verwendet werden. von Anfang/Ende/beiden Enden von string mas oma text Tom upper(string) text in Großbuchstaben umwandeln upper('tom') TOM Tabelle 9.. Konversionen können mit CREATE CONVERSION erzeugt werden.7. um die Argumente zu trennen. Einige Funktionen gibt es auch direkt für die Bitkettentypen. wobei die Werte dann automatisch in eine Zeichenkettendarstellung umgewandelt werden..) 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.

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

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

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.) 143 .

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.8: Eingebaute Konversionen (Forts.) 144 .

Diese Funktionen gibt es auch mit der normalen Syntax für Funktionsaufrufe.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. SQL definiert einige Funktionen mit spezieller Syntax.5 Funktionen und Operatoren für binäre Daten Dieser Abschnitt beschreibt Funktionen und Operatoren zur Bearbeitung von Werten des Typs bytea. gefolgt von _to_.) a. Die Konversionsnamen folgen einem einheitlichen Schema: Der offizielle Name der Quellkodierung mit allen nicht alphanumerischen Zeichen durch Unterstriche ersetzt.8: Eingebaute Konversionen (Forts.9. (Siehe Tabelle 9. um die Argumente zu trennen. 9. Einzelheiten sehen Sie in Tabelle 9.10. gefolgt vom auf gleiche Weise umgewandelten Zielkodierungsnamen. wo bestimmte Schlüsselwörter anstatt Kommas verwendet werden.) 145 . Daher könnten die Namen von den gebräuchlichen Kodierungsnamen abweichen.

die Mustervergleiche mit regulären Ausdrücken entweder nach SQL99 oder POSIX durchführen kann. escape.9: SQL-Funktionen und -Operatoren für binäre Daten Weitere Funktionen zur Zeichenkettenmanipulation sind in Tabelle 9. Tipp Wenn sie Anforderungen für Mustervergleiche haben. die diese Fähigkeiten überschreiten. die 00456'. hex. encode('123\\0 00456'::bytea.6 Mustervergleiche Es gibt drei verschiedene Möglichkeiten. typ text) Ergebnistyp bytea Beschränkung Entfernt die längste Datenkette. Einige davon werden intern verwendet. sollten Sie das Schreiben einer benutzerdefinierten Funktion in Perl oder Tcl in Betracht ziehen.10 aufgeführt. Funktion btrim(daten bytea bytes bytea) length(daten) decode(daten text. zuvor mit encode kodiert wurden. 146 . Parametertyp ist genauso wie bei encode. um die SQL-Standard-Funktionen aus Tabelle 9. vom Anfang und Ende von daten. 'escape') 123\000456 Tabelle 9. Anzahl Bytes in Daten Beispiel btrim('\\000tr im\\000'::byte a. vom Anfang und Ende von daten . 'escape') text Kodiert binäre Daten in eine Darstellung nur aus ASCII-Zeichen.9 zu implementieren.'\\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 steht.10: Andere Funktionen für binäre Daten 9.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. in PostgreSQL Mustervergleiche durchzuführen: der herkömmliche SQL-Operator LIKE. Tom Tabelle 9. Außerdem gibt es die Funktion substring. die nur aus Bytes in bytes besteht. Unterstützte Typen sind: base64. der neuere SQL99-Operator SIMILAR TO und reguläre Ausdrücke nach POSIX. typ text) encode(daten bytea.

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

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

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

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

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

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

) Quartal Monat in römischen Zahlen (I-XII.d.u.) Auf alle Muster können bestimmte Abänderungen angewendet werden.) Woche im Jahr (1-53) (Die erste Woche fängt am ersten Tag des Jahres an. i=Januar) (Kleinbuchstaben) Zeitzonenname (Großbuchstaben) Zeitzonenname (Kleinbuchstaben) Tabelle 9.) ISO-Wochennummer (Der erste Donnerstag des neuen Jahres ist in Woche Nummer 1. Januar 4712 v. Sonntag ist 1) Woche im Monat (1-5) (Die erste Woche fängt am ersten Tag des Monats an.Z.C.c.14 zeigt die Abänderungsmuster für die Formatierung von Datum und Zeit. I=Januar) (Großbuchstaben) Monat in römischen Zahlen (i-xii. oder AD oder A. 153 . englische Angabe der Zeitrechnung (Großbuchstaben) bc oder b. Zum Beispiel wäre FMMonth das Muster Month mit der Abänderung FM.Funktionen und Operatoren Muster Y Beschreibung die letzte Ziffer des Jahres BC oder B. um ihr Verhalten zu verändern.13: Mustervorlagen für die Formatierung von Datum/Zeit (Forts.) Jahrhundert (2 Ziffern) Julianischer Tag (Tage seit 1. Tabelle 9. oder ad oder a. 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.D.

Um drei Millisekunden zu erhalten. 'SS:MS') nicht 3 Millisekunden.MS. Zum Beispiel (mit dem Jahr 20000): to_date('200001131'. sondern 300. (Komma) Beschreibung Wert mit der angegebenen Anzahl von Ziffern Wert mit führenden Nullen Punkt zur Trennung von Nachkommastellen Komma als Tausendergruppierung Tabelle 9. 12 Minuten und 2 Sekunden + 20 Millisekunden + 1230 Mikrosekunden = 2. Zum Beispiel ergibt to_timestamp('12:3'.15: Mustervorlagen für die Formatierung von numerischen Werten 154 . ansonsten werden immer vier Ziffern als das Jahr genommen.US') ergibt 15 Stunden. ❏ to_timestamp und to_date ignorieren Folgen von mehreren Leerzeichen im Eingabetext. zum Beispiel '\\"YYYY Month\\"'. weil der Backslash schon eine besondere Bedeutung in Zeichenkettenkonstanten hat.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. wenn Sie Jahreszahlen mit mehr als vier Ziffern verwenden. ❏ 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. dass Zeichen als eins der Muster verwendet werden. So wird zum Beispiel in '"Hello Year "YYYY' das YYYY durch das Jahr ersetzt. weil die Umwandlung 12 + 0.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. ❏ Normaler Text kann in Mustervorlagen für to_char stehen und wird unverändert übernommen. aber spiel: to_timestamp('2000 JUN'. Hier ist ein komplexeres Beispiel: to_timestamp('15:12:02. 'HH:MI:SS. wie to_date('20000-1131'. 'YYYY MON') ist korrekt.001230'. was ansonsten verwendet wird. 'YYYY-MMDD') oder to_date('20000Nov31'. nicht aber das einzelne Y in Year. was als 12 + 0. dass bei der Mustervorlage SS:MS die Eingabewerte 12:3.3 Sekunden zählt. die zur Formatierung von numerischen Werten zur Verfügung stehen. ❏ Wenn Sie ein Anführungszeichen im Ergebnis haben wollen. wenn die Option FX nicht verwendet wird. müssen Sie einen Backslash davor stellen. (Punkt) . Das bedeutet. setzen Sie stattdessen ein nichtnumerisches Trennzeichen nach das Jahr.003 Sekunden gezählt wird. Nach dem YYYY muss ein nichtnumerisches Zeichen oder Muster stehen. muss man 12:003 schreiben. Sie können eine Teilzeichenkette in Anführungszeichen setzen.020.003 = 12. Tabelle 9. 'FXYYYY MON') ergibt einen Fehler.15 zeigt die Muster. 12:30 und 12:300 alle die gleiche Anzahl Millisekunden ergeben. 'YYYYMonDD'). um dem Ergebnis eines Musters eine feste Länge zu geben. 'YYYYMMDD') wird als 4-ziffriges Jahr interpretiert.021230 Sekunden.) ❏ Die Umwandlungen mit YYYY von Text in timestamp oder date hat eine Einschränkung. (Sie müssen zwei Backslashes eingeben. Zum Beito_timestamp('2000 JUN'. weil to_timestamp nur ein Leerzeichen erwartet. FX muss das erste Element in der Mustervorlage sein. Muster 9 0 . um zu verhindern.

aber to_char(-12.1' ' 0012. SG und TH sind PostgreSQL-Erweiterungen. 'Day. 06 05:39:18' 'Tuesday. 'S9999') ergibt ' -12'.9') to_char(485.15: Mustervorlagen für die Formatierung von numerischen Werten (Forts. '99.485' ' 1 485' ' 148. Wenn keine Ziffer verfügbar ist. wie 9en vorhanden sind.99') to_char(0. 6 ' -. FMDD HH12:MI:SS') to_char(-0. zum Beispiel.1.99') to_char(-0. to_char unterstützt nicht die Verwendung von V mit einen Dezimalpunkt. DD to_char(current_timestamp. 'MI9999') ergibt '. 'FMDay. (Zum Beispiel ist 99.0' '0012' ' 485' '-485' ' 4 8 5' ' 1. Ausdruck to_char(current_timestamp.1' ' 0. dass 9 vor MI steht. wobei n die Anzahl der Ziffern nach V ist. to_char(-12. 'FM9. Die Oracle-Implementierung erlaubt nicht die Verwendung von MI vor 9. '999. '999') to_char(485.1. wie die Funktion to_char verwendet werden kann.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.10' '-. ❏ TH funktioniert nicht mit Werten unter null oder mit Zahlen mit Bruchteilen. 'FM9990999. '9 9 9') to_char(1485.16: Beispiele für to_char 155 .999') to_char(1485.9') to_char(12.9') to_char(12. '999') to_char(-485.500' 05:39:18' Tabelle 9.12'.) ❏ Verwendungshinweise zur Formatierung von numerischen Werten: ❏ Ein mit SG. '9G999') to_char(148.9V99 nicht erlaubt. '9. ❏ V multipliziert den Eingabewert mit 10^n.5.16 zeigt einige Beispiele.) Tabelle 9. ❏ PL. '0.999') HH12:MI:SS') Ergebnis 'Tuesday . '9990999.1. dann wird ein Leerzeichen ausgegeben. ❏ 9 ergibt einen Wert mit der gleichen Zahl von Ziffern. sondern erfordert. PL oder MI formatiertes Vorzeichen steht nicht direkt neben der Zahl.

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

8.18: Funktionen für Datum/Zeit 157 . siehe Abschnitt 9.0 00126 2001 EST Tabelle 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. siehe Abschnitt 9. siehe Abschnitt 9.4 timeofday() date_trunc('hour'.1 Teilfeld ermitteln.Funktionen und Operatoren Operator * / Beispiel interval '1 hour' * int '3' interval '1 hour' / int '3' Ergebnis interval '03:00' interval '00:20' Tabelle 9.8.4 Beispiel Ergebnis age(timestamp '1957. siehe auch Abschnitt 9.8.) Funktion age(timestamp) Ergebnistyp interval Beschreibung Subtraktion vom heutigen Datum Subtraktion heutiges Datum. interval '2 years 3 mit extract). timestamp) date_part(text . timestamp '2001-02mit extract).4 aktuelle Zeit mit Datum. siehe Abschnitt 9. siehe Abschnitt months') 9.8. siehe Abschnitt 9.8. siehe Abschnitt 9.8.1 auf endlichen Wert prüfen (ungleich infinity) auf endlichen Wert prüfen (ungleich infinity) aktuelle Zeit.4 aktuelle Zeit mit Datum (gleichbedeutend mit current_timestamp).1 Teilfeld ermitteln (gleichbedeutend date_part('month'.1 auf angegebene Genauigkeit abschneiden.8. timestamp) current_date current_time current_timest amp date_part(text . siehe Abschnitt 9.8. timestamp '1957-0613') 43 years 9 mons 27 days age(timestamp.4 aktuelle Zeit mit Datum. siehe auch Abschnitt 9.17: Operatoren für Datum/Zeit (Forts. siehe Abschnitt 16 20:38:40') 9.8.8. siehe auch Abschnitt 9.2 Teilfeld ermitteln. 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'.8. interval) date_trunc(tex t.43 years 8 06-13') mons 3 days age('2001-04-10'.8.4 aktuelle Zeit mit Datum.4 aktuelle Zeit.

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

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

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

TIMESTAMP '2001-02-16 20:38:40'). Tabelle 9.) feld bestimmt. Ergebnis: 2001-02-16 20:00:00+00 SELECT date_trunc('year'. 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.3 AT TIME ZONE Die Klausel AT TIME ZONE ermöglicht die Umrechnung von Zeitangaben in andere Zeitzonen.19: Varianten von AT TIME ZONE 161 . Gültige Werte für feld sind: microseconds milliseconds second minute hour day month year decade century millennium Beispiele: SELECT date_trunc('hour'. auf null gesetzt sind (oder eins.8. INTERVAL '4 hours 3 minutes'). bei Tag und Monat). date_trunc('feld'. quelle) quelle ist ein Wertausdruck vom Typ timestamp.Funktionen und Operatoren SELECT date_part('hour'. TIMESTAMP '2001-02-16 20:38:40'). Ergebnis: 2001-01-01 00:00:00+00 9.8.19 zeigt ihre Varianten. die kleiner als das angegebene sind. (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. wobei alle Felder. auf welche Genauigkeit der Wert abgeschnitten werden soll. Der Rückgabewert ist vom Typ timestamp. Ergebnis: 4 9.

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

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

20: Geometrische Operatoren 164 .0)' box '((0.1).1))' ?-| lseg '((0. 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.0).0).0)' ## lseg '((2.(1.0).0).1))' * point '(2.1))' && box '((0.1)' << circle '((5.9 Geometrische Funktionen und Operatoren Die geometrischen Typen point.-1).10)' polygon '((0.1)' <^ circle '((0.0).5).2))' / point '(2.1))' .0).(1.(1. box.0).2))' circle '((0.1)' circle '((0.(2.0).0).0).0).1))' # '((1.(0.0))' ?# box '((-2.0).0).-1))' # '((1.(-1.1)' >> circle '((0.1)' ?| point '(0.0))' Tabelle 9.2))' box '((0.21 und Tabelle 9.(1.0).0))' ?|| lseg '((1.(1.1)' >^ circle '((0.(2.(3.0).0.point '(2.0))' @-@ path '((0.22 gezeigt werden.(0.0)' box '((0.0).0)' lseg '((0.0))' point '(0.0)' '((1.2).0)' box '((0.0).(1.1).0).3))' &> box '((0.(0.(2.0)' ?.1).(1.(2. line.2))' box '((0.0).(1.2))' point '(1.1)' lseg '((-1. Tabelle 9.0.0.0))' point '(0.point '(0.(2.1)' <-> circle '((5. lseg.(-1.0).Kapitel 9 9. path.1))' + point '(2.1))' ~= polygon '((1.1)' @ circle '((0.(1. polygon und circle haben eine große Zahl zugehöriger Funktionen und Operatoren.0).2))' box '((0.0).0).0).1)' circle '((0.0).0).1))' &< box '((0.(0.0).1)' circle '((0.(1. welche in Tabelle 9.0.0)' lseg '((-1.0).1)' circle '((5.2)' @@ circle '((0.(1.2))' point '(1.2).5).(-1.20.

(0.0)') box(point '(0.0).0)') width(box '((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.5).0).(2.0)') point(lseg '((-1.(1.0)]') length(path '((1.21: Geometrische Funktionen Funktion box(circle) box(point.(1.1).0).2))') point(polygon '((0.(2. point) box(polygon) circle(box) circle(point.0))') point(circle '((0.(1.1))'.1).0). point '(1.1).1).1).(2.1).(1.0).(1.0).Funktionen und Operatoren Funktion area(objekt) box(box.0). 2.(1.1).0).2.0.1))') Pfad in geschlossenen umwandeln popen(path Pfad in offenen umwandeln Radius des Kreises Breite des Rechtecks Tabelle 9. 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.0))') radius(circle '((0.0)') height(box '((0.(1.0).2))') center(box '((0.0)]') popen(path '((0.0))') '[(0.(1.0).0).0)') path(polygon '((0.-2).2.0).(1.0))') circle(box '((0. lseg '((-2.2.(2.0).1))') circle(point '(0.box '((0.2))') diameter(circle '((0.0)]') npoints(polygon '((1.1).1))') box(box '((0.0).(1.(1.0))'.(1.0).1).5.0)'.0))') Tabelle 9.0)'.(2.1)') box(polygon '((0.0).(1.0))') isopen(path '[(0.(2.0))') lseg(point '(-1.(2.22: Geometrische Typumwandlungsfunktionen 165 .0).0)'.(1.2.0).(1.(1.0).(2.(1.(2. point '(1.0).0) lseg(box '((-1.(2.0))') npoints(path '[(0.1))') isclosed(path '((0. point) path(polygon) point(circle) point(lseg.0).

5' < inet '192.0).p eine Spalte vom Typ point ist.5' inet '192. Wenn zum Beispiel t.0))') Tabelle 9. >> und >>= überprüfen.1/24' <<= inet '192.5' inet '192. Funktion broadcast(inet) host(inet) Ergebnistyp Beschreibung inet text Beispiel Ergebnis Broadcast-Adresse des Netzwerks IP-Adresse als Text auslesen broadcast('192. circle Pfad in Polygon polygon(path '((0.1.168.5' >= inet '192.168.4' inet '192.23: Operatoren für cidr und inet Tabelle 9.1/24' >>= inet '192.1/24' Tabelle 9. Die Funktionen host.168.5 Tabelle 9.168.168.1.168.1.1.1))') Kreis in 12-Punkte Polygon polygon(circle '((0.0).(1.1).0)') '((0. text und abbrev bieten in der Hauptsache alternative Ausgabeformate für Werte dieser Typen.168.168.1 192.1/24' inet '192. 9.1/24' >> inet '192. Sie können einen Textwert mit der normalen Umwandlungssyntax in inet umwandeln: inet(ausdruck) oder spaltennamen::inet. ob ein Subnetz in einem anderen Netz enthalten ist.5' <= inet '192.168.1.1.168.1. dann ergibt SELECT p[0] FROM t die X-Koordinate und UPDATE t SET p[1] = . die für die Typen cidr und inet zur Verfügung stehen.5' inet '192. <<=.1.168.168. die für die Typen cidr und inet zur Verfügung stehen. Sie betrachten dafür nur den Netzwerkteil der beiden Adressen und ignorieren einen möglichen Host-Teil.168.1.5' <> inet '192.1/24' inet'192.0)') Kreis in npkte-Punkte-Polygon polygon(12.168.4' inet '192. Ebenso können Werte vom Typ box und lseg als Array zweier Werte vom Typ point behandelt werden.5' << inet '192.1.23 zeigt die Operatoren.0).5/ 24') 192.168.255 .1.1.168.168.168.24 zeigt die Funktionen.1.1.1.10 Funktionen für Netzwerkadresstypen Tabelle 9.. ändert die Y-Koordinate.168.168.168.2.24: Funktionen für cidr und inet 166 ..1.5' > inet '192. circle) polygon(path) Ergebnistyp polygon polygon polygon polygon Beschreibung Beispiel Rechteck in 4-Punkte-Polygon polygon(box '((0.2.) Es ist möglich. 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.1.0). auf die beiden Zahlen in einem Wert des Typs point zuzugreifen. als ob point ein Array mit Indizes 0 und 1 wäre.168.Kapitel 9 Funktion polygon(box) polygon(circle) polygon(npkte.168.(2.22: Geometrische Typumwandlungsfunktionen (Forts.6' inet '192. Die Operatoren <<.5/24') /24 host('192.168.(1.5' inet '192.

168 192. bigint) setval(text.1/16 text(inet IP-Adresse und Netzmaskenlänge als Text '192.5 255.5/ 32 10. die für den Typ macaddr zur Verfügung stehen.1. Funktion nextval(text) currval(text) setval(text. Damit kann der übrig gebliebene Präfix mit einem Hersteller in Verbindung gebracht werden.168.26 gelistet sind. um eine solche Assoziierungstabelle zu erstellen und zu pflegen. Das Verzeichnis contrib/mac in der Quelltext-Distribution enthält einige Hilfsmittel.255.25: Funktionen für macaddr Der Typ macaddr hat auch die normalen Vergleichsoperatoren (>.168.1.1.1. bigint.) zur lexikographischen Sortierung.5/ .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.0/16') Tabelle 9. 9. 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. <= usw.5') auslesen abbrev(inet) text abgekürztes Ausgabeformat als Text abbrev(cidr '10.24: Funktionen für cidr und inet (Forts.26: Sequenzfunktionen 167 .25 zeigt die Funktionen.16) 16 Netzmaske des Netzwerks netmask('192.0.) Tabelle 9.168.255.11 Funktionen zur Bearbeitung von Sequenzen Dieser Abschnitt beschreibt die Funktion von PostgreSQL zur Verwendung mit Sequenzobjekten. um laufende Werte aus Sequenzobjekten zu erhalten. Sequenzobjekte (auch Sequenzgeneratoren oder einfach Sequenzen genannt) sind besondere Tabellen mit einer einzigen Zeile.168. um für die Zeilen einer Tabelle laufende Nummern zur eindeutigen Identifikation zu erzeugen.1.1.168. der zuletzt durch nextval erzeugt wurde aktuellen Wert der Sequenz setzen aktuellen Wert der Sequenz und den Parameter is_called setzen Tabelle 9.0/ /24') 24 192.1.168.5 24 /24') set_masklen('192.1. bieten einfache und für den Mehrbenutzerbetrieb geeignete Methoden.5/24'. Die Funktion trunc(macaddr) ergibt die MAC-Adresse mit den letzten 3 Bytes auf null gesetzt.0 /24') ermitteln Netzwerkteil der Adresse auslesen network('192. boolean) Ergebnistyp bigint bigint bigint bigint Beschreibung Sequenz erhöhen und neuen Wert zurückgeben Wert.1. welche in Tabelle 9. die mit dem Befehl CREATE SEQUENCE erzeugt werden.168. Die Sequenzfunktionen.5 192.Funktionen und Operatoren Funktion masklen(inet) set_masklen(inet. Ein Sequenzobjekt wird normalerweise verwendet.

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

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

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

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

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

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

31 listet Funktionen. pg_get_viewdef. (Beachten Sie. eines Constraints erforderlich ist. pg_get_indexdef bzw. Wenn Sie ein Objekt dem Namen nach überprüfen wollen. pg_type_is_visible. 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.31: Systemkataloginformationsfunktionen Die in Tabelle 9.Kapitel 9 SELECT relname FROM pg_class WHERE pg_table_is_visible(oid). einen unqualifizierten Namen auf diese Art zu überprüfen. pg_function_is_visible.32 gezeigten Funktionen ermitteln Kommentare. regprocedure oder regoperator) verwenden. zum Beispiel: SELECT pg_type_is_visible('myschema. können Sie die OID-Aliastypen (regclass. Alle diese Funktionen verlangen die OID. Gegenwärtig funktioniert pg_get_userbyid ermittelt den Benutzernamen. pg_get_ruledef. Funktionen. denn wenn der Name überhaupt erkannt würde. Ein NULL-Wert wird zurückgegeben. pg_operator_ is_visible und pg_opclass_is_visible führen die gleiche Art von Sichtbarkeitsprüfung für Daten- typen. welche vorher mit dem Befehl COMMENT erzeugt wurden. Bei Operatorklassen wird sowohl der Name als auch die zugehörige Indexmethode betrachtet. die Informationen aus den Systemkatalogen herausholen. wenn kein passender Kommentar für die angegebenen Parameter gefunden werden konnte. um das zu überprüfende Objekt zu identifizieren. Beachten Sie.) pg_get_constraintdef nur mit Fremdschlüssel-Constraints.widget'::regtype). dass es keinen Sinn macht. Tabelle 9. der zur Erzeugung einer Sicht. eines Index bzw. wenn es kein anderes Objekt mit dem gleichen Namen und den gleichen Argumentdatentypen vorher im Pfad gibt. der zur angegebenen Benutzernummer gehört. Operatoren bzw. regtype. dass dies eine Wiederzusammensetzung ist und nicht der Originaltext des Befehls. Bei Funktionen und Operatoren gilt. 174 . einer Regel. 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.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. muss er auch sichtbar sein. Operatorklassen aus. pg_get_constraintdef rekonstruie- ren den Befehl. ein Objekt im Suchpfad ist sichtbar.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Die Kosten der Planknoten können mit Konfigurationsparametern eingestellt werden (beschrieben in Abschnitt 16. (Welche Anfragen welche Arten von Index verwenden können.4). Sie sollten also die Zeit Ihrer Anfrage mit und ohne Index messen. dass die Kostenschätzungen falsch sind.Indexe gung in der Anfrage nicht auf den Index passt. Möglicherweise kann man da Abhilfe schaffen. Die Gesamtkosten werden aus den Kosten pro Zeile jedes Planknotens multipliziert mit der Schätzung.) ❏ 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. Wenn es Ihnen nicht gelingt. dass die Kostenschätzungen realistisch werden. ❏ Wenn es sich herausstellt. indem man die Parameter zur Statistikeinholung ändert (siehe Referenz von ALTER TABLE). Eine ungenaue Schätzung der Zeilenzahl kommt von unzureichenden Statistiken. 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. wie viele Zeilen der Planknoten ergeben wird (englisch selectivity estimate). 199 . die Parameter so einzustellen. gibt es wiederum zwei Möglichkeiten. dann werden Sie womöglich als letzten Ausweg die Verwendung der Indexe ausdrücklich erzwingen müssen. Vielleicht sollten Sie sich auch mit den PostgreSQL-Entwicklern in Verbindung setzen. um die Angelegenheit zu untersuchen. wurde in den vorangegangenen Abschnitten erklärt.

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

VAKAT VAKAT .

Im Unterverzeichnis doc in der Distribution gibt es mehrere plattformspezifische FAQ-Dokumente.2 Voraussetzungen Generell sollte PostgreSQL auf allen modernen Unix-kompatiblen Plattformen laufen können.14 14 Installationsanweisungen Dieses Dokument Kapitel beschreibt die Installation von PostgreSQL von der Quellcodedistribution. Kapitels.7 aufgezählt.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.1 Kurzversion . wenn es Probleme gibt. Die Plattformen. in denen Sie nachschauen sollten. 14./configure gmake su gmake install adduser postgres mkdir /usr/local/pgsql/data chown postgres /usr/local/pgsql/data su . sind unten in Abschnitt 14. 14. 221 . auf denen zum Zeitpunkt der Veröffentlichung getestet wurde.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Kapitel 14 236 .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Kapitel 16 266 .

auf dem der Server läuft.1 Datenbankbenutzer Datenbankbenutzer sind vollständig getrennt von Betriebssystembenutzern. Um einen bestehenden Benutzer zu entfernen. aber das ist nicht erforderlich. 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. Datenbankbenutzer gelten global in der gesamten Datenbankclusterinstallation (und nicht nur in einzelnen Datenbanken). name folgt den Namen für SQL-Bezeichner: entweder ohne Verzierung und Sonderzeichen oder in Anführungszeichen. verwenden Sie den SQL-Befehl CREATE USER: CREATE USER name. Es mag praktisch sein. 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 einen Benutzer zu erzeugen. verwaltet. Dieses Kapitel beschreibt. Diese Benutzer sind getrennt von den Benutzern.17 17 Datenbankbenutzer und Privilegien Jeder Datenbankcluster enthält Datenbankbenutzer. um zu kontrollieren. 17. enthält ein frisch initialisiertes System immer einen vordefinierten Benutzer. 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. Benutzer sind die Eigentümer von Datenbankobjekten (zum Beispiel Tabellen) und können anderen Benutzern Privilegien für diese Objekte zuweisen. der den 267 . die das Betriebssystem. Der Bequemlichkeit halber gibt es die Programme createuser und dropuser. und führt Sie in das Privilegiensystem ein. wie man Benutzer erzeugt und verwaltet. eine Übereinstimmung zu erhalten. verwenden Sie den analogen Befehl DROP USER: DROP USER name.

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

.

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

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

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

) pg_statio_user_seque nces Wie pg_statio_all_sequences. die die selben Statistikfunktionen verwenden. aber nur für Systemtabellen. pg_statio_sys_sequen Wie pg_statio_all_sequences. aber nur für Indexe von Systemtabellen.und Indexstatistiken verlangen die OID einer Tabelle oder eines Index. pg_statio_all_sequen Für jedes Sequenzobjekt in der aktuellen Datenbank. um zu ermitteln. Diese Funktionen sind in Tabelle 23. 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. welche Indexe verwendet werden und wie effektiv sie sind. Die Funktionen für Tabellen. die den Standardsichten zugrunde liegen. dass diese Funktionen nur über Tabellen und Indexe in der aktuellen Datenbank berichten können. Wie pg_statio_all_indexes. Wie pg_statio_all_tables. die Anzahl der gelesenen Diskblöcke und s Puffertreffer für diesen Index.) Die Funktionen. die Anzahl der Puffertreffer. (Gegenwärtig sind ces keine Systemsequenzen definiert. Wenn Sie die Statistiken auf andere Weise betrachten wollen.2: Statistikfunktionen 310 . Wenn die Anzahl der tatsächlich gelesenen Diskblöcke wesentlich kleiner ist als die Anzahl der Puffertreffer. die Anzahl der gelesenen Diskblöcke und Puffertreffer für alle Indexe dieser Tabelle. Die Funktionen. die über Serverprozesse berichten. um die Effektivität des Puffercache zu ermitteln. verlangen die laufende Nummer eines Serverprozesses als Argument. also ist diese Sicht immer leer.2 aufgelistet. Wie pg_statio_all_tables. aber nur mit Benutzersequenzen.1: Standard-Statistiksichten (Forts.) Die indexspezifischen Statistiken sind nützlich. aber nur mit Systemsequenzen. (Beachten Sie. haben die Datenbank-OID als Argument. können Sie selbst Anfragen schreiben. 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. pg_statio_sys_indexe s pg_statio_user_index es Wie pg_statio_all_indexes. aber nur für Indexe von Benutzertabellen. 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. Die pg_statio_-Sichten sind hauptsächlich nützlich. die Datenbankstatistiken berichten. Tabelle 23. die Gesamtzahl der aus dieser Tabelle gelesenen Diskblöcke. dann erfüllt der Cache die meisten Leseanfragen ohne einen Kernelaufruf zu benötigen. die Anzahl gelesener Diskblöcke ces und Puffertreffer in dieser Sequenz. aber nur für Benutzertabellen.Kapitel 23 Sichtname pg_statio_all_tables Beschreibung Für jede Tabelle in der aktuellen Datenbank.

den Index oder die Datenbank. pg_stat_get_backend_activity(s. wenn es ein Index ist.backendid) AS procpid. 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.Überwachung der Datenbankaktivität Funktion pg_stat_get_numscans(oid) Ergebnistyp bigint Beschreibung Wenn das Argument eine Tabelle ist. 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.2: Statistikfunktionen (Forts. weil der Kernel auch noch einen Cache hat. die Anzahl der von sequenziellen Scans gelesenen Tupel. 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. 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).) 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. die Anzahl ausgeführter Indexscans Wenn das Argument eine Tabelle ist.backendid) AS current_query FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s. wenn es ein Index ist. Um zum Beispiel die PID und die aktuelle Anfrage für jeden Serverprozess anzuzeigen. Die Funktion pg_stat_get_backend_idset bietet einen praktische Möglichkeit. die Anzahl der von sequenziellen Scans gelesenen gültigen (nicht abgelaufenen) Tabellentupel. Siehe Verwendungsbeispiel im Text. die Anzahl der von Indexscans gelesenen Indextupel Wenn das Argument eine Tabelle ist. eine Zeile für jeden aktiven Serverprozess zu erzeugen. aber die Anzahl der eigentlichen physikalischen Lesevorgänge ist normalerweise niedriger. 311 .

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

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

.

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

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

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

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

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

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

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

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

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

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

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

.

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

VAKAT VAKAT .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

mit dem Clientprogramme mit dem PostgreSQL-Server kommunizieren können.29 29 pgtcl: Die TclBindungsbibliothek pgtcl ist ein Tcl-Paket.1 gibt einen Überblick über die in pgtcl verfügbaren Befehle. 29. Diese Befehle sind im Einzelnen auf den folgenden Seiten beschrieben.1 Überblick Tabelle 29. Es stellt die meisten Funktionen von libpq für Tcl-Skripts zur Verfügung.1: pgtcl-Befehle 375 . 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.

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

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

Argumente verbindung Die Handle der zu schließenden Verbindung. Argumente Keine 378 .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. Rückgabewert Keiner pg_conndefaults Name pg_conndefaults -.eine Verbindung zum Server schließen Synopsis pg_disconnect verbindung Beschreibung pg_disconnect schließt eine Verbindung zum PostgreSQL-Server.Kapitel 29 pg_disconnect Name pg_disconnect -.

aber keinen Tcl-Fehler in pg_exec. auf der der Befehl ausgeführt werden soll. dass das Wegbleiben eines Tcl-Fehlers nicht anzeigt. um die Ergebnisse des Befehls zu ermitteln. wenn pgtcl keine Antwort vom Server erhalten konnte. Ansonsten wird ein Ergebnisobjekt erzeugt und eine Handle dafür zurückgegeben.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. 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. Die Handles für Befehlsergebnisse bestehen aus der Verbindungshandle gefolgt von einem Punkt und der Ergebnisnummer. Argumente verbindung Die Handle der Verbindung. Rückgabewert Eine Ergebnishandle. Eine vom Server zurückgegebene Fehlermeldung ergibt ein Ergebnisobjekt mit einem Fehlerstatus. Beachten Sie. pg_exec Name pg_exec -.Bindungsbibliothek Rückgabewert Das Ergebnis ist eine Liste. dass der SQL-Befehl erfolgreich war.pgtcl: Die Tcl. Diese Handle kann an pg_result übergeben werden. Ein Tcl-Fehler wird erzeugt. befehlstext Der auszuführende SQL-Befehl. die die möglichen Verbindungsparameter und deren aktuelle Vorgabewerte beschreibt. 379 .

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

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

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

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

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

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

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

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

Kapitel 29 deskriptor Ein Deskriptor für das Large Object von pg_lo_open. die das Large-Object-Segment enthalten soll. deskriptor Ein Deskriptor für das Large Object von pg_lo_open. länge Die Höchstzahl der zu lesenden Bytes. Rückgabewert Keiner 388 . in der das Large Object liegt. 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. Argumente verbindung Die Handle einer Datenbankverbindung. bufVar Der Name einer Puffervariablen.

Bindungsbibliothek pg_lo_write Name pg_lo_write -. deskriptor Ein Deskriptor für das Large Object von pg_lo_open. buf Eine Zeichenkette (kein Variablenname). länge Die Höchstzahl der zu schreibenden Bytes. die die zu schreibenden Daten enthält. in der das Large Object liegt.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.pgtcl: Die Tcl. Argumente verbindung Die Handle einer Datenbankverbindung. 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 .

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

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

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

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. 29. Beispiel 29.pgtcl: Die Tcl. Rückgabewert Keiner Hinweise pg_lo_export muss in einem BEGIN /COMMIT-Transaktionsblock aufgerufen werden.1 zeigt ein kleines Beispiel. wie die pgtcl-Befehle verwendet werden. in welche Datei die Daten exportiert werden sollen.4 Beispielprogramm Beispiel 29.Bindungsbibliothek Gibt an."] 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 .

.

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

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

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

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

} sqlerrm. long sqlerrd[6]. char sqlerrmc[70]. /* 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]. /* 0: leer /* 1: OID der aktuellen Zeile. Der Text endet mit der Zeilennummer in der Quelldatei. char sqlerrp[8]. 399 . Wenn es größer als null ist. ist das ein ernster Fehler. wie eine Datenbankdefinition. ist das ein normaler Fehler. */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ (Viele der leeren Felder könnten in einer zukünftigen Version verwendet werden. wenn angebracht /* 2: Anzahl betroffener Zeilen bei INSERT. struct { int sqlerrml.sqlcode 0 sein (ECPG_NO_ERROR). } sqlca.sqlcode kleiner als null ist.) Wenn beim letzten SQL-Befehl kein Fehler auftrat. die nicht mit der Anfrage übereinstimmt. der den Fehler beschreibt.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]. Wenn sqlca. als wenn eine Tabelle die gewünschte Zeile nicht enthält. sqlca. wird sqlca.sqlerrm. long sqlcode.sqlerrmc wird den Text enthalten. UPDATE /* oder DELETE Befehl /* 3: leer /* 4: leer /* 5: leer char sqlwarn[8]. long sqlabc.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

None) con2 = pg.connect('testdb'. Eine Beschreibung der genauen Bedeutung der Parameter finden Sie in Kapitel 27. SyntaxError Doppelt angegebenes Argument. None. user='bob') get_defhost Name get_defhost – ermittelt den Standardhostnamen [DV] 421 . Die Namen der Schlüsselwörter sind die. 5432. Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. die beim Alloziieren eines Objekts auftreten können) Beschreibung Diese Methode öffnet eine Verbindung zur angegebenen Datenbank auf dem angegebenen PostgreSQLServer. Die Argumente können auch mit Schlüsselwörtern angegeben werden. dann wird ein Objekt zurückgegeben.connect(dbname='testdb'. 'bob'. (zuzüglich aller Exceptions.error Ein Fehler geschah während des Verbindungsaufbaus durch pg. pg. host='localhost'. die in der Syntaxzeile stehen. None.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. 'myhost'. das eine Handle für die Datenbankverbindung ist. Beispiele import pg con1 = pg.

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

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. wenn Umgebungsvariab- len verwendet werden sollen.PyGreSQL: Die Python-Schnittstelle Beschreibung set_defhost() setzt den Standardhost für neue Verbindungen. Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht. Beschreibung get_defport() gibt den aktuell eingestellten Standardport zurück oder None. werden für zukünfige Verbindungen Umgebungsvariablen verwendet. set_defport Name set_defport – setzt den Standardport [DV] 423 . Wenn None als Parameter angegeben wird. Der vorherige Standardhost wird zurückgegeben.

Kapitel 32 Synopsis set_defport(port) Parameter port Neuer Standardport (ganze Zahl/-1). Wenn -1 als Parameter angegeben wird. 424 . Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente. dann werden für zukünfige Verbindungen Umgebungsvariablen verwendet. Rückgabetyp Ganze Zahl oder None Vorheriger Standardport. 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. Beschreibung set_defport() setzt den Standardport für neue Verbindungen.

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

Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht. oder None wenn Umgebungsvariablen verwendet werden sollen. 426 . Exceptions TypeError Falscher Argumenttyp oder zu viele Argumente.Kapitel 32 Synopsis get_deftty() Parameter Keine Rückgabetyp Zeichenkette oder None Standard-Debug-Terminal Exceptions SyntaxError Zu viele Argumente. Beschreibung get_deftty() gibt das aktuell eingestellte Standard-TTY für Debugausgaben zurück. 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.

Das vorherige Standard-TTY wird zurückgegeben.wenn Umgebungsva- riablen verwendet werden sollen.PyGreSQL: Die Python-Schnittstelle Beschreibung set_defhost() setzt das Standard-Debug-TTY für neue Verbindungen. 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. Umgebungsvariablen werden bei der Ermittlung des Rückgabewerts nicht untersucht. Wenn None als Parameter angegeben wird. dann werden für zukünftige Verbindungen Umgebungsvariablen verwendet. set_defbase Name set_defbase – setzt die Standarddatenbank [DV] 427 . Beschreibung get_defbase() gibt die aktuell eingestellte Standarddatenbank zurück oder None .

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