From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+In diesem Abschnitt wollen wir eine Reihe von Themen ansprechen, die
+bei der bisherigen Darstellung zu kurz gekommen sind. Aufgrund des
+beschränkten Platzes werden wir jedes Thema allerdings nur kurz
+ansprechen und verweisen für genauere Informationen auf die JDBC-Beschreibung
+(sie ist Bestandteil der seit dem JDK 1.2 ausgelieferten Online-Dokumentation)
+und auf weiterführende Literatur zum Thema JDBC.
+
+
+
+
+
+In Abschnitt 42.3.3
+sind wir bereits kurz auf die Verwendung von Metadaten eingegangen.
+Neben den Datenbankmetadaten gibt es die Methode getMetaData
+der Klasse ResultSet:
+
+
+Sie liefert ein Objekt vom Typ ResultSetMetaData,
+das Meta-Informationen über die Ergebnismenge zur Verfügung
+stellt. Wichtige Methoden sind:
+
+
+Mit getColumnCount
+kann die Anzahl der Spalten in der Ergebnismenge abgefragt werden.
+getColumnName
+und getTableName
+liefern den Namen der Spalte bzw. den Namen der Tabelle, zu der diese
+Spalte in der Ergebnismenge gehört, wenn man ihren numerischen
+Index angibt. Mit getColumnType
+kann der Datentyp einer Spalte abgefragt werden. Als Ergebnis wird
+eine der statischen Konstanten aus der Klasse java.sql.Types
+zurückgegeben.
+
+
+
+
+
+Mit den Escape-Kommandos wurde ein
+Feature eingeführt, das die Portierbarkeit von Datenbankanwendungen
+verbessern soll. In Anlehnung an ODBC fordert die JDBC-Spezifikation
+dazu, dass die JDBC-Treiber in der Lage sein müssen, besondere
+Zeichenfolgen in SQL-Anweisungen zu erkennen und in die spezifische
+Darstellung der jeweiligen Datenbank zu übersetzen. Auf diese
+Weise können beispielsweise Datums- und Zeitliterale portabel
+übergeben oder eingebaute Funktionen aufgerufen werden. Die Escape-Kommandos
+haben folgende Syntax:
+
+
+Am Anfang steht eine geschweifte Klammer, dann folgen der Name des
+Escape-Kommandos und mögliche Argumente, und am Ende wird das
+Kommando durch eine weitere geschweifte Klammer abgeschlossen.
+
+
+Um beispielsweise unabhängig von seiner konkreten Darstellung
+einen Datumswert einzufügen, kann das Escape-Kommando »d«
+verwendet werden. Es erwartet als Argument eine SQL-Zeichenkette im
+Format »yyyy-mm-dd« und erzeugt daraus das zur jeweiligen
+Datenbank passende Datumsliteral. In Listing 42.5
+haben wir dieses Kommando verwendet, um das Änderungsdatum der
+Datei in die Tabelle file zu schreiben.
+
+
+
+
+
+Die drei Methoden commit,
+rollback
+und setAutoCommit
+des Connection-Objekts
+steuern das Transaktionsverhalten der Datenbank:
+
+
+Nach dem Aufbauen einer JDBC-Verbindung ist die Datenbank (gemäß
+JDBC-Spezifikation) zunächst im Auto-Commit-Modus.
+Dabei gilt jede einzelne Anweisung als separate Transaktion, die nach
+Ende des Kommandos automatisch bestätigt wird. Durch Aufruf von
+setAutoCommit
+und Übergabe von false
+kann das geändert werden. Danach müssen alle Transaktionen
+explizit durch Aufruf von commit
+bestätigt bzw. durch rollback
+zurückgesetzt werden. Nach dem Abschluss einer Transaktion beginnt
+automatisch die nächste.
+
+
+Wichtig ist auch der Transaction Isolation Level,
+mit dem der Grad der Parallelität von Datenbanktransaktionen
+gesteuert wird. Je höher der Level, desto weniger Konsistenzprobleme
+können durch gleichzeitigen Zugriff mehrerer Transaktionen auf
+dieselben Daten entstehen. Um so geringer ist aber auch der Durchsatz
+bei einer großen Anzahl von gleichzeitigen Zugriffen. Transaction
+Isolation Levels werden von der Datenbank üblicherweise mit Hilfe
+von gemeinsamen und exklusiven Sperren realisiert. JDBC unterstützt
+die folgenden Levels:
+
+Mit Hilfe der beiden Methoden getTransactionIsolation
+und setTransactionIsolation
+des Connection-Objekts
+kann der aktuelle Transaction Isolation Level abgefragt bzw. verändert
+werden:
+
+
+Mit der Methode supportsTransactionIsolationLevel
+des DatabaseMetaData-Objekts
+kann abgefragt werden, ob eine Datenbank einen bestimmten Transaction
+Isolation Level unterstützt oder nicht.
+
+
+
+
+
+In den meisten Fällen braucht man keine exakte Kenntnis
+des Datentyps einer Tabellenspalte, wenn man diese abfragt. Die oben
+beschriebenen get-Methoden des
+ResultSet-Objekts
+führen geeignete Konvertierungen durch. Soll dagegen mit CREATE
+TABLE eine neue Datenbank definiert werden, muss zu jeder
+Spalte der genaue Datentyp angegeben werden. Leider unterscheiden
+sich die Datenbanken bezüglich der unterstützten Typen erheblich,
+und die CREATE TABLE-Anweisung
+ist wenig portabel. Die Klasse java.sql.Types
+listet alle JDBC-Typen auf und gibt für jeden eine symbolische
+Konstante an. Mit der Methode getTypeInfo
+der Klasse DatabaseMetaData
+kann ein ResultSet
+mit allen Typen der zugrunde liegenden Datenbank und ihren spezifischen
+Eigenschaften beschafft werden. In Tabelle 42.4
+findet sich eine Übersicht der wichtigsten SQL-Datentypen.
+
+
+
+
+
+Wie zuvor erwähnt, sind die JDBC-Objekte des Typs Connection
+und Statement
+möglicherweise kostspielig bezüglich ihres Rechenzeit- oder
+Speicherverbrauchs. Es empfiehlt sich daher, nicht unnötig viele
+von ihnen anzulegen.
+
+
+Während das bei Connection-Objekten
+einfach ist, kann es bei Statement-Objekten
+unter Umständen problematisch werden. Wird beispielsweise in
+einer Schleife mit vielen Durchläufen immer wieder eine Methode
+aufgerufen, die eine Datenbankabfrage durchführt, so stellt sich
+die Frage, woher sie das dafür erforderliche Statement-Objekt
+nehmen soll. Wird es jedesmal lokal angelegt, kann schnell der Speicher
+knapp werden. Wird es dagegen als statische oder als Klassenvariable
+angelegt, kann es zu Konflikten mit konkurrierenden Methoden kommen
+(die üblichen Probleme globaler Variablen).
+
+
+Eine gut funktionierende Lösung für dieses Problem besteht
+darin, Statement-Objekte
+auf der Connection
+zu cachen, also zwischenzuspeichern. Das kann etwa mit einer
+Queue erfolgen, in die nicht mehr benötigte Statement-Objekte
+eingestellt werden. Anstelle eines Aufrufs von createStatement
+wird dann zunächst in der Queue nachgesehen, ob ein recyclebares
+Objekt vorhanden ist, und dieses gegebenenfalls wiederverwendet. Es
+sind dann zu keinem Zeitpunkt mehr Statement-Objekte
+angelegt, als parallel benötigt werden. Natürlich
+dürfen nur Objekte in die Queue gestellt werden, die nicht mehr
+benötigt werden; ihr ResultSet
+sollte also vorher möglichst geschlossen werden. Das Statement-Objekt
+selbst darf nicht geschlossen werden, wenn es noch verwendet werden
+soll.
+
+
+Ein einfache Implementierung wird in dem folgendem Listing vorgestellt.
+Das Objekt vom Typ CachedConnection
+wird mit einem Connection-Objekt
+instanziert. Die Methoden getStatement
+und releaseStatement dienen
+dazu, Statement-Objekte
+zu beschaffen bzw. wieder freizugeben.
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 42 - Datenbankzugriffe mit JDBC
+
+
+
+
+
+42.4 Weiterführende Themen
+
+
+
+
+42.4.1 Metadaten
+
+
+
+
+
+
+
+
+
+
+ResultSetMetaData getMetaData()
+
+
+
+java.sql.ResultSet
+
+
+
+
+
+
+
+
+
+int getColumnCount()
+
+String getColumnName(int column)
+
+String getTableName(int column)
+
+int getColumnType(int column)
+
+
+
+java.sql.ResultSetMetaData
+42.4.2 Escape-Kommandos
+
+
+
+
+
+
+
+
+
+
+"{" <Kommandoname> [<Argumente>] "}"
+
+
+42.4.3 Transaktionen
+
+
+
+
+
+
+
+
+
+
+void commit()
+
+void rollback()
+
+void setAutoCommit(boolean autoCommit)
+
+
+
+java.sql.Connection
+
+
+
+
+
+
+
+
+
+
+
+
+int getTransactionIsolation()
+
+void setTransactionIsolation(int level)
+
+
+
+java.sql.Connection
+42.4.4 JDBC-Datentypen
+
+42.4.5 Umgang mit JDBC-Objekten
+
+
+
+
+Listing 42.11: Die Klasse CachedConnection
+
+
+
+
+
+001 /* CachedConnection.java */
+002
+003 import java.sql.*;
+004 import java.util.*;
+005
+006 public class CachedConnection
+007 {
+008 private Connection con;
+009 private LinkedList<Statement> cache;
+010 private int stmtcnt;
+011
+012 public CachedConnection(Connection con)
+013 {
+014 this.con = con;
+015 this.cache = new LinkedList<Statement>();
+016 this.stmtcnt = 0;
+017 }
+018
+019 public Statement getStatement()
+020 throws SQLException
+021 {
+022 if (cache.size() <= 0) {
+023 return con.createStatement();
+024 } else {
+025 return cache.poll();
+026 }
+027 }
+028
+029 public void releaseStatement(Statement statement)
+030 {
+031 cache.add(statement);
+032 }
+033 }
+
+
+CachedConnection.java
+
+Es ist wichtig, die JDBC-Objekte auch dann zu schließen, wenn +eine Ausnahme während der Bearbeitung aufgetreten ist. Andernfalls +würden möglicherweise Ressourcen nicht freigegeben und das +Programm würde so nach und nach mehr Speicher oder Rechenzeit +verbrauchen. Am einfachsten kann dazu die finally-Klausel +der try-catch-Anweisung +verwendet werden. +
+
![]() |
+![]() |
+
+
+ +Eine weitere Eigenschaft der Klasse ResultSet +verdient besondere Beachtung. Bei manchen JDBC-Treibern erlauben die +zurückgegebenen ResultSet-Objekte +das Lesen einer bestimmten Tabellenspalte nur einmal. Der zweite Versuch +wird mit einer Fehlermeldung »No data« (oder ähnlich) +quittiert. Manche Treiber erfordern sogar, dass die Spalten des ResultSet +in der Reihenfolge ihrer Definition gelesen werden. In beiden Fällen +ist es gefährlich, einen ResultSet +als Parameter an eine Methode zu übergeben, denn die Methode +weiß nicht, welche Spalten bereits vom Aufrufer gelesen wurden +und umgekehrt. Eine Lösung könnte darin bestehen, einen +ResultSet +mit integriertem Cache zu entwickeln, der sich bereits gelesene Spaltenwerte +merkt. Alternativ könnte man auch einen objekt-relationalen Ansatz +versuchen, bei dem jeder gelesene Satz der Ergebnismenge direkt ein +passendes Laufzeitobjekt erzeugt, das dann beliebig oft gelesen werden +kann. Wir wollen auf beide Varianten an dieser Stelle nicht weiter +eingehen. |
+
+
|
+![]() |
+
+Prepared Statements sind parametrisierte +SQL-Anweisungen. Sie werden zunächst deklariert und zum Vorkompilieren +an die Datenbank übergeben. Später können sie dann +beliebig oft ausgeführt werden, indem die formalen Parameter +durch aktuelle Werte ersetzt werden und die so parametrisierte Anweisung +an die Datenbank übergeben wird. Der Vorteil von Prepared Statements +ist, dass die Vorbereitungsarbeiten nur einmal erledigt werden müssen +(Syntaxanalyse, Vorbereitung der Abfragestrategie und -optimierung) +und die tatsächliche Abfrage dann wesentlich schneller ausgeführt +werden kann. Das bringt Laufzeitvorteile bei der wiederholten Ausführung +der vorkompilierten Anweisung. + +
+JDBC stellt Prepared Statements mit dem Interface PreparedStatement, +das aus Statement +abgeleitet ist, zur Verfügung. Die Methode prepareStatement +des Connection-Objekts +liefert ein PreparedStatement: +
+
+
++public PreparedStatement prepareStatement(String sql) + throws SQLException ++ + |
++java.sql.Connection | +
+Als Argument wird ein String übergeben, der die gewünschte +SQL-Anweisung enthält. Die formalen Parameter werden durch Fragezeichen +dargestellt. Bei den meisten Datenbanken dürfen sowohl Änderungs- +als auch Abfrageanweisungen vorkompiliert werden. Sie werden dann +später mit executeQuery +bzw. executeUpdate +ausgeführt. Anders als im Basisinterface sind diese Methoden +im Interface PreparedStatement +parameterlos: +
+
+
++public ResultSet executeQuery() + throws SQLException + +public int executeUpdate() + throws SQLException ++ + |
++java.sql.PreparedStatement | +
+Bevor eine dieser Methoden aufgerufen werden darf, ist es erforderlich, +die vorkompilierte Anweisung zu parametrisieren. Dazu muss für +jedes Fragezeichen eine passende set-Methode +aufgerufen und das gewünschte Argument übergeben werden. +Die set-Methoden gibt es für +alle JDBC-Typen (siehe beispielsweise die analoge Liste der get-Methoden +in Tabelle 42.1): +
+
+
++public void setBoolean(int parameterIndex, boolean x) + throws SQLException + +public void setByte(int parameterIndex, byte x) + throws SQLException + +... ++ + |
++java.sql.PreparedStatement | +
+Der erste Parameter gibt die Position des Arguments in der Argumentliste +an. Das erste Fragezeichen hat den Index 1, das zweite den Index 2 +usw. Der zweite Parameter liefert den jeweiligen Wert, der anstelle +des Fragezeichens eingesetzt werden soll. + +
+Als Beispiel wollen wir uns eine abgewandelte Form der in Abschnitt 42.3.5 +vorgestellten Methode countRecords +ansehen, bei der anstelle eines Statement-Objekts +ein PreparedStatement +verwendet wird: + + +
+
+
+
+001 public static void countRecords()
+002 throws SQLException
+003 {
+004 PreparedStatement pstmt = con.prepareStatement(
+005 "SELECT count(*) FROM ?"
+006 );
+007 String[] aTables = {"dir", "file"};
+008 for (int i = 0; i < aTables.length; ++i) {
+009 pstmt.setString(1, aTables[i]);
+010 ResultSet rs = pstmt.executeQuery();
+011 if (!rs.next()) {
+012 throw new SQLException("SELECT COUNT(*): no result");
+013 }
+014 System.out.println(aTables[i] + ": " + rs.getInt(1));
+015 }
+016 pstmt.close();
+017 }
+
+ |
+
+Das PreparedStatement +enthält hier den Namen der Tabelle als Parameter. In einer Schleife +nehmen wir nun für die Tabellen »dir« und »file« +jeweils eine Parametrisierung vor und führen dann die eigentliche +Abfrage durch. Der Rückgabewert von executeQuery +entspricht dem der Basisklasse, so dass der obige Code sich prinzipiell +nicht von dem in Abschnitt 42.3.5 +unterscheidet. +
+
![]() |
+![]() |
+
+
+ +Nicht alle Datenbanken erlauben es, Tabellennamen zu parametrisieren, +sondern beschränken diese Fähigkeit auf Argumente von Such- +oder Änderungsausdrücken. Tatsächlich läuft unser +Beispiel zwar mit InstantDB, aber beispielsweise nicht mit MS Access +95. |
+
+
|
+![]() |
+
+Dieser Abschnitt gibt eine kurze Übersicht der gebräuchlichsten +SQL-Anweisungen in ihren grundlegenden Ausprägungen. Er ersetzt +weder ein Tutorial noch eine Referenz und ist zu keinem der bekannten +SQL-Standards vollständig kompatibel. Trotzdem mag er für +einfache Experimente nützlich sein und helfen, die ersten JDBC-Anbindungen +zum Laufen zu bringen. Für »ernsthafte« Datenbankanwendungen +sollte zusätzliche Literatur konsultiert und dabei insbesondere +auf die Spezialitäten der verwendeten Datenbank geachtet werden. + +
+Die nachfolgenden Syntaxbeschreibungen sind an die bei SQL-Anweisungen +übliche Backus-Naur-Form angelehnt: +
+Mit CREATE TABLE +kann eine neue Tabelle angelegt werden. Mit DROP TABLE +kann sie gelöscht und mit ALTER TABLE +ihre Struktur geändert werden. Mit CREATE INDEX +kann ein neuer Index angelegt, mit DROP INDEX +wieder gelöscht werden. +
+
+
++CREATE TABLE TabName + (ColName DataType [DEFAULT ConstExpr] + [ColName DataType [DEFAULT ConstExpr]]...) + +ALTER TABLE TabName + ADD (ColName DataType + [ColName DataType]...) + +CREATE [UNIQUE] INDEX IndexName + ON TabName + (ColName [ASC|DESC] + [, ColName [ASC|DESC]]...) + +DROP TABLE TabName + +DROP INDEX IndexName ++ + |
+
+TabName, ColName und IndexName sind SQL-Bezeichner. +ConstExpr ist ein konstanter Ausdruck, der einen Standardwert +für eine Spalte vorgibt. DataType gibt den Datentyp der +Spalte an, die gebräuchlichsten von ihnen können Tabelle 42.4 +entnommen werden. + +
+
| Bezeichnung | +Bedeutung |
| CHAR(n) | +Zeichenkette der (festen) Länge n. |
| VARCHAR(n) | +Zeichenkette variabler Länge mit max. +n Zeichen. |
| SMALLINT | +16-Bit-Ganzzahl mit Vorzeichen. |
| INTEGER | +32-Bit-Ganzzahl mit Vorzeichen. |
| REAL | +Fließkommazahl mit etwa 7 signifikanten +Stellen. |
| FLOAT | +Fließkommazahl mit etwa 15 signifikanten +Stellen. Auch als DOUBLE oder DOUBLE PRECISION bezeichnet. |
| DECIMAL(n,m) | +Festkommazahl mit n Stellen, davon +m Nachkommastellen. Ähnlich NUMERIC. |
| DATE | +Datum (evtl. mit Uhrzeit). Verwandte Typen +sind TIME und TIMESTAMP. |
+Tabelle 42.4: SQL-Datentypen
+ + + + ++Ein neuer Datensatz kann mit INSERT INTO +angelegt werden. Soll ein bestehender Datensatz geändert werden, +ist dazu UPDATE +zu verwenden. Mit DELETE FROM +kann er gelöscht werden. +
+
+
+
+INSERT INTO TabName
+ [( ColName [,ColName] )]
+ VALUES (Expr [,Expr]...)
+
+UPDATE TabName
+ SET ColName = {Expr|NULL}
+ [,ColName = {Expr|NULL}]...
+ [WHERE SearchCond]
+
+DELETE FROM TabName
+ [WHERE SearchCond]
+
+
+ |
+
+TabName und ColName sind die Bezeichner der gewünschten +Tabelle bzw. Spalte. Expr kann eine literale Konstante oder +ein passender Ausdruck sein. SearchCond ist eine Suchbedingung, +mit der angegeben wird, auf welche Sätze die UPDATE- +oder DELETE FROM-Anweisung +angewendet werden soll. Wird sie ausgelassen, wirken die Änderungen +auf alle Sätze. Wir kommen im nächsten Abschnitt auf die +Syntax der Suchbedingung zurück. Wird bei der INSERT INTO-Anweisung +die optionale Feldliste ausgelassen, müssen Ausdrücke für +alle Felder angegeben werden. + + + + +
+Das Lesen von Daten erfolgt mit der SELECT-Anweisung. +Ihre festen Bestandteile sind die Liste der Spalten ColList +und die Liste der Tabellen, die in der Abfrage verwendet werden sollen. +Daneben gibt es eine Reihe von optionalen Bestandteilen: +
+
+
++SELECT [ALL|DISTINCT] ColList + FROM TabName [,TabName]... + [WHERE SearchCond] + [GROUP BY ColName [,ColName]...] + [HAVING SearchCond] + [UNION SubQuery] + [ORDER BY ColName [ASC|DESC] + [,ColName [ASC|DESC]]...] ++ + |
+
+Die Spaltenliste kann entweder einzelne Felder aufzählen, oder +es können durch Angabe eines Sternchens »*« alle Spalten +angegeben werden. Wurde mehr als eine Tabelle angegeben und sind die +Spaltennamen nicht eindeutig, kann ein Spaltenname durch Voranstellen +des Tabellennamens und eines Punkts qualifiziert werden. Zusätzlich +können die Spaltennamen mit dem Schlüsselwort »AS« +ein (möglicherweise handlicheres) Synonym erhalten. Die Syntax +von ColList ist: +
+
+
++ColExpr [AS ResultName] +[,ColExpr AS ResultName]]... ++ + |
+
+Zusätzlich gibt es einige numerische Aggregatfunktionen, mit +denen der Wert der als Argument angegebenen Spalte über alle +Sätze der Ergebnismenge kumuliert werden kann: + +
+
| Bezeichnung | +Bedeutung |
| COUNT | +Anzahl der Sätze |
| AVG | +Durchschnitt |
| SUM | +Summe |
| MIN | +Kleinster Wert |
| MAX | +Größter Wert |
+Tabelle 42.5: SQL-Aggregatfunktionen
+ ++Die WHERE-Klausel +definiert die Suchbedingung. Wurde sie nicht angegeben, liefert die +Anweisung alle vorhandenen Sätze. Der Suchausdruck SearchCond +kann sehr unterschiedliche Formen annehmen. Zunächst kann eine +Spalte mit Hilfe der relationalen Operatoren <, <=, >, >=, += und <> mit einer anderen Spalte oder einem Ausdruck verglichen +werden. Die Teilausdrücke können mit den logischen Operatoren +AND, +OR +und NOT +verknüpft werden, die Auswertungsreihenfolge kann in der üblichen +Weise durch Klammerung gesteuert werden. + +
+Mit Hilfe des Schlüsselworts LIKE +kann eine Ähnlichkeitssuche durchgeführt werden: +
+
+
++Expr LIKE Pattern ++ + |
+
+Mit Hilfe der Wildcards »%« und »_« können +auch unscharf definierte Begriffe gesucht werden. Jedes Vorkommen +von »%« passt auf eine beliebige Anzahl beliebiger Zeichen, +jedes »_« steht für genau ein beliebiges Zeichen. Manche +Datenbanken unterscheiden zwischen Groß- und Kleinschreibung, +andere nicht. + +
+Mit Hilfe der Klauseln IS NULL +und IS NOT NULL +kann getestet werden, ob der Inhalt einer Spalte den Wert NULL enthält +oder nicht: +
+
+
++ColName IS [NOT] NULL ++ + |
+
+Mit dem BETWEEN-Operator +kann bequem festgestellt werden, ob ein Ausdruck innerhalb eines vorgegebenen +Wertebereichs liegt oder nicht: +
+
+
++Expr BETWEEN Expr AND Expr ++ + |
+
+Neben den einfachen Abfragen gibt es eine Reihe von Abfragen, die +mit Subqueries (Unterabfragen) arbeiten: +
+
+
+
+EXISTS (SubQuery)
+
+Expr [NOT] IN (SubQuery)
+
+Expr RelOp {ALL|ANY} (SubQuery)
+
+
+ |
+
+Die Syntax von SubQuery entspricht der einer normalen SELECT-Anweisung. +Sie definiert eine separat definierte Menge von Daten, die als Teilausdruck +in einer Suchbedingung angegeben wird. Der EXISTS-Operator +testet, ob die Unterabfrage mindestens ein Element enthält. Mit +dem IN-Operator +wird getestet, ob der angegebene Ausdruck in der Ergebnismenge enthalten +ist. Die Ergebnismenge kann auch literal als komma-separierte Liste +von Werten angegeben werden. Schließlich kann durch Angabe eines +relationalen Operators getestet werden, ob der Ausdruck zu mindestens +einem (ANY) +oder allen (ALL) +Sätzen der Unterabfrage in der angegebenen Beziehung steht. Bei +den beiden letzten Unterabfragen sollte jeweils nur eine einzige Spalte +angegeben werden. + +
+Die GROUP BY-Klausel +dient dazu, die Sätze der Ergebnismenge zu Gruppen zusammenzufassen, +bei denen die Werte der angegebenen Spalten gleich sind. Sie wird +typischerweise zusammen mit den oben erwähnten Aggregatfunktionen +verwendet. Mit HAVING +kann zusätzlich eine Bedingung angegeben werden, mit der die +gruppierten Ergebnissätze »nachgefiltert« werden. + +
+Mit dem UNION-Operator +können die Ergebnismengen zweier SELECT-Anweisungen +zusammengefasst werden. Das wird typischerweise gemacht, wenn die +gesuchten Ergebnissätze aus mehr als einer Tabelle stammen (andernfalls +könnte der OR-Operator +verwendet werden). + +
+Die ORDER BY-Klausel +kann angegeben werden, um die Reihenfolge der Sätze in der Ergebnismenge +festzulegen. Die Sätze werden zunächst nach der ersten angegebenen +Spalte sortiert, bei Wertegleichheit nach der zweiten, der dritten +usw. Mit Hilfe der Schlüsselwörter ASC +und DESC +kann angegeben werden, ob die Werte auf- oder absteigend sortiert +werden sollen. +
| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |