Nach diesem ersten kleinen Streifzug durch INSERT, UPDATE und DELETE wollen wir uns ausgedehnt mit SELECT beschäftigen. SELECT bildet quasi das Rückgrat von SQL und bietet reichhaltige Möglichkeiten, Daten effizient und schnell abzufragen.
Wie das folgende Listing zeigt, stellt SELECT eine Fülle von Syntaxelementen zur Verfügung:
test=# \h SELECT
Command: SELECT
Description: retrieve rows from a table or view
Syntax:
[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
* | expression [ [ AS ] output_name ] [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY expression [, ...] ]
[ HAVING condition [, ...] ]
[ WINDOW window_name AS ( window_definition ) [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST
} ] [, ...] ]
[ LIMIT { count | ALL } ]
[ OFFSET start [ ROW | ROWS ] ]
[ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
[ FOR { UPDATE | SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ]
where from_item can be one of:
[ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, ...]
| column_definition [, ...] ) ]
function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
from_item [ NATURAL ] join_type from_item [ ON join_condition | USING (
join_column [, ...] ) ]
and with_query is:
with_query_name [ ( column_name [, ...] ) ] AS ( select )
TABLE { [ ONLY ] table_name [ * ] | with_query_name }
In diesem Abschnitt wollen wir uns intensiv mit diesem Befehl beschäftigen und uns ansehen, welche Möglichkeiten sich bieten.
Beginnen wir mit einigen einfachen SELECT Operationen. Zuvor fügen wir noch einige Testdatensätze ein:
test=# INSERT INTO t_person VALUES ('123456', 'Markus Eisner');
INSERT 318728 1
test=# INSERT INTO t_person VALUES ('12345678', 'Leo Lechner');
INSERT 318729 1
test=# INSERT INTO t_person VALUES ('2345', 'Gaika Huber');
INSERT 318730 1
test=# INSERT INTO t_person VALUES ('2456', 'Josef Fischer');
INSERT 318732 1
test=# INSERT INTO t_person VALUES ('24567', 'Anton Jelinek');
INSERT 318733 1
test=# SELECT * FROM t_person;
svnr | name
----------+---------------
123456 | Markus Eisner
12345678 | Leo Lechner
2345 | Gaika Huber
2456 | Josef Fischer
24567 | Anton Jelinek
(5 rows)
Wenn wir jetzt die Ausgabe auf einen bestimmten Datensatz limitieren wollen, können wir eine einfache WHERE Clause verwenden wie wir sie bereits von UPDATE und DELETE her kennen:
test=# SELECT * FROM t_person WHERE name = 'Markus Eisner'; svnr | name --------+--------------- 123456 | Markus Eisner (1 row)
Wie erwartet liefert PostgreSQL genau einen Datensatz. Bei der Selektierung von Datensätzen müssen wir bedenken, dass der zu suchende String exakt mit den Daten im Feld übereinzustimmen hat. Leerzeichen am Ende eines Strings führen beispielsweise dazu, dass der Datensatz nicht mehr gefunden wird:
test=# SELECT * FROM t_person WHERE name = 'Markus Eisner '; svnr | name ------+------ (0 rows)
Um dieses Problem zu umgehen, bietet PostgreSQL Funktionen wie trim, die die Leerzeichen einfach abschneiden:
test=# SELECT * FROM t_person WHERE name = trim('Markus Eisner ');
svnr | name
--------+---------------
123456 | Markus Eisner
(1 row)
Wenn wir Datensätze suchen wollen, die unterschiedlichen Kriterien unterliegen, können wir OR Verknüpfungen verwenden:
test=# SELECT * FROM t_person WHERE name = 'Markus Eisner' OR svnr = '2345'; svnr | name --------+--------------- 123456 | Markus Eisner 2345 | Gaika Huber (2 rows)
In diesem Fall werden zwei Datensätze zurück gegeben, da exakt zwei Tuples den jeweiligen Kriterien entsprechen.
Manchmal kann es vorkommen, dass komplexere WHERE Clauses zu verwenden sind. In solchen Fällen kommen oft AND / OR Verknüpfungen zum Einsatz. Wir empfehlen in solchen Fällen immer, die zusammengehörigen Blöcke entsprechend zu klammern. Zwar ist das Verhalten von AND / OR Ketten in SQL eindeutig definiert - im Sinne der Lesbarkeit sollte man aber immer explizit klammern:
test=# SELECT * FROM t_person WHERE (name = 'Markus Eisner' OR svnr = '2345') AND name = 'Gaika Huber'; svnr | name ------+------------- 2345 | Gaika Huber (1 row)