Inhaltsverzeichnis
mysql im Stapelbetrieb (Batch Mode)
Dieses Kapitel enthält eine Einführung in MySQL in Form eines
Tutorials. Datei wird gezeigt, wie Sie das
mysql-Client-Programm benutzen, um eine einfache
Datenbank zu erzeugen und zu benutzen. mysql
(auch ``Terminal-Monitor'' oder einfach ``Monitor'' genannt) ist ein
interaktives Programm, mit dem Sie sich mit einem MySQL-Server
verbinden, Anfragen (Queries) absetzen und die Ergebnisse ansehen
können. mysql kann auch im Stapelbetrieb (Batch
Mode) benutzt werden: Sie schreiben Ihre Anfragen zuerst in eine
Datei und veranlassen dann mysql, die Inhalte
dieser Datei auszuführen. Hier werden beide Möglichkeiten
beschrieben, mysql zu benutzen.
Sie können mysql mit der
--help-Option aufrufen, um eine Liste der Optionen
zu sehen:
shell> mysql --help
Dieses Kapitel setzt voraus, dass mysql auf Ihrer
Maschine installiert ist und dass ein MySQL-Server verfügbar ist,
mit dem Sie sich verbinden können. Wenn das nicht der Fall sein
sollte, setzen Sie sich mit Ihrem MySQL-Administrator in Verbindung.
(Wenn Sie der Administrator sind, müssen Sie
in anderen Abschnitten des Handbuchs nachsehen.)
Dieses Kapitel beschreibt den gesamten Prozess der Einrichtung und Benutzung einer Datenbank. Wenn Sie lediglich wissen wollen, wie man auf eine bereits existierende Datenbank zugreift, können Sie die Abschnitte überspringen, die beschreiben, wie man eine Datenbank und die Tabellen, die sie enthält, erzeugt.
Weil dieses Kapitel ein Tutorial ist, wurden notwendigerweise viele Details ausgelassen. Sehen Sie in den relevanten Abschnitten dieses Handbuchs nach, wenn Sie weitere Informationen zu den Themen suchen, die hier besprochen werden.
Um sich zum Server zu verbinden, müssen Sie beim Aufruf von
mysql in der Regel einen MySQL-Benutzernamen
und üblicherweise auch ein Passwort angeben. Wenn der Server auf
einer anderen Maschine als der läuft, von der Sie sich einloggen,
müssen Sie auch einen Hostnamen angeben. Setzen Sie sich mit
Ihrem Administrator in Verbindung, um herauszubekommen, welche
Verbindungsparameter Sie benutzen sollten (das heißt welchen
Host, welchen Benutzername und welches Passwort Sie verwenden
sollen). Wenn Sie die richtigen Parameter kennen, sollten Sie sich
wie folgt verbinden können:
shell> mysql -h host -u user -p
Enter password: ********
******** steht für Ihr Passwort. Geben Sie es
ein, wenn mysql Enter
password: anzeigt.
Wenn das funktioniert hat, sehen Sie ein paar einführende
Informationen, gefolgt von der
mysql>-Eingabeaufforderung:
shell>mysql -h host -u user -pEnter password: ******** Welcome to the MySQL monitor. Commands end mit ; or \g. Your MySQL connection id ist 459 to server version: 3.22.20a-log Type 'help' for help. mysql>
Die Eingabeaufforderung sagt Ihnen, dass mysql
bereit für die Eingabe von Befehlen ist.
Einige Einige MySQL-Installationen erlauben Benutzern, sich als
anonyme (unbenannte) Benutzer mit dem Server auf dem lokalen Host
zu verbinden. Wenn das auf Ihrer Maschine der Fall ist, können
Sie sich mit diesem Server verbinden, indem Sie
mysql ohne irgend welche Optionen aufrufen:
shell> mysql
Nachdem Sie sich erfolgreich verbunden haben, können Sie die
Verbindung jederzeit trennen, indem Sie QUIT an
der mysql>-Eingabeaufforderung eingeben.
mysql> QUIT
Bye
Sie können die Verbindung auch trennen, indem Sie STRG+D eingeben.
Die meisten Beispiele der folgenden Abschnitte setzen voraus, dass
Sie mit dem Server verbunden sind. Das wird durch
mysql> angezeigt.
Stellen Sie sicher, dass Sie mit dem Server verbunden sind, wie im
vorherigen Abschnitt erörtert. Dadurch wird noch keine Datenbank
ausgewählt, mit der Sie arbeiten können, aber das ist in
Ordnung. Hier ist es erst einmal wichtiger, herauszufinden, wie
Sie Anfragen (Queries) absetzen, als direkt mit dem Erzeugen von
Tabellen, dem Einladen von Daten in diese und der Abfrage von
Daten aus diesen zu beginnen. Dieser Abschnitt beschreibt die
grundlegenden Prinzipien der Befehlseingabe, indem etliche
Anfragen gezeigt werden, die Sie ausprobieren können, um sich mit
der Arbeitsweise von mysql vertraut zu machen.
Hier ist ein einfacher Befehl, der den Server bittet, Ihnen seine
Versionsnummer und das aktuelle Datum mitzuteilen. Geben Sie
folgendes an der mysql>-Eingabeaufforderung
ein und drücken Sie die Eingabetaste:
mysql>SELECT VERSION(), CURRENT_DATE;+--------------+--------------+ | version() | CURRENT_DATE | +--------------+--------------+ | 3.22.20a-log | 1999-03-19 | +--------------+--------------+ 1 row in set (0.01 sec) mysql>
Diese Anfrage erläutert verschiedene Dinge über
mysql:
Ein Befehl besteht normalerweise aus einem SQL-Statement,
gefolgt von einem Semikolon. (Es gibt ein paar Ausnahmen, bei
denen das Semikolon nicht benötigt wird.
QUIT, das vorher erwähnt wurde, stellt
eine solche Ausnahme dar. Wir kommen später noch zu anderen
Ausnahmen.)
Wenn Sie einen Befehl absetzen, sendet
mysql ihn zum Server, der ihn ausführt,
und zeigt die Ergebnisse an. Danach wird eine neue
mysql>-Eingabeaufforderung angezeigt, um
klar zu machen, dass es für einen weiteren Befehl bereit ist.
mysql zeigt die Ausgabe der Anfrage in
Tabellenform an (Zeilen und Spalten). Die erste Zeile enthält
Spaltenüberschriften. Die folgenden Zeilen sind die
Ergebnisse der Anfrage. Normalerweise sind die
Spaltenüberschriften die Spaltennamen der Tabellen, die Sie
abfragen. Wenn Sie statt der Spaltennamen den Wert eines
Ausdrucks abfragen (wie im gezeigten Beispiel), beschriftet
mysql die Spaltenüberschrift mit dem
Ausdruck selbst.
mysql zeigt, wie viele Zeilen zurück
gegeben wurden und wie lang die Ausführung der Anfrage
dauerte, was ihnen eine grobe Einschätzung der
Server-Performance ermöglicht. Diese Werte sind ungenau, weil
sie die Wanduhrzeit repräsentieren (und nicht die Prozessor-
oder Maschinenzeit), und weil sie von Faktoren wie der
Serverlast und der Netzwerk-Wartezeit beeinflusst werden. (Um
uns kurz zu fassen, zeigen wir die ``rows in set''-Zeile in
den weiteren Beispielen dieses Kapitels nicht mehr an.)
Schlüsselwörter können in beliebiger Schreibweise (Groß und klein) eingegeben werden. Folgende Anfragen sind gleichwertig:
mysql>SELECT VERSION(), CURRENT_DATE;mysql>select version(), current_date;mysql>SeLeCt vErSiOn(), current_DATE;
Hier kommt eine weitere Anfrage. Sie zeigt, wie Sie
mysql als einfachen Rechner benutzen können:
mysql> SELECT SIN(PI()/4), (4+1)*5;
+-------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+-------------+---------+
| 0.707107 | 25 |
+-------------+---------+
Die bislang gezeigten Befehle sind relativ kurze, einzeilige Statements. Sie können allerdings auch mehrfache Statements auf einer einzelnen Zeile eingeben. Beenden Sie einfach jedes davon mit einem Semikolon:
mysql> SELECT VERSION(); SELECT NOW();
+--------------+
| version() |
+--------------+
| 3.22.20a-log |
+--------------+
+---------------------+
| NOW() |
+---------------------+
| 1999-03-19 00:15:33 |
+---------------------+
Ein Befehl muss nicht auf einer einzelnen Zeile eingegeben werden,
so dass längere Befehle, die mehrere Zeilen erfordern, kein
Problem darstellen. mysql stellt anhand des
beendenden Semikolons fest, wo Ihr Statement endet, und nicht etwa
anhand des Zeilenendes. (Mit anderen Worten akzeptiert
mysql Freiformat-Eingaben: Es sammelt
Eingabezeilen, führt sie aber solange nicht aus, bis es das
Semikolon sieht.)
Hier ist ein einfaches Statement, auf mehrere Zeilen verteilt:
mysql>SELECT->USER()->,->CURRENT_DATE;+--------------------+--------------+ | USER() | CURRENT_DATE | +--------------------+--------------+ | joesmith@localhost | 1999-03-18 | +--------------------+--------------+
Sehen Sie, wie sich die Eingabeaufforderung von
mysql> zu -> ändert,
nachdem Sie die erste Zeile der Mehrzeilen-Anfrage eingegeben
haben. Auf diese Weise zeigt mysql an, dass es
noch nicht das komplette Statement gesehen hat und auf den Rest
wartet. Die Eingabeaufforderung ist Ihr Freund, denn sie stellt
wertvolle Rückmeldungen zur Verfügung. Wenn Sie diese
Rückmeldungen nutzen, werden Sie immer dessen gewahr sein, worauf
mysql wartet.
Wenn Sie den Befehl, den Sie gerade eingeben, nicht ausführen
wollen, können Sie ihn mit \c abbrechen:
mysql>SELECT->USER()->\cmysql>
Beachten Sie auch hierbei die Eingabeaufforderung. Sie ändert
sich zurück zu mysql>, nachdem Sie
\c eingegeben haben, und diese Rückmeldung
bedeutet, dass mysql für einen weiteren Befehl
bereit ist.
Folgende Tabelle zeigt alle Eingabeaufforderungen, denen Sie
begegnen können, und fasst zusammen, was sie über den Zustand
von mysql aussagen:
| Eingabeaufforderung | Bedeutung |
mysql> | Bereit für den nächsten Befehl. |
-> | Wartet auf die nächste Zeile eines mehrzeiligen Befehls. |
'> | Wartet auf die nächste Zeile und fasst eine Zeichenkette zusammen, die
mit einem Apostroph (‘'’)
beginnt. |
"> | Wartet auf die nächste Zeile und fasst eine Zeichenkette zusammen, die
mit Anführungszeichen
(‘"’) beginnt. |
Mehrzeilige Statements passieren häufig aus Versehen, wenn Sie
vorhaben, einen Befehl auf einer einzelnen Zeile abzusetzen, aber
das beendende Semikolon vergessen. In diesem Fall wartet
mysql auf weitere Eingaben:
mysql>SELECT USER()->
Wenn so etwas passiert (Sie dachten, Sie hätten ein Statement
eingegeben, aber die einzige Antwort ist die
->-Eingabeaufforderung), wartet
mysql höchstwahrscheinlich auf das Semikolon.
Wenn Sie nicht darauf achten, was Ihnen die Eingabeaufforderung
mitteilen will, könnten Sie eine ganze Weile herum sitzen, bevor
Sie feststellen, was Sie tun müssen. Geben Sie ein Semikolon ein,
um das Statement zu vollenden, und mysql wird
es ausführen:
mysql>SELECT USER()->;+--------------------+ | USER() | +--------------------+ | joesmith@localhost | +--------------------+
Die '>- und
">-Eingabeaufforderungen kommen bei der
Sammlung von Zeichenketten vor. In MySQL können Sie Zeichenketten
wahlweise in ‘'’- oder
‘"’-Zeichen eingeschlossen eingeben
(zum Beispiel 'hallo' oder
"tschüß"), und mysql
läßt Sie auch Zeichenketten eingeben, die sich über mehrere
Zeilen erstrecken. Wenn Sie eine '>- oder
">-Eingabeaufforderung sehen, heißt das,
dass Sie eine Zeile eingegeben haben, die eine Zeichenkette
enthält, die mit ‘'’ oder
‘"’ beginnt, dass Sie aber noch
nicht das entsprechende beendende Zeichen (ebenfalls
‘'’ oder
‘"’) eingegeben haben. Das ist in
Ordnung, wenn Sie tatsächlich eine mehrzeilige Zeichenkette
eingeben, aber wie wahrscheinlich ist das? Nicht sehr
wahrscheinlich. Wahrscheinlicher ist, dass die
'>- und
">-Eingabeaufforderungen anzeigen, dass Sie
versehentlich ein ‘'’- oder
‘"’-Zeichen ausgelassen haben.
Beispiel:
mysql>SELECT * FROM meine_tabelle WHERE name = "Schmidt AND age < 30;">
Wenn Sie dieses SELECT-Statement eingeben, dann
EINGABE drücken und auf das Ergebnis warten, wird nichts
passieren. Statt sich zu fragen, warum diese Anfrage so lange
dauert, beachten Sie des Rätsels Lösung, die die
">-Eingabeaufforderung anzeigt. Sie sagt
Ihnen, dass mysql auf den Rest einer nicht
beendeten Zeichenkette wartet. (Sehen Sie den Fehler im Statement?
Der Zeichenkette "Schmidt fehlt das zweite
Anführungszeichen.)
Was machen Sie in diesem Fall? Das einfachste ist, den Befehl
abzubrechen. Sie können jetzt allerdings nicht einfach
\c eingeben, weil mysql es
als Teil der Zeichenkette interpretieren würde, die es gerade
sammelt! Geben Sie daher zuerst das schließende
Anführungszeichen ein, damit mysql weiß, dass
die Zeichenkette zuende ist, und erst danach
\c:
mysql>SELECT * FROM meine_tabelle WHERE name = "Schmidt AND age < 30;">"\cmysql>
Die Eingabeaufforderung ändert sich wieder zu
mysql> und zeigt damit an, dass
mysql für einen weiteren Befehl bereit ist.
Es ist wichtig, die Bedeutung der '>- und
">-Eingabeaufforderungen zu kennen, denn
wenn Sie versehentlich eine nicht beendete Zeichenkette eingeben,
werden alle folgenden Zeilen, die Sie eingeben, von
mysql ignoriert - inklusive einer Zeile, die
QUIT enthält! Das kann recht verwirrend sein,
besonders dann, wenn Sie nicht wissen, dass Sie das schließende
Anführungszeichen eingeben müssen, bevor Sie den aktuellen
Befehl abbrechen können.
Jetzt, wo Sie wissen, wie Sie Befehle eingeben, ist es Zeit, auf eine Datenbank zuzugreifen.
Nehmen wir an, Sie haben zuhause mehrere Haustiere (Ihre Menagerie) und Sie wollen unterschiedliche Arten von Information über sie im Überblick behalten. Das können Sie tun, indem Sie Tabellen erzeugen, die Ihre Daten beinhalten, und die Sie mit den gewünschten Informationen füllen. Dann können Sie verschiedene Arten von Fragen über Ihre Haustiere beantworten, indem Sie Daten aus den Tabellen abrufen. Dieser Abschnitt zeigt Ihnen:
Wie Sie eine Datenbank erzeugen
Wie Sie eine Tabelle anlegen
Wie Sie Daten in die Tabelle laden
Wie Sie auf unterschiedliche Weise Daten aus der Tabelle abfragen
Wie Sie mehrere Tabellen benutzen
Die Menagerie-Datenbank wird (bewusst) einfach sein, aber man kann
sich leicht Situationen im echten Leben vorstellen, in denen ein
ähnlicher Typ von Datenbank benutzt werden könnte.
Beispielsweise könnte ein Bauer eine solche Datenbankbenutzung,
um den Überblick über sein Vieh zu behalten, oder ein Tierarzt,
um seine Patientendaten im Griff zu haben. Sie finden eine
Menagerie-Distribution, die einige der benutzten Anfragen und
Beispielsdaten enthält, auf der MySQL-Website. Sie finden die
Distribution entweder unter
komprimiertes
tar-Format oder unter
Zip-Format.
Benutzen Sie das SHOW-Statement, um
herauszufinden, welche Datenbanken zur Zeit auf dem Server
existieren:
mysql> SHOW DATABASES;
+----------+
| database |
+----------+
| mysql |
| test |
| tmp |
+----------+
Die Liste der Datenbanken weicht wahrscheinlich von derjenigen auf
Ihrer Maschine ab, aber wahrscheinlich befinden sich die
mysql- und test-Datenbanken
darunter. Die mysql-Datenbank ist notwendig,
weil darin die Zugriffsrechte für Benutzer gespeichert sind. Die
test-Datenbank ist meist als Arbeitsbereich zum
Ausprobieren dabei.
Wenn die test-Datenbank existiert, versuchen
Sie, darauf zuzugreifen:
mysql> USE test
database changed
Beachten Sie, dass USE - wie
QUIT - kein Semikolon erfordert. (Sie können
solche Statements mit einem Semikolon beenden, wenn Sie wollen, es
schadet nicht.) Das USE-Statement ist auch auf
andere Art besonders: Es muss auf einer einzigen Zeile eingegeben
werden.
Sie können die test-Datenbank für die
folgenden Beispiele benutzen (wenn Sie Zugriff darauf haben), aber
alles, was Sie dort anlegen, kann von jedem sonstigen, der Zugriff
darauf hat, entfernt werden. Aus diesem Grund sollten Sie besser
Ihren MySQL-Administrator um Erlaubnis bitten, eine eigene
Datenbankbenutzung zu können. Nehmen wir an, Sie wollen Ihre
Datenbank menagerie nennen. Dafür muss der
Administrator folgenden Befehl eingeben:
mysql> GRANT ALL ON menagerie.* TO ihr_mysql_name;
Wobei ihr_mysql_name der MySQL-Benutzername
ist, der Ihnen zugewiesen wurde.
Wenn der Administrator für Sie eine Datenbank erzeugt, wenn er Ihre Zugriffsrechte einträgt, können Sie sie unmittelbar benutzen. Ansonsten müssen Sie sie selbst anlegen:
mysql> CREATE DATABASE menagerie;
Unter Unix sind Datenbanknamen abhängig von der
Groß-/Kleinschreibung (im Gegensatz zu SQL-Schlüsselwörtern),
daher müssen Sie sich auf Ihre Datenbank immer mit
menagerie beziehen, nicht mit
Menagerie, MENAGERIE oder
irgend einer anderen Variante. Dasselbe gilt für Tabellennamen.
(Unter Windows trifft diese Beschränkung nicht zu. Dennoch muss
man sich bei einer gegebenen Anfrage auf Datenbanken und
Tabellen in derselben Schreibweise beziehen.)
Das Erzeugen einer Datenbank wählt diese nicht zur Benutzung
aus. Das müssen Sie explizit tun. Um
menagerie zur aktuell ausgewählten Datenbank
zu machen, benutzen Sie folgenden Befehl:
mysql> USE menagerie
database changed
Ihre Datenbank muss nur einmal erzeugt werden, aber Sie müssen
sie jedes Mal zur Benutzung auswählen, wenn Sie eine
mysql-Sitzung beginnen. Das können Sie durch
die Eingabe eines USE-Statements wie oben
beschrieben tun. Alternativ können Sie die Datenbank auf der
Kommandozeile auswählen, wenn Sie mysql
aufrufen. Geben Sie einfach ihren Namen nach den
Verbindungsparametern ein, die Sie ansonsten eingeben müssen.
Beispiel:
shell> mysql -h host -u user -p menagerie
Enter password: ********
Beachten Sie, dass menagerie auf der
gezeigten Kommandozeile nicht Ihr Passwort ist! Wenn Sie Ihr
Passwort auf der Kommandozeile nach der
-p-Option eingeben wollen, müssen Sie das
ohne Leerzeichen dazwischen machen (beispielsweise als
-pmeinpasswort, nicht als -p
meinpasswort). Es wird allerdings nicht empfohlen, das
Passwort auf der Kommandozeile einzugeben, denn dann kann es
durch andere Benutzer, die auf Ihrer Maschine eingeloggt sind,
ausspioniert werden.
Die Datenbank zu erzeugen ist leicht, aber bis jetzt ist sie
noch leer, wie Ihnen SHOW TABLES zeigt:
mysql> SHOW TABLES;
Empty set (0.00 sec)
Der schwierigere Teil besteht darin, sich zu entscheiden, wie die Struktur Ihrer Datenbank sein sollte: Welche Tabellen Sie benötigen und welche Spalten in jeder Tabelle enthalten sein sollen.
Sie brauchen eine Tabelle, die für jedes Ihrer Haustiere einen
Datensatz enthält. Diese kann pet-Tabelle
genannt werden, und sie sollte zumindest den Namen jedes Tiers
enthalten. Weil lediglich der Name nicht besonders interessant
ist, sollte die Tabelle weitere Informationen enthalten. Wenn
zum Beispiel mehr als eine Person in Ihrer Familie ein Haustier
hält, würden Sie den Namen des Besitzers jedes Haustiers
auflisten wollen. Ausserdem wollen Sie vielleicht ein paar
grundlegende Informationen wie Art und Geschlecht einfügen.
Was ist mit dem Alter? Diese Information könnte interessant sein, aber es ist keine gute Idee, sie in der Datenbank zu speichern. Das Alter ändert sich, wenn die Zeit vergeht, was bedeutet, dass Sie Ihre Datensätze oft aktualisieren müssen. Statt dessen ist es besser, einen festen Wert wie das Geburtsdatum zu speichern. Immer, wenn Sie dann das Alter benötigen, berechnen Sie es als Differenz zwischen dem aktuellen Datum und dem Geburtstag. MySQL stellt Funktionen für Datumsberechnungen zur Verfügung, daher ist so etwas nicht schwer. Ausserdem hat die Speicherung von Geburtsdaten anstelle von Alter weitere Vorteile:
Sie können die Datenbank für Aufgaben wie die Erzeugung einer Liste bevorstehender Tier-Geburtstage benutzen. (Wenn Sie das etwas albern finden, bedenken Sie, dass sich dieselbe Frage zum Beispiel bei einer Geschäftsdatenbank stellt, um Kunden herauszufinden, denen Sie in Kürze Geburtstagswünsche schicken wollen, also für die Computer-unterstützte persönliche Note.)
Sie können Altersberechnungen mit anderen Bezugsdaten als dem aktuellen Datum durchführen. Wenn Sie das Sterbedatum speichern, können Sie zum Beispiel leicht errechnen, wie alt ein Haustier war, als es starb.
Wahrscheinlich fallen Ihnen weitere Informationen ein, die
sinnvoller Weise in der pet-Tabelle
gespeichert werden könnten. Für unser Beispiel sollen die
bisher identifizierten Informationen fürs Erste ausreichen:
Name, Besitzer, Art, Geschlecht, Geburtstag und Sterbetag.
Legen Sie mit einem CREATE TABLE-Statement
das Layout Ihrer Tabelle fest:
mysql>CREATE TABLE pet (name VARCHAR(20), besitzer VARCHAR(20),->art VARCHAR(20), geschlecht CHAR(1), geburtstag DATE, sterbetag DATE);
VARCHAR ist für die
name-, besitzer- und
art-Spalten eine gute Wahl, weil die
Spaltenwerte in der Länge variieren werden. Diese Spalten
müssen auch nicht alle gleich sein, also 20
Zeichen lang. Sie können jede beliebige Länge zwischen
1 und 255 wählen, was
immer Ihnen vernünftig erscheint. (Wenn Sie eine schlechte Wahl
getroffen haben und sich später herausstellt, dass Sie eine
längere Spalte brauchen, stellt MySQL ein ALTER
TABLE-Statement zur Verfügung.)
Das Geschlecht der Tiere kann vielfältig dargestellt werden,
zum Beispiel als "m" und
"w", oder auch als
"männlich" und
"weiblich". Am einfachsten ist es, hierfür
einzelne Zeichen wie "m" und
"w" zu verwenden.
Der DATE-Datentyp für
geburtstag und sterbetag
liegt auf der Hand.
Nachdem Sie eine Tabelle angelegt haben, sollte SHOW
TABLES auch etwas zeigen:
mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| pet |
+---------------------+
Um sicherzustellen, dass Ihre Tabelle so wie erwartet angelegt
wurde, benutzen Sie das DESCRIBE-Statement:
mysql> DESCRIBE pet;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| besitzer | varchar(20) | YES | | NULL | |
| art | varchar(20) | YES | | NULL | |
| geschlecht | char(1) | YES | | NULL | |
| geburtstag | date | YES | | NULL | |
| sterbetag | date | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
Sie können DESCRIBE jederzeit benutzen, zum
Beispiel, wenn Sie die Namen der Spalten Ihrer Tabelle vergessen
haben oder von welchem Datentyp sie sind.
Nachdem Sie Ihre Tabelle erzeugt haben, müssen Sie sie mit
Daten füllen. Hierfür sind die LOAD DATA-
und INSERT-Statements nützlich.
Nehmen wir an, Sie haben Haustiere wie unten aufgeführt.
(Achten Sie bei den Datumsangaben bitte darauf, dass MySQL Daten
im YYYY-MM-DD-Format erwartet, was von dem
Format abweichen kann, an das Sie gewohnt sind.)
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
| Fluffy | Harold | Katze | w | 1993-02-04 | |
| Claws | Gwen | Katze | m | 1994-03-17 | |
| Buffy | Harold | Hund | w | 1989-05-13 | |
| Fang | Benny | Hund | m | 1990-08-27 | |
| Bowser | Diane | Hund | m | 1998-08-31 | 1995-07-29 |
| Chirpy | Gwen | Vogel | w | 1998-09-11 | |
| Whistler | Gwen | Vogel | 1997-12-09 | ||
| Slim | Benny | Schlange | m | 1996-04-29 |
Weil Sie mit einer leeren Tabelle beginnen, ist eine einfache Möglichkeit, diese mit Daten zu füllen, dass Sie eine Textdatei erzeugen, die eine Zeile für jedes Ihrer Tiere enthält, und die Inhalte dieser Datei dann mit einem einzigen Statement in die Tabelle laden.
Erzeugen Sie also eine Textdatei pet.txt,
die einen Datensatz pro Zeile enthält, mit Werten, die durch
TAB-Zeichen getrennt sind, und zwar in der Reihenfolge, in der
die Spalten im CREATE TABLE-Statement
aufgeführt waren. Fehlende Werte (wie unbekanntes Geschlecht
oder Sterbedaten für Tiere, die noch leben) ersetzen Sie mit
NULL-Werten. Um das in Ihrer Textdatei
darzustellen, nehmen Sie \N. Der Datensatz
für den Vogel Whistler zum Beispiel sieht wie folgt aus (wobei
der Leerraum zwischen den Werten ein einzelnes TAB-Zeichen
darstellt):
Whistler | Gwen | Vogel | \N | 1997-12-09 | \N |
Um die Textdatei pet.txt in die
pet-Tabelle zu laden, benutzen Sie folgenden
Befehl:
mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;
Sie können das Trennzeichen für die Spalten und das Zeichen
für Zeilenende im LOAD DATA-Statement
explizit festlegen, wenn Sie wollen, aber vorgabemäßig sind
das das TAB-Zeichen und das Zeilenvorschub-Zeichen. Das reicht
für das Statement aus, um die Datei
pet.txt korrekt einzulesen.
Wenn Sie einzeln neue Datensätze hinzufügen wollen, ist das
INSERT-Statement nützlich. In seiner
einfachsten Form geben Sie für jede Spalte Werte an, in genau
der Reihenfolge, in der die Spalten im CREATE
TABLE-Statement aufgeführt wurden. Nehmen wir an,
dass Diane einen neuen Hamster namens Puffball bekommt. Sie
fügen einen neuen Datensatz mittels
INSERT-Statement wie folgt hinzu:
mysql>INSERT INTO pet->VALUES ('Puffball','Diane','Hamster','w','1999-03-30',NULL);
Beachten Sie, dass hierbei Zeichenketten- und Datumswerte in
Anführungszeichen stehen. Mit INSERT können
Sie auch direkt NULL einfügen, um einen
fehlenden Wert darzustellen. Sie können dafür nicht
\N wie bei LOAD DATA
verwenden.
Diesem Beispiel können Sie auch entnehmen, dass es einiger
Tipparbeit bedurft hätte, die anfänglichen Datensätze mit
mehreren INSERT-Statements einzufügen, statt
hierfür ein einziges LOAD DATA-Statement zu
verwenden.
Das SELECT-Statement wird benutzt, um
Informationen aus einer Tabelle herauszuziehen. Die allgemeine
Form des Statements ist:
SELECT auszuwählende_spalten FROM tabelle WHERE gewünschte_bedingungen
auszuwählende_spalten bezeichnet, was Sie
sehen wollen. Das kann entweder eine Liste von Spalten sein oder
*, um ``alle Spalten'' zu bezeichnen.
tabelle kennzeichnet die Tabelle, aus der Sie
Spalten abfragen wollen. Die WHERE-Klausel
ist optional. Wenn sie vorhanden ist, kennzeichnet
gewünschte_bedingungen die Bedingungen, mit
denen die Zeilen übereinstimmen müssen, damit sie abgefragt
werden.
Die einfachste Form von SELECT fragt alles
aus einer Tabelle ab:
mysql> SELECT * FROM pet;
+----------+----------+----------+------------+------------+------------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+----------+----------+----------+------------+------------+------------+
| Fluffy | Harold | Katze | w | 1993-02-04 | NULL |
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
| Fang | Benny | Hund | m | 1990-08-27 | NULL |
| Bowser | Diane | Hund | m | 1998-08-31 | 1995-07-29 |
| Chirpy | Gwen | Vogel | w | 1998-09-11 | NULL |
| Whistler | Gwen | Vogel | NULL | 1997-12-09 | NULL |
| Slim | Benny | Schlange | m | 1996-04-29 | NULL |
| Puffball | Diane | Hamster | w | 1999-03-30 | NULL |
+----------+----------+----------+------------+------------+------------+
Diese Form von SELECT ist nützlich, wenn
Sie Ihre gesamte Tabelle abfragen wollen, zum Beispiel, wenn
Sie sich gerade mit einem anfänglichen Satz Daten geladen
haben. Wie das so passiert, zeigt die Ausgabe einen Fehler
auf: Bowser scheint gestorben zu sein, bevor er geboren wurde!
In den Original-Stammbaum-Papieren finden Sie, dass das
korrekte Geburtsjahr 1989 ist, nicht 1998.
Es gibt eine ganze Reihe Möglichkeiten, das zu beheben:
Editieren Sie die Datei pet.txt und
beheben Sie den Fehler. Leeren Sie dann die Tabelle und
laden Sie erneut Daten hinein, indem Sie zuerst
DELETE und dann LOAD
DATA benutzen:
mysql>SET AUTOCOMMIT=1; # Für schnelles Neuerzeugen der Tabellemysql>DELETE FROM pet;mysql>LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;
Wenn Sie das jedoch tun, müssen Sie die Daten für Puffball erneut eingeben.
Den fehlerhaften Datensatz mit einem
UPDATE-Statement in Ordnung bringen:
mysql> UPDATE pet SET geburtstag = "1989-08-31" WHERE name = "Bowser";
Wie gezeigt ist es einfach, eine ganze Tabelle abzufragen. Aber typischerweise wird das selten gewünscht sein, besonders, wenn die Tabelle Groß wird. Statt dessen werden Sie an der Antwort auf bestimmte Fragen interessiert sein, wobei Sie ein paar Beschränkungen in Bezug auf die Informationen, die Sie wollen, festlegen. Schauen wir uns einige Auswahl-Anfragen an, hinsichtlich der Fragen in Bezug auf Ihre Haustiere, die sie beantworten.
Sie können nur bestimmte Zeilen Ihrer Tabelle auswählen. Wenn Sie zum Beispiel die Geburtstags-Änderung von Bowser überprüfen wollen, wählen Sie Bowsers Datensatz wie folgt aus:
mysql> SELECT * FROM pet WHERE name = "Bowser";
+--------+----------+---------+-------------+------------+------------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+--------+----------+---------+-------------+------------+------------+
| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
+--------+----------+---------+-------------+------------+------------+
Die Ausgabe bestätigt, dass das Jahr inzwischen korrekt als 1989, nicht 1998, eingetragen ist.
Vergleiche von Zeichenketten achten normalerweise nicht auf
Groß-/Kleinschreibung, daher können Sie den Namen als
"bowser", "BOWSER" usw.
angeben. Das Anfrageergebnis wird dasselbe bleiben.
Sie können für jede Spalte Bedingungen festlegen, nicht nur
für name. Wenn Sie zum Beispiel wissen
wollen, welche Tiere nach 1998 geboren wurden, formulieren Sie
eine Bedingung für die geburtstag-Spalte:
mysql> SELECT * FROM pet WHERE geburtstag >= "1998-1-1";
+----------+----------+---------+-------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+----------+----------+---------+-------------+------------+-----------+
| Chirpy | Gwen | Vogel | w | 1998-09-11 | NULL |
| Puffball | Diane | Hamster | w | 1999-03-30 | NULL |
+----------+----------+---------+-------------+------------+-----------+
Sie können Bedingungen kombinieren, um zum Beispiel weibliche Hunde festzustellen:
mysql> SELECT * FROM pet WHERE art = "Hund" AND geschlecht = "w";
+-------+-----------+---------+------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+-------+-----------+---------+------------+------------+-----------+
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+-----------+---------+------------+------------+-----------+
Die vorherige Anfrage benutzt den logischen Operator
AND. Es gibt auch einen
OR-Operator:
mysql> SELECT * FROM pet WHERE art = "Schlange" OR art = "Vogel";
+----------+----------+---------+-------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+----------+----------+---------+-------------+------------+-----------+
| Chirpy | Gwen | Vogel | w | 1998-09-11 | NULL |
| Whistler | Gwen | Vogel | NULL | 1997-12-09 | NULL |
| Slim | Benny | Schlange| m | 1996-04-29 | NULL |
+----------+----------+---------+-------------+------------+-----------+
AND und OR können
gemischt werden. Wenn Sie das tun, ist es eine gute Idee,
Klammern zu verwenden, um anzuzeigen, wie die Bedingungen
gruppiert werden sollen:
mysql>SELECT * FROM pet WHERE (art = "Katze" AND geschlecht = "m")->OR (art = "Hund" AND geschlecht = "w");+-------+-----------+---------+-------------+------------+-----------+ | name | besitzer | art | geschlecht | geburtstag | sterbetag | +-------+-----------+---------+-------------+------------+-----------+ | Claws | Gwen | Katze | m | 1994-03-17 | NULL | | Buffy | Harold | Hund | w | 1989-05-13 | NULL | +-------+-----------+---------+-------------+------------+-----------+
Wenn Sie nicht ganze Zeilen Ihrer Tabelle sehen wollen, geben
Sie einfach die Spalten an, an denen Sie interessiert sind,
getrennt durch Kommas. Wenn Sie zum Beispiel wissen wollen,
wann Ihre Tiere geboren wurden, wählen Sie die
name- und
geburtstag-Spalten aus:
mysql> SELECT name, geburtstag FROM pet;
+----------+------------+
| name | geburtstag |
+----------+------------+
| Fluffy | 1993-02-04 |
| Claws | 1994-03-17 |
| Buffy | 1989-05-13 |
| Fang | 1990-08-27 |
| Bowser | 1989-08-31 |
| Chirpy | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim | 1996-04-29 |
| Puffball | 1999-03-30 |
+----------+------------+
Um herauszufinden, wem welches Haustier gehört, benutzen Sie diese Anfrage:
mysql> SELECT besitzer FROM pet;
+----------+
| besitzer |
+----------+
| Harold |
| Gwen |
| Harold |
| Benny |
| Diane |
| Gwen |
| Gwen |
| Benny |
| Diane |
+----------+
Beachten Sie jedoch, dass diese Anfrage einfach die
besitzer-Spalte jedes Datensatzes abfragt,
wodurch mehrere von ihnen mehrfach erscheinen. Um die Ausgabe
zu minimieren, fragen Sie jeden eindeutigen Datensatz nur
einmal ab, indem Sie das Schlüsselwort
DISTINCT verwenden:
mysql> SELECT DISTINCT besitzer FROM pet;
+-----------+
| besitzer |
+-----------+
| Benny |
| Diane |
| Gwen |
| Harold |
+-----------+
Sie können eine WHERE-Klausel verwenden,
um die Auswahl von Zeilen mit der Auswahl von Spalten zu
kombinieren. Um zum Beispiel nur die Geburtstage von Hunden
und Katzen zu erhalten, benutzen Sie diese Anfrage:
mysql>SELECT name, art, geburtstag FROM pet->WHERE art = "Hund" OR art = "Katze";+--------+---------+------------+ | name | art | geburtstag | +--------+---------+------------+ | Fluffy | Katze | 1993-02-04 | | Claws | Katze | 1994-03-17 | | Buffy | Hund | 1989-05-13 | | Fang | Hund | 1990-08-27 | | Bowser | Hund | 1989-08-31 | +--------+---------+------------+
Sie haben bei den vorherigen Beispielen vielleicht bemerkt,
dass die Ergebniszeilen in keiner bestimmten Reihenfolge
angezeigt werden. Häufig ist es jedoch einfacher, die Ausgabe
der Anfrage zu überprüfen, wenn die Zeilen auf sinnvolle Art
sortiert werden. Um ein Ergebnis zu sortieren, benutzen Sie
die ORDER BY-Klausel.
Hier sind die Geburtstage der Haustiere, sortiert nach Geburtstag:
mysql> SELECT name, geburtstag FROM pet ORDER BY geburtstag;
+----------+------------+
| name | geburtstag |
+----------+------------+
| Buffy | 1989-05-13 |
| Bowser | 1989-08-31 |
| Fang | 1990-08-27 |
| Fluffy | 1993-02-04 |
| Claws | 1994-03-17 |
| Slim | 1996-04-29 |
| Whistler | 1997-12-09 |
| Chirpy | 1998-09-11 |
| Puffball | 1999-03-30 |
+----------+------------+
Um in umgekehrter Reihenfolge zu sortieren, fügen Sie das
DESC- (descending) Schlüsselwort zum Namen
der Spalte, die Sie sortieren wollen, hinzu:
mysql> SELECT name, geburtstag FROM pet ORDER BY geburtstag DESC;
+----------+------------+
| name | geburtstag |
+----------+------------+
| Puffball | 1999-03-30 |
| Chirpy | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim | 1996-04-29 |
| Claws | 1994-03-17 |
| Fluffy | 1993-02-04 |
| Fang | 1990-08-27 |
| Bowser | 1989-08-31 |
| Buffy | 1989-05-13 |
+----------+------------+
Sie können über mehrere Spalten sortieren. Um beispielsweise zuerst nach der Art des Tieres und dann nach dem Geburtsdatum innerhalb der Tierart zu sortieren (die jüngsten Tiere zuerst), benutzen Sie folgende Anfrage:
mysql> SELECT name, art, geburtstag FROM pet ORDER BY art, geburtstag DESC;
+----------+----------+------------+
| name | art | geburtstag |
+----------+----------+------------+
| Chirpy | Vogel | 1998-09-11 |
| Whistler | Vogel | 1997-12-09 |
| Claws | Katze | 1994-03-17 |
| Fluffy | Katze | 1993-02-04 |
| Fang | Hund | 1990-08-27 |
| Bowser | Hund | 1989-08-31 |
| Buffy | Hund | 1989-05-13 |
| Puffball | Hamster | 1999-03-30 |
| Slim | Schlange | 1996-04-29 |
+----------+----------+------------+
Beachten Sie, dass sich das
DESC-Schlüsselwort nur auf die Spalte
bezieht, die unmittelbar davor steht
(geburtstag). art-Werte
werden nach wie vor in aufsteigender Reihenfolge sortiert.
MySQL stellt etliche Funktionen zur Verfügung, mit denen Sie Datumsberechnungen wie Altersberechnungen oder das Extrahieren von Datumsteilen durchführen können.
Um festzustellen, wie alt jedes Ihrer Haustiere ist, berechnen Sie die Differenz im Jahresanteil des aktuellen Datums und des Geburtstags und subtrahieren eins, wenn das aktuelle Datum früher im Kalender erscheint als das Geburtsdatum. Folgende Anfrage zeigt für jedes Haustier das Geburtsdatum, das aktuelle Datum und das Alter in Jahren:
mysql>SELECT name, geburtstag, CURRENT_DATE,->(YEAR(CURRENT_DATE)-YEAR(geburtstag))->- (RIGHT(CURRENT_DATE,5)<RIGHT(geburtstag,5))->AS age->FROM pet;+----------+------------+--------------+------+ | name | geburtstag | CURRENT_DATE | age | +----------+------------+--------------+------+ | Fluffy | 1993-02-04 | 2001-08-29 | 8 | | Claws | 1994-03-17 | 2001-08-29 | 7 | | Buffy | 1989-05-13 | 2001-08-29 | 12 | | Fang | 1990-08-27 | 2001-08-29 | 11 | | Bowser | 1989-08-31 | 2001-08-29 | 11 | | Chirpy | 1998-09-11 | 2001-08-29 | 2 | | Whistler | 1997-12-09 | 2001-08-29 | 3 | | Slim | 1996-04-29 | 2001-08-29 | 5 | | Puffball | 1999-03-30 | 2001-08-29 | 2 | +----------+------------+--------------+------+
Hier zieht YEAR() den Jahresanteil eines
Datums heraus. RIGHT() zieht die rechts
stehenden fünf Zeichen heraus, die für den
MM-DD-Teil des Datums stehen. Der Teil in
dem Ausdruck, der die MM-DD-Werte
vergleicht, wird zu 1 oder 0 ausgewertet, was die
Jahresdifferenz ein Jahr nach unten anpasst, wenn
CURRENT_DATE früher im Jahr erscheint als
geburtstag. Der gesamte Ausdruck ist als
Überschrift etwas plump, daher wir ein Alias
(age) benutzt, um die Spaltenüberschrift
etwas lesbarer zu machen.
Die Anfrage funktioniert, aber das Ergebnis könnte leichter
überblickt werden, wenn die Zeilen in einer bestimmten
Reihenfolge angezeigt würden. Das kann man erreichen, indem
man eine ORDER BY name-Klausel hinzufügt,
um die Ausgabe nach Namen zu sortieren:
mysql>SELECT name, geburtstag, CURRENT_DATE,->(YEAR(CURRENT_DATE)-YEAR(geburtstag))->- (RIGHT(CURRENT_DATE,5)<RIGHT(geburtstag,5))->AS age->FROM pet ORDER BY name;+----------+------------+--------------+------+ | name | geburtstag | CURRENT_DATE | age | +----------+------------+--------------+------+ | Bowser | 1989-08-31 | 2001-08-29 | 11 | | Buffy | 1989-05-13 | 2001-08-29 | 12 | | Chirpy | 1998-09-11 | 2001-08-29 | 2 | | Claws | 1994-03-17 | 2001-08-29 | 7 | | Fang | 1990-08-27 | 2001-08-29 | 11 | | Fluffy | 1993-02-04 | 2001-08-29 | 8 | | Puffball | 1999-03-30 | 2001-08-29 | 2 | | Slim | 1996-04-29 | 2001-08-29 | 5 | | Whistler | 1997-12-09 | 2001-08-29 | 3 | +----------+------------+--------------+------+
Um die Ausgabe nach Alter (age) statt nach
name zu sortieren, benutzen Sie einfach
eine andere ORDER BY-Klausel:
mysql>SELECT name, geburtstag, CURRENT_DATE,->(YEAR(CURRENT_DATE)-YEAR(geburtstag))->- (RIGHT(CURRENT_DATE,5)<RIGHT(geburtstag,5))->AS age->FROM pet ORDER BY age;+----------+------------+--------------+------+ | name | geburtstag | CURRENT_DATE | age | +----------+------------+--------------+------+ | Chirpy | 1998-09-11 | 2001-08-29 | 2 | | Puffball | 1999-03-30 | 2001-08-29 | 2 | | Whistler | 1997-12-09 | 2001-08-29 | 3 | | Slim | 1996-04-29 | 2001-08-29 | 5 | | Claws | 1994-03-17 | 2001-08-29 | 7 | | Fluffy | 1993-02-04 | 2001-08-29 | 8 | | Fang | 1990-08-27 | 2001-08-29 | 11 | | Bowser | 1989-08-31 | 2001-08-29 | 11 | | Buffy | 1989-05-13 | 2001-08-29 | 12 | +----------+------------+--------------+------+
Eine ähnliche Anfrage kann benutzt werden, um das Alter am
Sterbetag bei Tieren festzustellen, die gestorben sind. Das
können Sie feststellen, indem Sie überprüfen, ob der
sterbetag-Wert NULL ist.
Dann berechnen Sie für diejenigen Tiere mit
Nicht-NULL-Werten den Unterschied zwischen
sterbetag- und
geburtstag-Werten:
mysql>SELECT name, geburtstag, sterbetag,->(YEAR(sterbetag)-YEAR(geburtstag)) - (RIGHT(sterbetag,5)<RIGHT(geburtstag,5))->AS age->FROM pet WHERE sterbetag IS NOT NULL ORDER BY age;+--------+------------+------------+------+ | name | geburtstag | sterbetag | age | +--------+------------+------------+------+ | Bowser | 1989-08-31 | 1995-07-29 | 5 | +--------+------------+------------+------+
Die Anfrage benutzt sterbetag IS NOT NULL
statt sterbetag != NULL, weil
NULL ein spezieller Wert ist. Das wird
später erklärt. See Abschnitt 4.3.4.6, „Mit NULL-Werten arbeiten“.
Was ist, wenn Sie wissen wollen, welche Tiere nächsten Monat
Geburtstag haben? Für diese Art von Berechnung sind Jahre und
Tage irrelevant. Sie wollen lediglich den Monatsanteil der
geburtstag-Spalte extrahieren. MySQL bietet
etliche Funktionen für die Extraktion von Datumsanteilen, wie
YEAR(), MONTH() und
DAYOFMONTH(). MONTH()
ist hier die richtige Funktion. Um festzustellen, wie sie
funktioniert, geben Sie eine Anfrage ein, die sowohl die Werte
von geburtstag als auch die von
MONTH(geburtstag) ausgibt:
mysql> SELECT name, geburtstag, MONTH(geburtstag) FROM pet;
+----------+------------+-------------------+
| name | geburtstag | MONTH(geburtstag) |
+----------+------------+-------------------+
| Fluffy | 1993-02-04 | 2 |
| Claws | 1994-03-17 | 3 |
| Buffy | 1989-05-13 | 5 |
| Fang | 1990-08-27 | 8 |
| Bowser | 1989-08-31 | 8 |
| Chirpy | 1998-09-11 | 9 |
| Whistler | 1997-12-09 | 12 |
| Slim | 1996-04-29 | 4 |
| Puffball | 1999-03-30 | 3 |
+----------+------------+-------------------+
Tiere mit Geburtstagen im kommenden Monat zu finden ist
ebenfalls leicht. Nehmen wir an, der aktuelle Monat ist April.
Dann ist der Monatswert 4 und Sie suchen
nach Tieren, die im Mai (Monat 5) geboren sind, wie folgt:
mysql> SELECT name, geburtstag FROM pet WHERE MONTH(geburtstag) = 5;
+-------+------------+
| name | geburtstag |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
Ein bisschen komplizierter ist es, wenn der aktuelle Monat
Dezember ist. Hier können Sie nicht einfach eins zur
Monatszahl (12) hinzufügen, weil es keinen
13. Monat gibt. Statt dessen suchen Sie nach Tieren, die im
Januar (Monat 1) geboren sind.
Sie können die Anfrage sogar so schreiben, dass sie
unabhängig davon funktioniert, was der aktuelle Monat ist.
Auf diese Art brauchen Sie keine bestimmte Monatszahl in der
Anfrage benutzen. DATE_ADD() erlaubt Ihnen,
einem gegebenen Datum ein Zeitintervall hinzuzufügen. Wenn
Sie dem Wert von NOW() einen Monat
hinzufügen und dann den Monatsanteil mit
MONTH() extrahieren, ergibt das den Monat,
der die kommenden Geburtstage enthält:
mysql>SELECT name, geburtstag FROM pet->WHERE MONTH(geburtstag) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));
Eine andere Möglichkeit, diese Aufgabe zu erfüllen, ist,
1 zu addieren, um den nächsten Monat nach
dem aktuellen zu erhalten (nach Gebrauch der Modulo-Funktion
(MOD), um den Monatswert auf
0 zu stellen, falls er aktuell
12) ist:
mysql>SELECT name, geburtstag FROM pet->WHERE MONTH(geburtstag) = MOD(MONTH(NOW()), 12) + 1;
MONTH gibt eine Zahl zwischen 1 und 12
zurück. MOD(irgendwas,12) gibt eine Zahl
zwischen 0 und 11 zurück. Daher muss die Addition nach
MOD() erfolgen, weil wir ansonsten von
November (11) bis Januar (1) gehen würden.
Der NULL-Wert birgt Überraschungen, bis
Sie mit ihm vertraut sind. Konzeptionell bedeutet
NULL einen fehlenden oder unbekannten Wert.
Er wird in einiger Hinsicht anders als andere Werte behandelt.
Um auf NULL zu testen, können Sie nicht
die arithmetischen Vergleichoperatoren wie
=, < oder
!= verwenden. Um sich das zu
veranschaulichen, probieren Sie folgenden Anfrage:
mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 != NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
Wie man sieht, erhält man aus diesen Vergleichen keine
sinnvollen Ergebnisse. Benutzen Sie statt dessen die
IS NULL- und IS NOT
NULL-Operatoren:
mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
| 0 | 1 |
+-----------+---------------+
In MySQL bedeutet 0 oder NULL logisch
Falsch und alles sonstige bedeutet logisch Wahr. Der
vorgabemäßige Wahrheitswert einer Boolschen Operation ist 1.
Diese besondere Behandlung von NULL ist der
Grund, warum es im vorherigen Abschnitt notwendig war, mit
sterbetag IS NOT NULL anstelle von
sterbetag != NULL festzustellen, welche
Tiere nicht mehr leben.
MySQL stellt Standard-SQL-Suchmuster-Übereinstimmung zur
Verfügung, ebenso wie eine Art der
Suchmuster-Übereinstimmung, die auf regulären Ausdrücken
basiert, die denen ähnlich sind, die von Unix-Hilfsprogrammen
wie vi, grep und
sed benutzt werden.
SQL-Suchmuster-Übereinstimmung gestattet Ihnen,
‘_’ zu benutzen, um ein
einzelnes Zeichen und ‘%’, um
eine beliebige Anzahl von Zeichen (inklusive des 0-Zeichens)
zu finden. In den MySQL-SQL-Suchmustern spielt die
Groß-/Kleinschreibung vorgabemäßig keine Rolle. Einige
Beispiele sind unten dargestellt. Beachten Sie, dass Sie
= oder != nicht benutzen
können, wenn Sie SQL-Suchmuster benutzen. Stattdessen müssen
Sie die LIKE- oder NOT
LIKE-Vergleichsoperatoren benutzen.
So finden Sie Namen, die mit
‘b’ anfangen:
mysql> SELECT * FROM pet WHERE name LIKE "b%";
+--------+----------+------+------------+------------+------------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+--------+----------+------+------------+------------+------------+
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
+--------+----------+------+------------+------------+------------+
So finden Sie Namen, die auf
‘fy’ enden:
mysql> SELECT * FROM pet WHERE name LIKE "%fy";
+--------+----------+-------+------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+--------+----------+-------+------------+------------+-----------+
| Fluffy | Harold | Katze | w | 1993-02-04 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+--------+----------+-------+------------+------------+-----------+
So finden Sie Namen, die ‘w’
enthalten:
mysql> SELECT * FROM pet WHERE name LIKE "%w%";
+----------+----------+---------+-------------+------------+------------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+----------+----------+---------+-------------+------------+------------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
+----------+----------+---------+-------------+------------+------------+
Um Namen zu finden, die genau fünf Zeichen enthalten,
benutzen Sie das
‘_’-Suchmuster-Zeichen:
mysql> SELECT * FROM pet WHERE name LIKE "_____";
+-------+----------+---------+-------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+-------+----------+---------+-------------+------------+-----------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+----------+---------+-------------+------------+-----------+
Die andere Art von Suchmuster-Übereinstimmung benutzt
erweiterte reguläre Ausdrücke. Wenn Sie bei dieser Art von
Suchmuster auf Übereinstimmung prüfen, benutzen Sie die
REGEXP- und NOT
REGEXP-Operatoren (oder RLIKE und
NOT RLIKE, die synonym sind).
Einige Charakteristika erweiterter regulärer Ausdrücke sind:
‘.’ findet jedes beliebige
Zeichen.
Eine Zeichenklasse ‘[...]’
findet jedes Zeichen innerhalb der eckigen Klammern. So
stimmt zum Beispiel ‘[abc]’
mit ‘a’,
‘b’ oder
‘c’ überein. Um einen
Bereich von Zeichen zu benennen, benutzen Sie einen
Bindestrich. ‘[a-z]’ stimmt
mit jedem Buchstaben in Kleinschreibung überein,
wohingegen ‘[0-9]’ mit
jeder Ziffer übereinstimmt.
‘*’ stimmt mit null oder
mehr Instanzen der Sache überein, die ihm voransteht.
‘x*’ zum Beispiel stimmt
mit einer beliebigen Anzahl von
‘x’-Zeichen überein.
‘[0-9]*’ stimmt mit einer
beliebigen Anzahl von Ziffern überein, und
‘.*’ mit jeder Anzahl von
irgendetwas.
Reguläre Ausdrücke achten auf Groß-/Kleinschreibung,
aber Sie können eine Zeichenklasse benutzen, um beide
Schreibungen zu finden, wenn Sie wollen.
‘[aA]’ zum Beispiel stimmt
mit ‘a’ in Groß- und
Kleinschreibung überein und
‘[a-zA-Z]’ mit jedem
Buchstaben in Groß- und Kleinschreibung.
Das Suchmuster stimmt überein, wenn es irgendwo in dem Wert auftaucht, der überprüft wird. (SQL-Suchmuster stimmen nur überein, wenn sie mit dem gesamten Wert übereinstimmen.)
Um ein Suchmuster so zu verankern, dass er mit dem Anfang
oder dem Ende des überprüften Werts übereinstimmen
muss, benutzen Sie ‘^’ am
Anfang oder ‘$’ am Ende des
Suchmusters.
Um darzustellen, wie erweiterte reguläre Ausdrücke
funktionieren, werden die LIKE-Anfragen von
oben noch einmal mit REGEXP gezeigt.
Um Namen zu finden, die mit ‘b’
anfangen, benutzen Sie ‘^’, um
auf Übereinstimmung am Anfang des Namens zu prüfen:
mysql> SELECT * FROM pet WHERE name REGEXP "^b";
+--------+-----------+---------+-------------+------------+------------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+--------+-----------+---------+-------------+------------+------------+
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
+--------+-----------+---------+-------------+------------+------------+
Vor MySQL-Version 3.23.4 achtet REGEXP auf
Groß-/Kleinschreibung. Daher gibt diese Anfrage ein Ergebnis
ohne Zeilen zurück. Um sowohl Groß- als auch Kleinschreibung
von ‘b’ zu finden, benutzen Sie
statt dessen folgende Anfrage:
mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";
Ab MySQL 3.23.4 müssen Sie, um die Beachtung der
Groß-/Kleinschreibung in einem
REGEXP-Vergleich zu erzwingen, das
BINARY-Schlüsselwort verwenden, um eine
der Zeichenketten zu einer binären Zeichenkette zu machen.
Diese Anfrage stimmt nur mit
‘b’ in Kleinschreibung am
Anfang eines Namens überein:
mysql> SELECT * FROM pet WHERE name REGEXP BINARY "^b";
Um Namen zu finden, die auf
‘fy’ enden, benutzen Sie
‘$’, um Übereinstimmung am
Ende des Namens zu finden:
mysql> SELECT * FROM pet WHERE name REGEXP "fy$";
+--------+-----------+---------+-------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+--------+-----------+---------+-------------+------------+-----------+
| Fluffy | Harold | Katze | w | 1993-02-04 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+--------+-----------+---------+-------------+------------+-----------+
Um Namen zu finden, die ‘w’ in
Groß- oder Kleinschreibung enthalten, benutzen Sie diese
Anfrage:
mysql> SELECT * FROM pet WHERE name REGEXP "w";
+----------+----------+---------+-------------+------------+------------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+----------+----------+---------+-------------+------------+------------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Bowser | Diane | Hund | m | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
+----------+----------+---------+-------------+------------+------------+
Weil ein Suchmuster mit regulären Ausdrücken an beliebiger Stelle im Wert gefunden wird, ist es bei der vorherigen Anfrage nicht notwendig, ein Jokerzeichen (Wildcard) auf irgendeine Seite des Suchmusters zu setzen, um nach Übereinstimmung im gesamten Wert zu suchen, wie es bei SQL-Suchmustern der Fall sein müsste.
Um Namen zu finden, die genau fünf Zeichen enthalten,
benutzen Sie ‘^’ und
‘$’, um mit Anfang und Ende des
Namens Übereinstimmung zu finden, und fünf Instanzen von
‘.’ dazwischen:
mysql> SELECT * FROM pet WHERE name REGEXP "^.....$";
+-------+-----------+---------+-------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+-------+-----------+---------+-------------+------------+-----------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+-----------+---------+-------------+------------+-----------+
Sie könnten die vorherige Anfrage auch unter Verwendung des
‘{n}’-
``wiederhole-n-mal''-Operators schreiben:
mysql> SELECT * FROM pet WHERE name REGEXP "^.{5}$";
+-------+-----------+---------+-------------+------------+-----------+
| name | besitzer | art | geschlecht | geburtstag | sterbetag |
+-------+-----------+---------+-------------+------------+-----------+
| Claws | Gwen | Katze | m | 1994-03-17 | NULL |
| Buffy | Harold | Hund | w | 1989-05-13 | NULL |
+-------+-----------+---------+-------------+------------+-----------+
Datenbanken werden oft benutzt, um die Frage zu beantworten, wie oft eine bestimmte Art von Daten in einer Tabelle erscheint. Sie wollen beispielsweise wissen, wie viele Haustiere Sie haben, oder wie viele Haustiere jeder Besitzer hat, oder Sie wollen verschiedene Arten von Zählungen Ihrer Tiere durchführen.
Die Gesamtzahl der Tiere zählen, die Sie haben, ist dieselbe
Frage wie ``Wie viele Zeilen sind in der
pet-Tabelle?'', denn es gibt einen
Datensatz pro Haustier. Die
COUNT()-Funktion zählt die Anzahl von
Nicht-NULL-Ergebnissen, daher lautet die
Anfrage, um Ihre Tiere zu zählen, wie folgt:
mysql> SELECT COUNT(*) FROM pet;
+----------+
| COUNT(*) |
+----------+
| 9 |
+----------+
Sie haben vorher schon einmal die Namen der Leute abgefragt,
die Haustiere besitzen. Sie können COUNT()
benutzen, wenn Sie herausfinden wollen, wie viele Tiere jeder
Besitzer hat:
mysql> SELECT besitzer, COUNT(*) FROM pet GROUP BY besitzer;
+-----------+----------+
| besitzer | COUNT(*) |
+-----------+----------+
| Benny | 2 |
| Diane | 2 |
| Gwen | 3 |
| Harold | 2 |
+-----------+----------+
Beachten Sie die Benutzung von GROUP BY, um
alle Datensätze für jeden besitzer zu
gruppieren. Ohne das erhalten Sie eine Fehlermeldung:
mysql> SELECT besitzer, COUNT(besitzer) FROM pet;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause
COUNT() und GROUP BY
sind nützlich, um Ihre Daten auf verschiedene Weise zu
charakterisieren. Die folgenden Beispiele zeigen verschiedene
Möglichkeiten, um Zählungen Ihrer Tiere durchzuführen.
Anzahl der Tiere pro Art:
mysql> SELECT art, COUNT(*) FROM pet GROUP BY art;
+---------+----------+
| art | COUNT(*) |
+---------+----------+
| Vogel | 2 |
| Katze | 2 |
| Hund | 3 |
| Hamster | 1 |
| Schlange| 1 |
+---------+----------+
Anzahl der Tiere pro Geschlecht:
mysql> SELECT geschlecht, COUNT(*) FROM pet GROUP BY geschlecht;
+-------------+----------+
| geschlecht | COUNT(*) |
+-------------+----------+
| NULL | 1 |
| w | 4 |
| m | 4 |
+-------------+----------+
(In dieser Ausgabe zeigt NULL an, dass das
Geschlecht unbekannt ist.)
Anzahl der Tiere pro Kombination von Art und Geschlecht:
mysql> SELECT art, geschlecht, COUNT(*) FROM pet GROUP BY art, geschlecht;
+---------+-------------+----------+
| art | geschlecht | COUNT(*) |
+---------+-------------+----------+
| Vogel | NULL | 1 |
| Vogel | w | 1 |
| Katze | w | 1 |
| Katze | m | 1 |
| Hund | w | 1 |
| Hund | m | 2 |
| Hamster | w | 1 |
| Schlange| m | 1 |
+---------+-------------+----------+
Sie müssen nicht die gesamte Tabelle abfragen, wenn Sie
COUNT() benutzen. Die vorherige Anfrage
beispielsweise sieht lediglich für Hunde und Katzen wie folgt
aus:
mysql>SELECT art, geschlecht, COUNT(*) FROM pet->WHERE art = "Hund" OR art = "Katze"->GROUP BY art, geschlecht;+---------+-------------+----------+ | art | geschlecht | COUNT(*) | +---------+-------------+----------+ | Katze | w | 1 | | Katze | m | 1 | | Hund | w | 1 | | Hund | m | 2 | +---------+-------------+----------+
Oder wenn Sie die Anzahl von Tieren pro Geschlecht wissen wollen, beschränkt auf die Tiere, deren Geschlecht bekannt ist:
mysql>SELECT art, geschlecht, COUNT(*) FROM pet->WHERE geschlecht IS NOT NULL->GROUP BY art, geschlecht;+---------+-------------+----------+ | art | geschlecht | COUNT(*) | +---------+-------------+----------+ | Vogel | w | 1 | | Katze | w | 1 | | Katze | m | 1 | | Hund | w | 1 | | Hund | m | 2 | | Hamster | w | 1 | | Schlange| m | 1 | +---------+-------------+----------+
In der pet-Tabelle behalten Sie die
Übersicht über Ihre Haustiere. Wenn Sie weitere
Informationen über sie aufzeichnen wollen, beispielsweise
Ereignisse in ihrem Leben wie Besuche beim Tierarzt oder wenn
Nachwuchs zur Welt kommt, brauchen Sie eine weitere Tabelle.
Wie sollte diese aussehen? Sie benötigt:
Den Namen des Haustiers, damit Sie wissen, auf welches Tier sich jedes Ereignis bezieht.
Ein Datum, damit Sie wissen, wann sich das Ereignis zugetragen hat.
Ein Feld, um das Ereignis zu beschreiben.
Ein Feld für den Typ des Ereignisses, wenn Sie in der Lage sein wollen, Ereignisse zu kategorisieren.
Nach diesen Vorüberlegungen könnte das CREATE
TABLE-Statement für die
ereignis-Tabelle wie folgt aussehen:
mysql>CREATE TABLE ereignis (name VARCHAR(20), datum DATE,->typ VARCHAR(15), bemerkung VARCHAR(255));
Wie bei der pet-Tabelle ist es am
einfachsten, die anfänglichen Datensätze mit Hilfe einer
TAB-getrennten Textdatei einzuladen, die folgende
Informationen enthält:
| Fluffy | 1995-05-15 | Nachwuchs | 4 Kätzchen, 3 weiblich, 1 männlich |
| Buffy | 1993-06-23 | Nachwuchs | 5 Hündchen, 2 weiblich, 3 männlich |
| Buffy | 1994-06-19 | Nachwuchs | 3 Hündchen, 3 weiblich |
| Chirpy | 1999-03-21 | Tierarzt | Schnabel gerade gebogen |
| Slim | 1997-08-03 | Tierarzt | Gebrochene Rippe |
| Bowser | 1991-10-12 | Zwinger | |
| Fang | 1991-10-12 | Zwinger | |
| Fang | 1998-08-28 | Geburtstag | Geschenk: neues Kauspielzeug |
| Claws | 1998-03-17 | Geburtstag | Geschenk: neues Flohhalsband |
| Whistler | 1998-12-09 | Geburtstag | Erster Geburtstag |
Laden Sie die Datensätze wie folgt ein:
mysql> LOAD DATA LOCAL INFILE "ereignis.txt" INTO TABLE ereignis;
Auf der Grundlage dessen, was Sie durch die Abfragen der
pet-Tabelle gelernt haben, sollten sie in
der Lage sein, Abfragen der Datensätze der
ereignis-Tabelle durchzuführen, was
prinzipiell dasselbe ist. Aber wann ist die
ereignis-Tabelle allein nicht ausreichend,
um Fragen zu beantworten, die Sie stellen könnten?
Nehmen wir an, Sie wollen herausfinden, wie alt jedes Haustier
war, als es Nachwuchs bekam. In der
ereignis-Tabelle steht, wann das geschah,
aber um das Alter der Mutter auszurechnen, wird ihr Geburtstag
benötigt. Weil dieser in der pet-Tabelle
steht, brauchen Sie für diese Anfrage beide Tabellen:
mysql>SELECT pet.name, (TO_DAYS(datum) - TO_DAYS(geburtstag))/365 AS age,anmerkung->FROM pet, ereignis->WHERE pet.name = ereignis.name AND typ = "Nachwuchs";+--------+------+------------------------------------+ | name | age | anmerkung | +--------+------+------------------------------------+ | Fluffy | 2.27 | 4 kätzchen, 3 weiblich, 1 männlich | | Buffy | 4.12 | 5 hündchen, 2 weiblich, 3 männlich | | Buffy | 5.10 | 3 hündchen, 3 weiblich | +--------+------+------------------------------------+
Zu dieser Anfrage gibt es einiges anzumerken:
In der FROM-Klausel stehen zwei
Tabellen, weil die Anfrage aus beiden Tabellen
Informationen herausziehen muss.
Wenn Sie Informationen aus mehreren Tabellen verbinden
(englisch: join), müssen Sie angeben, wie Datensätze in
der einen Tabelle mit solchen in der anderen Tabelle in
Übereinstimmung gebracht werden können. Das ist einfach,
weil beide eine name-Spalte haben. Die
Anfrage benutzt die WHERE-Klausel, um
Datensätze beider Tabellen basierend auf den
name-Werten in Übereinstimmung zu
bringen.
Weil die name-Spalte in beiden Tabellen
vorkommt, müssen Sie angeben, welche Tabelle Sie meinen,
wenn Sie auf die Spalte verweisen. Das wird gemacht, indem
dem Spaltennamen der Tabellenname voran gestellt wird.
Sie müssen nicht unbedingt zwei verschiedene Tabellen haben,
um eine Verknüpfung (Join) durchzuführen. Manchmal ist es
nützlich, eine Tabelle mit sich selbst zu verknüpfen, wenn
Sie nämlich Datensätze in einer Tabelle mit Datensätze in
derselben Tabelle vergleichen wollen. Um zum Beispiel
Zuchtpaare unter Ihren Haustieren zu finden, können Sie die
pet-Tabelle mit sich selbst verknüpfen, um
Paare von männlichen und weiblichen Tieren derselben Art
zusammen zu bringen:
mysql>SELECT p1.name, p1.geschlecht, p2.name, p2.geschlecht, p1.art->FROM pet AS p1, pet AS p2->WHERE p1.art = p2.art AND p1.geschlecht = "w" AND p2.geschlecht = "m";+--------+-------------+--------+-------------+---------+ | name | geschlecht | name | geschlecht | art | +--------+-------------+--------+-------------+---------+ | Fluffy | w | Claws | m | Katze | | Buffy | w | Fang | m | Hund | | Buffy | w | Bowser | m | Hund | +--------+-------------+--------+-------------+---------+
In dieser Anfrage legen wir Aliase für den Tabellennamen fest, um auf die Spalten verweisen zu können und um auseinander zu halten, auf welche Instanz der Tabelle sich jede Spaltenreferenz bezieht.
Was ist, wenn Sie den Namen einer Datenbank oder Tabelle vergessen haben oder für eine gegebene Tabelle die Struktur nicht mehr kennen (wie zum Beispiel die Spalten heißen)? MySQL löst solcherlei Probleme mit diversen Statements, die Informationen über die Datenbanken und Tabellen bereitstellen, die es unterstützt.
SHOW DATABASES kennen Sie schon. Dieses listet
die Datenbanken auf, die vom Server verwaltet werden. Um
herauszufinden, welche Datenbank aktuell ausgewählt ist, benutzen
Sie die DATABASE()-Funktion:
mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie |
+------------+
Wenn Sie noch keine Datenbank ausgewählt haben, ist das Ergebnis leer.
Um herauszufinden, welche Tabellen die aktuelle Datenbank enthält (wenn Sie sich zum Beispiel über den Namen einer Tabelle nicht sicher sind), benutzen Sie folgenden Befehl:
mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| ereignis |
| pet |
+---------------------+
Wenn Sie die Struktur einer Tabelle sehen wollen, ist der
DESCRIBE-Befehl nützlich. Er zeigt
Informationen über jede Tabellenspalte an:
mysql> DESCRIBE pet;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| besitzer | varchar(20) | YES | | NULL | |
| art | varchar(20) | YES | | NULL | |
| geschlecht | char(1) | YES | | NULL | |
| geburtstag | date | YES | | NULL | |
| sterbetag | date | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
Field zeigt den Spaltennamen,
Type ist der Datentyp der Spalte,
Null zeigt an, ob die Spalte
NULL-Werte enthalten darf oder nicht,
Key zeigt an, ob die Spalte indiziert ist oder
nicht und Default legt den Vorgabewert der
Spalte fest.
Wenn Sie Indexe auf eine Tabelle haben, zeigt Ihnen SHOW
INDEX FROM tabelle Informationen über diese an.
Hier finden sich Beispiele, wie geläufige Probleme mit MySQL gelöst werden können.
Einige der Beispiele benutzen die Tabelle shop,
die den Stückpreis für jeden Artikel für bestimmte Händler
enthält. Unter der Annahme, dass jeder Händler einen einzelnen
fest Preis pro Artikel hat, ist (artikel,
haendler) der Primärschlüssel für diese
Datensätze.
Starten Sie das Kommandozeilen-Werkzeug mysql
und wählen Sie eine Datenbank aus:
mysql ihr-datenbank-name
(Bei den meisten MySQL-Installationen können Sie die Datenbank 'test' auswählen.)
Erzeugen Sie die Beispiel-Tabelle wie folgt:
CREATE TABLE shop ( artikel INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, haendler CHAR(20) DEFAULT '' NOT NULL, preis DOUBLE(16,2) DEFAULT '0.00' NOT NULL, PRIMARY KEY(artikel, haendler)); INSERT INTO shop VALUES (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3,'C',1.69), (3,'D',1.25),(4,'D',19.95);
Die Beispieldaten sehen jetzt so aus:
mysql> SELECT * FROM shop;
+---------+---------+-------+
| artikel | haendler| preis |
+---------+---------+-------+
| 0001 | A | 3.45 |
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | B | 1.45 |
| 0003 | C | 1.69 |
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+---------+-------+
``Was ist die höchste Artikelnummer?''
SELECT MAX(artikel) AS artikel FROM shop +---------+ | artikel | +---------+ | 4 | +---------+
``Suche Artikelnummer, Händler und Preis des teuersten Artikels.''
In ANSI-SQL wird das mit einer Unterabfrage (Sub-Query) durchgeführt:
SELECT artikel, haendler, preis FROM shop WHERE preis=(SELECT MAX(preis) FROM shop)
In MySQL (was noch keine Unterabfragen hat) führen Sie das in zwei Schritten durch:
Mit einem SELECT-Statement ermitteln Sie
den höchsten Preis in der Tabelle.
Mit diesem Wert stellen Sie die aktuelle Anfrage zusammen:
SELECT artikel, haendler, preis FROM shop WHERE preis=19.95
Eine andere Lösung besteht darin, alle Zeilen absteigend nach
Preis zu sortieren und nur die erste Zeile zu nehmen, indem Sie
die MySQL-spezifische LIMIT-Klausel benutzen:
SELECT artikel, haendler, preis FROM shop ORDER BY preis DESC LIMIT 1
ACHTUNG: Wenn es mehrere
teuerste Artikel gibt (die zum Beispiel alle 19.95 kosten),
zeigt die LIMIT-Lösung nur einen davon!
``Was ist der höchste Preis pro Artikel?''
SELECT artikel, MAX(preis) AS preis FROM shop GROUP BY artikel +---------+-------+ | artikel | preis | +---------+-------+ | 0001 | 3.99 | | 0002 | 10.99 | | 0003 | 1.69 | | 0004 | 19.95 | +---------+-------+
``Suche für jeden Artikel den oder die Händler mit den teuersten Preisen.''
In ANSI-SQL würden Sie das wie folgt mit einer Unterabfrage erledigen:
SELECT artikel, haendler, preis
FROM shop s1
WHERE preis=(SELECT MAX(s2.preis)
FROM shop s2
WHERE s1.artikel = s2.artikel);
In MySQL macht man das am besten in mehreren Schritten:
Die Liste (artikel,maxpreis) holen.
Für jeden Artikel die korrespondierenden Zeilen holen, die den höchsten Preis gespeichert haben.
Das kann auf einfache Weise mit einer temporären Tabelle geschehen:
CREATE TEMPORARY TABLE tmp (
artikel INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
preis DOUBLE(16,2) DEFAULT '0.00' NOT NULL);
LOCK TABLES shop read;
INSERT INTO tmp SELECT artikel, MAX(preis) FROM shop GROUP BY artikel;
SELECT shop.artikel, haendler, shop.preis FROM shop, tmp
WHERE shop.artikel=tmp.artikel AND shop.preis=tmp.preis;
UNLOCK TABLES;
DROP TABLE tmp;
Wenn Sie keine TEMPORARY-Tabelle benutzen,
müssen Sie zusätzlich die 'tmp'-Tabelle sperren.
``Kann das mit einer einzigen Anfrage durchgeführt werden?''
Ja, aber nur unter Verwendung eines recht ineffizienten Tricks, den wir den ``MAX-CONCAT-Trick'' nennen:
SELECT artikel,
SUBSTRING( MAX( CONCAT(LPAD(preis,6,'0'),haendler) ), 7) AS haendler,
0.00+LEFT( MAX( CONCAT(LPAD(preis,6,'0'),haendler) ), 6) AS preis
FROM shop
GROUP BY artikel;
+---------+---------+-------+
| artikel | haendler| preis |
+---------+---------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+---------+-------+
Das letzte Beispiel kann etwas effizienter gemacht werden, wenn man das Aufteilen der verketteten Spalte im Client durchführt.
Sie können MySQL-Benutzer-Variablen verwenden, um Ergebnisse zwischenzuspeichern, ohne sie in temporäre Variablen im Client speichern zu müssen. See Abschnitt 7.1.4, „Benutzer-Variablen“.
Um zum Beispiel die Artikel mit dem höchsten und dem niedrigsten Preis herauszufinden, können Sie folgendes machen:
select @min_preis:=min(preis),@max_preis:=max(preis) from shop; select * from shop where preis=@min_preis or preis=@max_preis; +---------+---------+-------+ | artikel | haendler| preis | +---------+---------+-------+ | 0003 | D | 1.25 | | 0004 | D | 19.95 | +---------+---------+-------+
Sie brauchen keine Fremdschlüssel, um zwei Tabellen zu verknüpfen.
Das einzige, was MySQL nicht durchführt, ist der
CHECK, um sicherzustellen, dass die
Schlüssel, die Sie benutzen, in der oder den Tabelle(n)
existieren, auf die Sie verweisen, und es löscht auch nicht
automatisch Zeilen aus einer Tabelle mit einer
Fremdschlüssel-Definition. Wenn Sie Ihre Schlüssel wie
gewöhnlich benutzen, funktioniert das gut:
CREATE TABLE personen (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE hemden (
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
stil ENUM('t-shirt', 'polo', 'dress') NOT NULL,
farbe ENUM('rot', 'blau', 'orange', 'weiß', 'schwarz') NOT NULL,
besitzer SMALLINT UNSIGNED NOT NULL references personen,
PRIMARY KEY (id)
);
INSERT INTO personen VALUES (NULL, 'Antonio Paz');
INSERT INTO hemden VALUES
(NULL, 'polo', 'blau', LAST_INSERT_ID()),
(NULL, 'dress', 'weiß', LAST_INSERT_ID()),
(NULL, 't-shirt', 'blau', LAST_INSERT_ID());
INSERT INTO personen VALUES (NULL, 'Lilliana Angelovska');
INSERT INTO hemden VALUES
(NULL, 'dress', 'orange', LAST_INSERT_ID()),
(NULL, 'polo', 'rot', LAST_INSERT_ID()),
(NULL, 'dress', 'blau', LAST_INSERT_ID()),
(NULL, 't-shirt', 'weiß', LAST_INSERT_ID());
SELECT * FROM personen;
+----+---------------------+
| id | name |
+----+---------------------+
| 1 | Antonio Paz |
| 2 | Lilliana Angelovska |
+----+---------------------+
SELECT * FROM hemden;
+----+---------+--------+----------+
| id | stil | farbe | besitzer |
+----+---------+--------+----------+
| 1 | polo | blau | 1 |
| 2 | dress | weiß | 1 |
| 3 | t-shirt | blau | 1 |
| 4 | dress | orange | 2 |
| 5 | polo | rot | 2 |
| 6 | dress | blau | 2 |
| 7 | t-shirt | weiß | 2 |
+----+---------+--------+----------+
SELECT h.* FROM personen p, hemden h
WHERE p.name LIKE 'Lilliana%'
AND h.besitzer = p.id
AND h.farbe <> 'weiß';
+----+-------+--------+----------+
| id | stil | farbe | besitzer |
+----+-------+--------+----------+
| 4 | dress | orange | 2 |
| 5 | polo | rot | 2 |
| 6 | dress | blau | 2 |
+----+-------+--------+----------+
MySQL optimiert derzeit noch nicht, wenn Sie über zwei
unterschiedliche Schlüssel suchen, die mit
OR kombiniert werden (eine Suche mit einem
Schlüssel mit verschiedenen OR-Teilen wird
recht gut optimiert):
SELECT feld1_index, feld2_index FROM test_tabelle WHERE feld1_index = '1' OR feld2_index = '1'
Der Grund liegt darin, dass wir bislang noch keine Zeit hatten,
hierfür eine effiziente Möglichkeit zu implementieren, die das
für allgemeine Fälle abhandelt. (Die
AND-Handhabung ist im Vergleich jetzt
komplett allgemein und funktioniert sehr gut.)
In der Zwischenzeit können Sie dieses Problem sehr effizient
lösen, indem Sie eine TEMPORARY-Tabelle
verwenden. Diese Art der Optimierung ist ebenfalls sehr gut,
wenn Sie sehr komplizierte Anfragen verwenden, bei denen der
SQL-Server die Optimierungen in falscher Reihenfolge
durchführt.
CREATE TEMPORARY TABLE tmp SELECT feld1_index, feld2_index FROM test_tabelle WHERE feld1_index = '1'; INSERT INTO tmp SELECT feld1_index, feld2_index FROM test_tabelle WHERE feld2_index = '1'; SELECT * from tmp; DROP TABLE tmp;
Diese Möglichkeit der Anfrage ist im Endeffekt ein
UNION von zwei Anfragen.
Folgendes zeigt, wie Sie die Bit-Gruppen-Funktionen benutzen können, um die Anzahl der Tage pro Monat zu zählen, in denen ein Benutzer eine Web-Seite besucht hat.
CREATE TABLE t1 (jahr YEAR(4), monat INT(2) UNSIGNED ZEROFILL, tag INT(2) UNSIGNED ZEROFILL); INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),(2000,2,23),(2000,2,23); SELECT jahr,monat,BIT_COUNT(BIT_OR(1<<tag)) AS tage FROM t1 GROUP BY jahr,monat; Das gibt folgendes Ergebnis zurück: +------+-------+------+ | jahr | monat | tage | +------+-------+------+ | 2000 | 01 | 3 | | 2000 | 02 | 2 | +------+-------+------+
Dies berechnet, wie viele verschiedene Tage für eine gegebene Jahr-Monats-Kombination benutzt wurden, bei automatischer Entfernung doppelter Einträge (Duplikate).
In den vorherigen Abschnitten haben Sie mysql
interaktiv benutzt, um Anfragen einzugeben und die Ergebnisse zu
betrachten. Sie können mysql auch im
Stapelbetrieb benutzen. Dafür schreiben Sie dei Befehle, die Sie
ausführen wollen, in eine Datei, und teilen
mysql dann mit, seine Eingaben aus dieser Datei
zu lesen:
shell> mysql < stapel-datei
Wenn Sie auf der Kommandozeile Verbindungsparameter angeben müssen, könnte der Befehl wie folgt aussehen:
shell> mysql -h host -u user -p < stapel-datei
Enter password: ********
Wenn Sie mysql auf diese Weise benutzen,
erzeugen Sie eine Skript-Datei und führen dann das Skript aus.
Warum sollten Sie ein Skript benutzen? Hier sind ein paar Gründe:
Wenn Sie eine Anfrage wiederholt ausführen (sagen wir jeden Tag oder jede Woche), vermeiden Sie mit einem Skript, dass Sie sie jedes Mal zur Ausführung erneut eintippen müssen.
Sie können aus existierenden Anfragen neue Anfragen erzeugen, die ähnlich sind, indem Sie die Skript-Dateien kopieren und editieren.
Der Stapelbetrieb kann auch für die Entwicklung einer Anfrage
nützlich sein, insbesondere, wenn Sie mehrzeilige Befehle
oder Befehlssequenzen aus mehreren Statements entwickeln. Wenn
Sie einen Fehler machen, müssen Sie nicht alles noch einmal
tippen, sondern editieren einfach Ihr Skript, um den Fehler zu
beheben, und weisen mysql an, es erneut
auszuführen.
Wenn Sie eine Anfrage haben, die eine größere Ausgabe erzeugt, können Sie die Ausgabe durch einen Pager laufen lassen, statt zuzusehen, wie Sie über den Bildschirm flimmert:
shell> mysql < stapel-datei | more
Für weitere Verarbeitung können Sie die Ausgabe auch in eine Datei lenken:
shell> mysql < stapel-datei > mysql.ausgabe
Sie können Ihr Skript an andere Leute verteilen, so dass auch sie die Befehle laufen lassen können.
In einigen Situationen ist interaktive Benutzung nicht
angebracht, zum Beispiel dann, wenn Sie eine Anfrage durch
einen cron-Job ausführen lassen. In diesem
Fall brauchen Sie Stapelbetrieb.
Das Standard-Ausgabeformat ist anders (präziser), wenn Sie
mysql im Stapelbetrieb laufen lassen, als wenn
Sie es interaktiv nutzen. Die Ausgabe von SELECT DISTINCT
art FROM pet zum Beispiel sieht so aus, wenn Sie sie
interaktiv laufen lassen:
+---------+ | art | +---------+ | Vogel | | Katze | | Hund | | Hamster | | Schlange| +---------+
Aber wie folgt, wenn sie im Stapelbetrieb läuft:
art Vogel Katze Hund Hamster Schlange
Wenn Sie im Stapelbetrieb das interaktive Ausgabeformat haben
wollen, benutzen Sie mysql -t. Um die Befehle
auszugeben, die ausgeführt werden, benutzen Sie mysql
-vvv.
Bei Analytikerna und Lentus haben wir die Systeme und die Feldarbeit für ein großes Forschungsprojekt gemacht. Dieses Projekt ist eine Zusammenarbeit zwischen dem Institut für Umweltmedizin des Karolinska Institutes, Stockholm, und der Abteilung für klinische Forschung bei Altersprozessen und Psychologie der University of Southern California.
Das Projekt beinhaltet einen Screening-Teil, bei dem alle Zwillinge in Schweden, die älter als 65 Jahre sind, per Telefon interviewt wurden. Zwillinge, die bestimmte Kriterien erfüllen, werden im nächsten Schritt weiter untersucht. In diesem späteren Stadium werden Zwillinge, die teilnehmen wollen, von einem Arzt-Schwester-Team besucht. Einige Untersuchungen beinhalten physische und neuropsychologische Untersuchungen, Labortests, Neuroimaging, Bewertungen des psychischen Zustands und eine Sammlung der Familiengeschichten. Zusätzlich werden Daten über medizinische und umweltbedingte Risikofaktoren gesammelt.
Weitere Informationen zu den Zwillingsstudien finden Sie hier:
http://www.imm.ki.se/TWIN/TWINGREATBRITAINW.HTM
Der spätere Teil des Projekts wird mit einer Web-Schnittstelle verwaltet, die Perl und MySQL benutzt.
Jeden Abend werden alle Daten der Interviews in eine MySQL-Datenbank verschoben.
Mit folgender Anfrage wird festgelegt, wer in den zweiten Teil des Projekts geht:
select
concat(p1.id, p1.tvab) + 0 as tvid,
concat(p1.christian_name, " ", p1.surname) as Name,
p1.postal_code as Code,
p1.city as City,
pg.abrev as Area,
if(td.participation = "Aborted", "A", " ") as A,
p1.dead as dead1,
l.event as event1,
td.suspect as tsuspect1,
id.suspect as isuspect1,
td.severe as tsevere1,
id.severe as isevere1,
p2.dead as dead2,
l2.event as event2,
h2.nurse as nurse2,
h2.doctor as doctor2,
td2.suspect as tsuspect2,
id2.suspect as isuspect2,
td2.severe as tsevere2,
id2.severe as isevere2,
l.finish_date
from
twin_project as tp
/* For Twin 1 */
left join twin_data as td on tp.id = td.id and tp.tvab = td.tvab
left join informant_data as id on tp.id = id.id and tp.tvab = id.tvab
left join harmony as h on tp.id = h.id and tp.tvab = h.tvab
left join lentus as l on tp.id = l.id and tp.tvab = l.tvab
/* For Twin 2 */
left join twin_data as td2 on p2.id = td2.id and p2.tvab = td2.tvab
left join informant_data as id2 on p2.id = id2.id and p2.tvab = id2.tvab
left join harmony as h2 on p2.id = h2.id and p2.tvab = h2.tvab
left join lentus as l2 on p2.id = l2.id and p2.tvab = l2.tvab,
person_data as p1,
person_data as p2,
postal_groups as pg
where
/* p1 gets main twin and p2 gets his/her twin. */
/* ptvab is a field inverted by tvab */
p1.id = tp.id and p1.tvab = tp.tvab and
p2.id = p1.id and p2.ptvab = p1.tvab and
/* Just the sceening survey */
tp.survey_no = 5 and
/* Skip if partner died before 65 but allow emigration (dead=9) */
(p2.dead = 0 or p2.dead = 9 or
(p2.dead = 1 and
(p2.sterbetag_date = 0 or
(((to_days(p2.sterbetag_date) - to_days(p2.geburtstagday)) / 365)
>= 65))))
and
(
/* Twin is suspect */
(td.future_contact = 'Yes' and td.suspect = 2) or
/* Twin is suspect - Informant is Blessed */
(td.future_contact = 'Yes' and td.suspect = 1 and id.suspect = 1) or
/* No twin - Informant is Blessed */
(ISNULL(td.suspect) and id.suspect = 1 and id.future_contact = 'Yes') or
/* Twin broken off - Informant is Blessed */
(td.participation = 'Aborted'
and id.suspect = 1 and id.future_contact = 'Yes') or
/* Twin broken off - No inform - Have partner */
(td.participation = 'Aborted' and ISNULL(id.suspect) and p2.dead = 0))
and
l.event = 'Finished'
/* Get at area code */
and substring(p1.postal_code, 1, 2) = pg.code
/* Not already distributed */
and (h.nurse is NULL or h.nurse=00 or h.doctor=00)
/* Has not refused or been aborted */
and not (h.status = 'Refused' or h.status = 'Aborted'
or h.status = 'Died' or h.status = 'Other')
order by
tvid;
Einige Erläuterungen:
concat(p1.id, p1.tvab) + 0 as tvid
Wir wollen nach den verketteten id und
tvab in numerischer Reihenfolge
sortieren. Indem wir 0 hinzufügen,
bringen wir MySQL dazu, das Ergebnis als Zahl zu behandeln.
Spalte id
Diese identifiziert ein Zwillingspaar. Sie ist in allen Tabellen Schlüssel.
Spalte tvab
Diese identifiziert ein Zwillingspaar. Sie hat einen Wert
von 1 oder 2.
Spalte ptvab
Sie ist die Umkehrung von tvab. Wenn
tvab 1 ist, ist sie
2, und umgekehrt. Sie ist dafür da,
MySQL die Optimierung der Anfrage zu erleichtern.
Diese Anfrage demonstriert unter anderem, wie man ein
Nachschlagen (Lookup) in einer Tabelle von derselben Tabelle aus
mit einem Join durchführt (p1 und
p2). In dem Beispiel wird das dazu benutzt,
um festzustellen, ob der Partner eines Zwillings vor Erreichen
des 65. Lebensjahrs starb. Wenn das der Fall ist, wird die Zeile
nicht zurückgegeben.
Das Geschilderte existiert in allen Tabellen mit
zwillingsbezogenen Informationen. Wir haben einen Schlüssel auf
beide id,tvab (alle Tabellen), und auf
id,ptvab (person_data), um
Anfragen schneller zu machen.
Auf unserer Produktionsmaschine (einer 200MHz-UltraSPARC) gibt diese Anfrage etwa 150 bis 200 Zeilen zurück und benötigt weniger als eine Sekunde.
Die aktuelle Anzahl von Datensätzen in den oben benutzten Tabellen:
| Tabelle | Zeilen |
person_data | 71074 |
lentus | 5291 |
twin_project | 5286 |
twin_data | 2012 |
informant_data | 663 |
harmony | 381 |
postal_groups | 100 |
Jedes Interview endet mit einem Statuscode, genannt
ereignis. Die unten stehende Anfrage wird
benutzt, um eine Tabelle über alle Zwillingspaare anzuzeigen,
kombiniert mit dem Ereignis. Das zeigt an, wie viele Paare
beider Zwillingen im Zustand beendet sind, bei wie vielen Paaren
ein Zwilling im Zustand beendet ist, welche ein Interview
abgelehnt haben usw.
select
t1.event,
t2.event,
count(*)
from
lentus as t1,
lentus as t2,
twin_project as tp
where
/* We are looking at one pair at a time */
t1.id = tp.id
and t1.tvab=tp.tvab
and t1.id = t2.id
/* Just the sceening survey */
and tp.survey_no = 5
/* This makes each pair only appear once */
and t1.tvab='1' and t2.tvab='2'
group by
t1.event, t2.event;
Der Contrib-Abschnitt beinhaltet Programme, mit denen Sie Ihre Benutzer durch eine MySQL-Datenbank authentifizieren können, und mit denen Sie Ihre Logdateien in eine MySQL-Tabelle schreiben können.
Sie können das Log-Format von Apache so ändern, dass es durch MySQL leicht gelesen werden kann, indem Sie folgendes in die Apache-Konfigurationsdatei schreiben:
LogFormat \
"\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\", \
\"%U\",\"%{Referer}i\",\"%{User-Agent}i\""
In MySQL können Sie dann etwas wie das hier tun:
LOAD DATA INFILE '/local/access_log' INTO TABLE tabelle FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.