Previous: SQL benutzen
Up: Praktischer Teil SQL
Next: Tips & Tricks
Sobald man mit dem DBMS verbunden ist, kann man die Befehle eingeben, die auch von PHP aus aufgerufen werden.
Bei der dialogorientierten Benutzung und im Batch-Betrieb müssen die Befehle immer mit einem ; abgeschlossen werden. Man kann ohne Probleme einen Befehl in mehrere Zeilen schreiben, indem man erst am Ende das Semikolon setzt.
Als theoretische Grundlage wird die Beispiel-Datenbank, die in Kapitel 4.6 beschrieben wurde, benutzt.
Im Allgemeinen wird wohl eine Datenbank vom Administrator (beim Jugendnetz: wir) eingerichtet werden. Von diesem bekommst du dann auch die nötigen Zugangsdaten wie Datenbankname, Benutzername und Paßwort. Bist du selbst jedoch der Administrator des Systems (wie z.B. bei der Installation eines Offline-Testwebservers), mußt du das Einrichten der Datenbank auch selbst erledigen; der MySQL-Befehl hierzu lautet CREATE DATABASE, gefolgt von dem gewünschten Namen der Datenbank.
Beim Anlegen wie auch beim späteren Benutzen der Datenbank ist folgendes zu bedenken:
Unix/Linux unterscheidet Groß- und Kleinschreibung. Aufgrund o.g. Dateisystem-Abhängigkeit
der Datenbank (Verzeichnischarakter) wäre die Datenbank ,,Termine`` nämlich eine
andere als ,,termine``.
Als Grundregel solltest du dir einfach angewöhnen, bei jeglichen Eingaben von
Datenbank-, Tabellen- und Feldnamen grundsätzlich auf die Groß- und Kleinschreibung zu
achten und diese konsistent zu halten, also auch in allen SQL-Befehlen diese Namen genau
so zu verwenden, wie sie angelegt wurden. Selbst wenn Windows (ja, auch hier läuft
MySQL!) weniger restriktiv ist, vermeidest du durch dieses Vorgehen späteren Ärger z.B.
bei Portierungen von Datenbanken nach Unix/Linux.
Nach dem Einrichten der Datenbank ist diese bereits benutzbar, d.h. du kannst jetzt Tabellen mit entsprechenden Feldern anlegen (mehr dazu im nächsten Abschnitt: 6.2). Arbeitest du hingegen auf dem mysql-Prompt, mußt du zuerst die Datenbank wechseln: das geht mittels USE <DB-Name>.
CREATE TABLE table_name (create_definition,...)Für table_name ist selbstverständlich der Name der zu erstellenden Tabelle einzusetzen. Die drei Punkte hinter `create_definition` bedeuten, daß mehrere `create_definitions` durch Kommas getrennt hintereinander stehen können. Die `create_definitions` müssen innerhalb der runden Klammern stehen!
Für `create_definition` kann man folgendes einsetzen:
feld_name Typ [NOT NULL] [AUTO_INCREMENT] [UNIQUE] [PRIMARY KEY] oder PRIMARY KEY (feld_name,...) oder UNIQUE (feld_name,...) oder FOREIGN KEY (feld_name,...) [reference_definition]Für `reference_definition` muß man folgendes einsetzen:
REFERENCES table_name[(index_spalte,...)]
Mit NOT NULL wird festgelegt, daß ein Wert (das kann auch ein leerer sein) eingetragen werden muß. NULL ist nicht mit der Zahl 0 zu verwechseln; NULL bedeutet einfach ,,kein Wert``. Wenn bei INSERT kein Wert für dieses Feld angegeben wurde, wird der Standardwert genommen. Es gibt keine Fehlermeldung (nur MySQL)!
Wenn ein Zahlenfeld mit dem Schlüsselwort AUTO_INCREMENT angelegt wurde, wird, solange kein Wert für dieses Feld angeben wurde, der höchste Wert +1 genommen. AUTO_INCREMENT kann nur einmal pro Tabelle in einem Primärschlüsselfeld verwendet werden. AUTO_INCREMENT gibt es nur in MySQL.
Wenn UNIQUE bei einem Feld angegeben wurde, darf ein Wert in maximal einem Tupel vorkommen, d.h. jeder Wert muß eindeutig sein. Bei Primärschlüsseln wird automatisch UNIQUE angenommen.
Mit PRIMARY KEY wird der Primärschlüssel festgelegt. Bei zusammengesetzten Primärschlüsseln sind alle Felder, die Teil des Schlüssels sind, anzugeben. Primärschlüssel müssen eindeutig sein und es muß NOT NULL angegeben werden.
UNIQUE und PRIMARY KEY können entweder direkt hinter einer Spaltendefinition angegeben werden oder getrennt davon. Sobald erst eine Kombination mehrerer Spalten den Primärschlüssel bildet, d.h. eindeutig ist, muß der Primärschlüssel getrennt angegeben werden.
Mit FOREIGN KEY wird die Fremdschlüsselbeziehung angegeben. MySQL unterstützt bis jetzt noch keine Fremdschlüssel und ignoriert folglich die Angaben.
Für Typ ist einer der Datentypen aus Tabelle 6.1 zu verwenden.
Typ | Beschreibung |
TINYINT | -128 .. 127 |
TINYINT UNSIGNED | 0 .. 255 |
INT | -2.147.483.648 .. 2.147.483.647 |
INT UNSIGNED | 0 .. 4.294.967.295 |
BIGINT | -3402823e+31 .. 3402823e+31 |
DECIMAL(length,dec) | Kommazahl der Länge `length` und mit `dec` Dezimalstellen; die Länge beträgt: Stellen vor dem Komma + 1 Stelle für Komma + Stellen nach dem Komma |
VARCHAR(NUM) [BINARY] | Zeichenkette mit max `NUM` Stellen ( ). Alle Leerstellen am Ende werden gelöscht. Solange nicht `BINARY` angegeben wurde, wird bei Vergleichen nicht auf Groß-/Kleinschreibung geachtet. |
TEXT | Text mit einer max. Länge von 65535 Zeichen |
MEDIUMTEXT | Text mit einer max. Länge von 16.777.216 Zeichen |
TIME | Zeit; Format: HH:MM:SS, HHMMSS, HHMM oder HH |
DATE | Datum; Format: YYYY-MM-DD, wobei `-` jedes nicht numerische Zeichen sein kann |
TIMESTAMP | setzt einen Datumswert beim Einfügen/Updaten einzelner Felder automatisch auf das Systemdatum. |
Format: YYYYMMDDHHMMSS. Wenn mehrere Felder den Typ `TIMESTAMP` haben, wird immer nur das erste automatisch geändert! |
Die Bedeutung der YMHSDs ist in der Tabelle 6.2 erläutert.
D | Tag (engl. day) |
H | Stunde (engl. hour) |
M | Monat (engl. month) oder Minute (engl. minute) |
S | Sekunde (engl. second) |
Y | Jahr (engl. year) |
Wenn ein Buchstabe mehrmals vorkommt, so bedeutet das, daß es mehrere Stellen gibt.
Ein kleines Beispiel:
Es soll eine Tabelle `Mitarbeiter` erstellt werden. Zu jedem Mitarbeiter
sind Name, Telefonnummer und die Mitarbeiter-Nummer (kurz MNr) zu speichern. Die
MNr ist Primärschlüssel und soll automatisch um 1 erhöht werden. Der Name ist
nicht optional. Daraus ergibt sich folgender Befehl:
CREATE TABLE Mitarbeiter ( MNr INT NOT NULL AUTO_INCREMENT, VNr INT, AbtNr INT NOT NULL, Name VARCHAR(30) NOT NULL, GebDat DATE, Telefon VARCHAR(30), PRIMARY KEY(MNr), FOREIGN KEY(VNr) REFERENCES Mitarbeiter(MNr), FOREIGN KEY(AbtNr) REFERENCES Abteilung(AbtNr) );Die mehrfachen Leerstellen sind optional. Sie sind hier nur der Übersichtlichkeit halber eingefügt.
Wenn man versucht, die Mitarbeiter-Tabelle bei einem DBMS, das Fremdschlüssel unterstützt, als erstes anzulegen, wird man eine Fehlermeldung erhalten, weil die referenzierte Tabelle noch nicht existiert. In diesem Fall kann man die Tabellenstruktur nachträglich mit ALTER TABLE (6.11) anpassen.
Im Anhang A.1 sind noch einmal sämtliche `CREATE TABLE` -Definitionen aufgeführt, die für unser Beispiel benötigt werden. Es sind der Vollständigkeit halber auch sämtliche Fremdschlüssel mit angegeben, obwohl sie unter MySQL keine Bedeutung haben.
SHOW TABLESoder
SHOW COLUMNS FROM tableSHOW TABLES zeigt alle angelegten Tabellen an. Mit SHOW COLUMNS FROM table lassen sich die Felder in der Tabelle `table` anzeigen.
Nach unserem obigen CREATE TABLE würde sich folgende Ausgabe ergeben:
mysql> SHOW TABLES; +--------------+ | Tables in cr | +--------------+ | Mitarbeiter | +--------------+ 1 row in set (0.01 sec) mysql> SHOW COLUMNS FROM Mitarbeiter; +---------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+----------------+ | MNr | int(11) | | PRI | 0 | auto_increment | | VNr | int(11) | YES | | NULL | | | AbtNr | int(11) | | | 0 | | | Name | varchar(30) | | | | | | GebDat | date | YES | | NULL | | | Telefon | varchar(30) | YES | | NULL | | +---------+-------------+------+-----+---------+----------------+ 5 rows in set (0.00 sec)In der unteren Tabelle ist zu erkennen, welche Felder mit welchen Typen und Attributen in der jeweiligen Tabelle vorhanden sind. Nur für `VNr`, `GebDat` und ` Telefon` sind NULL-Werte zugelassen. Der Primärschlüssel ist `MNr`. Wie man sieht, wurden die Fremdschlüssel ignoriert.
Die Syntax lautet:
DROP TABLE table_name
Achtung: Es erfolgt keine Abfrage, ob du dies wirklich tun willst! Mit der Tabelle werden natürlich auch alle Daten der Tabelle unwiderruflich gelöscht!
INSERT INTO table_name [ (feld_name,...) ] VALUES (werte,...)Die Feldnamen können weggelassen werden, wenn in alle Felder etwas eingefügt werden soll. In diesem Fall muß man aber die Werte in genau der Reihenfolge eingeben, in der die Felder in der CREATE TABLE Anweisung definiert wurden.
In der Regel, vor allem aber in Programmen, empfiehlt es sich, die Feldnamen anzugeben, weil man sich nie darauf verlassen sollte, daß sich die Reihenfolge der Spalten nicht ändert.
Bei den Werten müssen Zeichenketten und Datum in Hochkommata (Anführungszeichen) stehen, nur für Zahlen gilt das nicht.
In unsere oben erstellte Tabelle sollen folgende Werte eingefügt werden:
Name | GebDat | Telefon |
---|---|---|
Christoph Reeg | 13.5.1979 | |
junetz.de | 5.3.1998 | 069/764758 |
Damit ergeben sich folgende Befehle und Ausgaben (wie man hier bereits sieht, gibt der MySQL-Prompt automatisch die Zeichenfolge `->` aus, wenn ein mehrzeiliger Befehl eingegeben wird):
mysql> INSERT INTO Mitarbeiter (Name,GebDat) -> VALUES ('Christoph Reeg','1979-5-13'); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO Mitarbeiter (Name,GebDat,Telefon) -> VALUES ('junetz.de','1998-3-5','069/764758'); Query OK, 1 row affected (0.00 sec)
Wegen fehlender Fremdschlüssel konnten die Mitarbeiter in die DB eingefügt werden, obwohl wir keine Abteilung für sie angegeben haben. Deshalb muß man immer selbst für die Einhaltung der Beziehung(en) sorgen!
Um die Datenbasis für unser Beispiel in die DB einzutragen, wird der Befehl noch ein paarmal benutzt. Diese konkrete Anwendung kann im Anhang A.2 nachgeschlagen werden.
Bei den folgenden Kurzbeispielen gehen wir von der Datenbasis unseres Beispiels aus.
SELECT [DISTINCT | ALL] select_expression,... FROM tables ... [WHERE where_definition] [GROUP BY feld_name,...] [ORDER BY feld_name [ASC | DESC] ,...] [LIMIT [offset,] rows]
Die kürzestmögliche SELECT-Anweisung lautet:
SELECT * FROM table
Es sollen z.B. alle Mitarbeiter ausgegeben werden:
mysql> select * from Mitarbeiter; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 3 | 1 | 1 | Uli | NULL | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.00 sec) mysql>
DISTINCT und ALL sind exklusive, optionale Parameter; soll heißen, es kann immer nur einer, muß aber keiner benutzt werden. DISTINCT sorgt dafür, daß jede identische Zeile nur einmal ausgegeben wird. Mit ALL werden die sich wiederholenden Werte auch mehrmals ausgegeben. Ohne Parameter verhält sich das DBMS normalerweise, als ob man ALL angeben würde.
Es sollen alle Telefonnummern aus der Mitarbeiter-Tabelle ausgeben werden:
mysql> SELECT Telefon from Mitarbeiter; +--------------+ | Telefon | +--------------+ | NULL | | 069/764758 | | NULL | | 069/764758 | | 06196/671797 | | 069/97640232 | +--------------+ 6 rows in set (0.01 sec) mysql> SELECT ALL Telefon from Mitarbeiter; +--------------+ | Telefon | +--------------+ | NULL | | 069/764758 | | NULL | | 069/764758 | | 06196/671797 | | 069/97640232 | +--------------+ 6 rows in set (0.00 sec) mysql> SELECT DISTINCT Telefon from Mitarbeiter; +--------------+ | Telefon | +--------------+ | NULL | | 06196/671797 | | 069/764758 | | 069/97640232 | +--------------+ 4 rows in set (0.05 sec) mysql>
Als Beispiel alle Mitarbeiter, nach Namen sortiert:
mysql> SELECT * from Mitarbeiter ORDER BY Name; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 3 | 1 | 1 | Uli | NULL | NULL | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.00 sec) mysql> SELECT * from Mitarbeiter ORDER BY Name ASC; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 3 | 1 | 1 | Uli | NULL | NULL | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.01 sec) mysql> SELECT * from Mitarbeiter ORDER BY Name DESC; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 3 | 1 | 1 | Uli | NULL | NULL | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.00 sec) mysql>
Als letztes soll nach dem Geburtsdatum sortiert werden.
mysql> SELECT * from Mitarbeiter ORDER BY GebDat; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 3 | 1 | 1 | Uli | NULL | NULL | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.01 sec) mysql>Die ersten vier Mitarbeiter haben kein Geburtsdatum eingetragen. Um sie dennoch irgendwie zu sortieren, ist bei ihnen ein zweites Sortierkriterium notwendig. Das kann einfach mit einem Komma getrennt hinter ORDER BY geschrieben werden.
Um zum Beispiel nach Geburtsdatum und, wenn das nicht eindeutig ist, dann nach Namen zu sortieren, ist folgende Anweisung notwendig:
mysql> SELECT * from Mitarbeiter ORDER BY GebDat,Name; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | | 3 | 1 | 1 | Uli | NULL | NULL | | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | +-----+------+-------+----------------+------------+--------------+ 6 rows in set (0.00 sec) mysql>
Ein kleines Beispiel:
Es soll ausgegeben werden, wie viele Mitarbeiter in den jeweiligen Abteilungen arbeiten.
mysql> SELECT count(*), AbtNr from Mitarbeiter GROUP BY AbtNr; +----------+-------+ | count(*) | AbtNr | +----------+-------+ | 3 | 1 | | 2 | 2 | | 1 | 3 | +----------+-------+ 3 rows in set (0.00 sec) mysql>Die sechs Tupel (Datensätze), die wir in der Mitarbeiter-Tabelle haben, werden zu drei Gruppen zusammengefaßt; anschließend wird die Anzahl der Tupel pro Gruppe ausgeben.
Eigentlich dürfen in der select_expression nur Spalten angegeben werden, die in GROUP BY auftauchen, MySQL ignoriert dies allerdings. Folgende Anweisung wäre eigentlich unzulässig, zudem ist sie völlig sinnlos - was besagt schon die Spalte `Name`?
mysql> SELECT Name,count(*),AbtNr from Mitarbeiter GROUP BY AbtNr; +----------------+----------+-------+ | Name | count(*) | AbtNr | +----------------+----------+-------+ | junetz.de | 3 | 1 | | Maier | 2 | 2 | | Christoph Reeg | 1 | 3 | +----------------+----------+-------+ 3 rows in set (0.00 sec) mysql>
mysql> select * from table LIMIT 5,10; # gibt die Zeilen 6-15 zurück mysql> select * from table LIMIT 5; # gibt die ersten 5 Zeilen zurück mysql> select * from table LIMIT 0,5; # dasselbe nochmal
Im Normalfall werden die benötigten Spalten durch Kommas getrennt angegeben. Sobald die Spaltennamen nicht mehr eindeutig sind, weil mehrere Tabellen angegeben wurden, muß der Tabellenname, gefolgt von einem Punkt, vorangestellt werden; es können dabei auch sog. Aliase verwendet werden. Mehr dazu weiter unten.
Neben den reinen Spaltenwerten können auch Werte, die aus den Spaltenwerten berechnet oder durch sonstige Funktionen erstellt wurden, ausgegeben werden. In Kapitel 6.7 werden die Funktionen ausführlich beschrieben.
Als Beispiel sollen der Mitarbeitername und die Telefonnummer ausgegeben werden. Die beiden Ausgaben sind äquivalent, wie man unschwer erkennen kann. Solange nur aus einer Tabelle ausgelesen wird, ist die erstere allerdings eher empfehlenswert, da nicht zu umständlich.
mysql> select Name, Telefon from Mitarbeiter; +----------------+--------------+ | Name | Telefon | +----------------+--------------+ | Christoph Reeg | NULL | | junetz.de | 069/764758 | | Uli | NULL | | JCP | 069/764758 | | Maier | 06196/671797 | | Meier | 069/97640232 | +----------------+--------------+ 6 rows in set (0.02 sec) mysql> select Mitarbeiter.Name, Mitarbeiter.Telefon from Mitarbeiter; +----------------+--------------+ | Name | Telefon | +----------------+--------------+ | Christoph Reeg | NULL | | junetz.de | 069/764758 | | Uli | NULL | | JCP | 069/764758 | | Maier | 06196/671797 | | Meier | 069/97640232 | +----------------+--------------+ 6 rows in set (0.00 sec) mysql>
Die folgenden zwei Anweisungen sind völlig identisch, abgesehen davon, daß erstere kürzer ist. Der einzige Unterschied liegt in den ersten beiden Zeilen. Im ersten Beispiel wird bei der FROM-Anweisung ein Alias definiert, welches in der ersten Zeile bei der select_expression benutzt wird.
mysql> select M.Name, M.Telefon, M.AbtNr -> FROM Mitarbeiter M -> WHERE M.AbtNr = 1; +-----------+------------+-------+ | Name | Telefon | AbtNr | +-----------+------------+-------+ | junetz.de | 069/764758 | 1 | | Uli | NULL | 1 | | JCP | 069/764758 | 1 | +-----------+------------+-------+ 3 rows in set (0.00 sec) mysql> select Mitarbeiter.Name, Mitarbeiter.Telefon, -> Mitarbeiter.AbtNr -> FROM Mitarbeiter -> WHERE Mitarbeiter.AbtNr = 1; +-----------+------------+-------+ | Name | Telefon | AbtNr | +-----------+------------+-------+ | junetz.de | 069/764758 | 1 | | Uli | NULL | 1 | | JCP | 069/764758 | 1 | +-----------+------------+-------+ 3 rows in set (0.01 sec) mysql>
Zum Umbenennen der Spalten wird einfach hinter den Spaltennamen bzw. Ausdruck der Aliasname geschrieben. Alternativ kann auch AS aliasname benutzt werden.
Ein kleines Beispiel:
Es soll die Anzahl der Mitarbeiter ausgegeben werden. Dazu wird eine Funktion benötigt
(siehe Kapitel 6.7, das soll uns aber nicht weiter stören).
mysql> SELECT count(*) -> FROM Mitarbeiter; +----------+ | count(*) | +----------+ | 6 | +----------+ 1 row in set (0.00 sec) mysql>Das einzige störende ist, daß die Spalte ,,count(*)`` heißt. Viel schöner wäre es doch, wenn sie z.B. ,,Anzahl`` heißen würde:
mysql> SELECT count(*) Anzahl -> FROM Mitarbeiter; +--------+ | Anzahl | +--------+ | 6 | +--------+ 1 row in set (0.00 sec) mysql> SELECT count(*) AS Anzahl -> FROM Mitarbeiter; +--------+ | Anzahl | +--------+ | 6 | +--------+ 1 row in set (0.00 sec) mysql>Wie man unschwer erkennen kann, ist das AS optional.
Die `where_definition` wird auch beim Löschen (DELETE) und Ändern (UPDATE) von ausgewählten Datensätzen gebraucht.
Eine Bedingung kann aus mehreren Teilbedingungen, die mit AND und OR verknüpft werden müssen, bestehen. Eine Teilbedingung besteht aus einem Spaltennamen, einem Operator sowie entweder einer Konstanten, einer weiteren Spalte oder einer Funktion. Die Teilbedingungen können auch mit NOT verneint werden. Schreibfaule können an Stelle von NOT auch einfach ! verwenden; das Ergebnis ist dasselbe. Die Reihenfolge der Teilbedingungen kann durch Klammern beeinflußt werden. Als Operatoren stehen die Vergleichsoperatoren sowie die Operatoren `LIKE`, `BETWEEN` und `IN` zur Auswahl. Alle Vergleichsoperatoren aus Tabelle 6.3 stehen zur Verfügung. Bei Vergleichen mit Strings (=VARCHAR) wird im Normalfall nicht auf die Groß-/Kleinschreibung geachtet. Wenn man jedoch unterscheiden will, so muß beim Anlegen der Tabelle bei VARCHAR die Option BINARY angegeben werden.
Operator | Bedeutung | verneinender Operator |
= | gleich | <> bzw. != |
<> oder != | ungleich | = |
> | größer | <= |
< | kleiner | >= |
>= | größer gleich | < |
<= | kleiner gleich | > |
Es sollen alle Mitarbeiter ausgegeben werden, bei denen die Abteilungsnummer größer als 2 ist:
mysql> SELECT Name, AbtNr -> FROM Mitarbeiter -> WHERE AbtNr > 2; +----------------+-------+ | Name | AbtNr | +----------------+-------+ | Christoph Reeg | 3 | +----------------+-------+ 1 row in set (0.00 sec) mysql> SELECT Name, AbtNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr < 3); +----------------+-------+ | Name | AbtNr | +----------------+-------+ | Christoph Reeg | 3 | +----------------+-------+ 1 row in set (0.00 sec) mysql>
Es sollen alle Mitarbeiter ausgegeben werden, die der Abteilung 1 angehören und als Vorgesetztennummer ebenfalls die 1 haben.
mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE AbtNr = 1 -> AND VNr = 1; +-----------+-------+------+ | Name | AbtNr | VNr | +-----------+-------+------+ | junetz.de | 1 | 1 | | Uli | 1 | 1 | +-----------+-------+------+ 2 rows in set (0.02 sec) mysql>
Es sollen alle Mitarbeiter ausgegeben werden, die keinen Vorgesetzten haben oder der Abteilung 1 angehören:
mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE AbtNr = 1 -> OR VNr IS NULL; +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0.01 sec) mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr <> 1) -> OR VNr IS NULL; +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0.00 sec) mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr <> 1 AND VNr IS NOT NULL); +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0.00 sec) mysql>Bei der Überprüfung auf keinen Vorgesetzten ist IS NULL verwendet worden, da bei Vergleichen mit NULL-Werten nicht mit den normalen Operatoren gearbeitet werden kann. Statt dessen ist nur IS NULL oder, verneint, IS NOT NULL möglich.
Es gibt mit Sicherheit noch 1001 andere Möglichkeiten, auf diese Lösung zu kommen. Da der erste Korrekturleser mir das nicht glauben wollte, hier noch ein paar Möglichkeiten mehr:
mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE NOT (AbtNr < 1 OR AbtNr > 1) -> OR VNr IS NULL; +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0.00 sec) mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE (AbtNr <= 1 AND AbtNr >= 1) -> OR VNr IS NULL; +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0.01 sec) mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE AbtNr & 1 = 1 -> OR VNr IS NULL; +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0.00 sec) mysql> SELECT Name, AbtNr, VNr -> FROM Mitarbeiter -> WHERE POW(13,AbtNr) = 13 -> OR POW(VNr,42) IS NULL; +----------------+-------+------+ | Name | AbtNr | VNr | +----------------+-------+------+ | Christoph Reeg | 3 | NULL | | junetz.de | 1 | 1 | | Uli | 1 | 1 | | JCP | 1 | 3 | +----------------+-------+------+ 4 rows in set (0.02 sec) mysql>Es sind noch nicht 1001 Möglichkeiten, aber wenn ich vieeel Zeit habe, werde ich daran weiterarbeiten ;-). Wer sich die beiden letzten Lösungen genau angesehen hat, wird feststellen, daß dort unbekannte Befehle verwendet werden; in Kapitel 6.7 werden diese noch genauer beschrieben.
Bei der letzten Möglichkeit sieht man, was passiert, wenn mit NULL-Werten gerechnet wird: Das Ergebnis ist NULL.
Es sollen alle Mitarbeiter ausgegeben werden, bei denen die Telefon-Vorwahl auf ,, 96`` endet. Falls du eine Möglichkeit findest, das mit Vergleichsoperatoren (und ohne Funktionen) zu lösen, schicke mir bitte eine E-Mail an die Adresse dsp@reeg.net; ich bevorzuge übrigens den Operator LIKE.
mysql> SELECT Name, Telefon -> FROM Mitarbeiter -> WHERE Telefon LIKE '%96/%'; +-------+--------------+ | Name | Telefon | +-------+--------------+ | Maier | 06196/671797 | +-------+--------------+ 1 row in set (0.00 sec) mysql>
Es soll ein Mitarbeiter mit Namen ,,Meier`` ausgegeben werden. Allerdings ist unbekannt, ob er sich mit ,,ei`` oder ,,ai`` schreibt. Es sollen also alle Möglichkeiten ausgegeben werden.
mysql> SELECT Name -> FROM Mitarbeiter -> WHERE Name LIKE 'M_ier'; +-------+ | Name | +-------+ | Maier | | Meier | +-------+ 2 rows in set (0.00 sec) mysql>
Wie wir sehen, gibt es zwei Jokerzeichen:
% | DOS-Pendant: * | steht für eine beliebige (auch 0) Anzahl beliebiger Zeichen |
_ | DOS-Pendant: ? | steht für genau ein beliebiges Zeichen |
Beispiel: Es sollen alle Mitarbeiter ausgewählt werden, deren Abteilungs-Nummer zwischen 2 und 5 liegt. Mit dem bisherigen Wissen würde man folgende Anweisung nehmen:
mysql> SELECT * FROM Mitarbeiter -> WHERE AbtNr >= 2 AND AbtNr <=5; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0.01 sec) mysql>Man kann es aber noch etwas vereinfachen:
mysql> SELECT * FROM Mitarbeiter -> WHERE AbtNr BETWEEN 2 AND 5; +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0.00 sec) mysql>BETWEEN kann bei Textspalten, Datumsspalten und numerischen Spalten verwendet werden.
Zur Verdeutlichung: Es sollen alle Mitarbeiter ausgegeben werden, deren Telefonnummer ,,06196/671797`` oder ,,069/764758`` ist. Mit den bisherigen Operatoren würde sich folgende Abfrage ergeben:
mysql> SELECT * FROM Mitarbeiter -> WHERE Telefon = '06196/671797' OR Telefon = '069/764758'; +-----+------+-------+-----------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+-----------+------------+--------------+ | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | +-----+------+-------+-----------+------------+--------------+ 3 rows in set (0.00 sec) mysql>Das funktioniert zwar, aber da diese Möglichkeit bei großen Mengen von Werten sehr umständlich und unübersichtlich wird, hier das ganze nochmal mit dem IN-Operator:
mysql> SELECT * FROM Mitarbeiter -> WHERE Telefon IN ('06196/671797','069/764758'); +-----+------+-------+-----------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+-----------+------------+--------------+ | 2 | 1 | 1 | junetz.de | 1998-03-05 | 069/764758 | | 4 | 3 | 1 | JCP | NULL | 069/764758 | | 5 | 1 | 2 | Maier | NULL | 06196/671797 | +-----+------+-------+-----------+------------+--------------+ 3 rows in set (0.00 sec) mysql>Der IN-Operator kann bei Textspalten, Datumsspalten und numerischen Spalten verwendet werden.
Die Verneinung des IN-Operators ist NOT IN. Als Beispiel sollen alle Mitarbeiter ausgegeben werden, deren Telefonnummer nicht ,,06196/671797`` oder ,,069/97640232`` ist. Erst umständlich mit OR und dann elegant...
mysql> SELECT * FROM Mitarbeiter -> WHERE NOT (Telefon = '06196/671797' OR Telefon = '069/764758'); +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 3 | 1 | 1 | Uli | NULL | NULL | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM Mitarbeiter -> WHERE Telefon NOT IN ('06196/671797','069/764758'); +-----+------+-------+----------------+------------+--------------+ | MNr | VNr | AbtNr | Name | GebDat | Telefon | +-----+------+-------+----------------+------------+--------------+ | 1 | NULL | 3 | Christoph Reeg | 1979-05-13 | NULL | | 3 | 1 | 1 | Uli | NULL | NULL | | 6 | 5 | 2 | Meier | NULL | 069/97640232 | +-----+------+-------+----------------+------------+--------------+ 3 rows in set (0.00 sec) mysql>
Es wäre zum Beispiel Schwachsinn, zu versuchen, den Betrag von allen Stellenanzahlen auf einmal zu berechnen; bei der Summe paßt das schon eher.
Eine Auswahl der mathematischen Funktionen ist in Tabelle 6.4 aufgeführt.
|
In Tabelle 6.6 und 6.7 sind sonstige, teilweise praktische Funktionen aufgeführt. Die Tabellen sind nicht vollständig!
|
|
In PHP gibt es auch eine Datum-Formatierungsfunktion. Ob man nun mit der MySQL-Funktion das Datum formatiert und dann mit PHP ausgibt oder mit Hilfe der PHP-Funktion das Datum formatiert, ist häufig egal. Teilweise ist es praktischer, mit Hilfe der MySQL-Funktion das Datum zu formatieren, weil man dann die Formatierungsanweisung in der SQL-Abfrage hat und mit PHP nur ausgeben muß. Andererseits kann es aber auch praktischer sein, mit PHP zu formatieren, wenn man zum Beispiel dasselbe Datum an mehreren Stellen auf der Seite verschieden formatiert haben will. Wie gesagt, es kommt auf den Einzelfall und die Vorlieben des Programmierers an.
|
In Verbindung mit Gruppenfunktionen darf streng genommen kein Spaltenname mehr mit in der select_expression stehen. Die einzige Ausnahme ist dann gegeben, wenn der Spaltenname in der GROUP BY-Anweisung steht. MySQL sieht das etwas lockerer und gibt keine Fehlermeldung bei Verwendung von Spaltennamen in der select_expression aus, allerdings hat dies im Normalfall wenig Sinn.
In Tabelle 6.10 sind ein Teil der verfügbaren Gruppenfunktionen aufgeführt.
|
Für `expr` ist immer der Name der Spalte einzusetzen, mit der diese Operation erfolgen soll.
Beispiel: Es soll ausgegeben werden, wie viele Mitarbeiter ihren Geburtstag angegeben haben.
mysql> SELECT count(GebDat) -> FROM Mitarbeiter; +---------------+ | count(GebDat) | +---------------+ | 2 | +---------------+ 1 row in set (0.27 sec) mysql>
mysql> SELECT m.Name, m.AbtNr, a.Name, a.AbtNr -> FROM Mitarbeiter m, Abteilung a; +----------------+-------+------------+-------+ | Name | AbtNr | Name | AbtNr | +----------------+-------+------------+-------+ | Christoph Reeg | 3 | EDV | 1 | | junetz.de | 1 | EDV | 1 | | Uli | 1 | EDV | 1 | | JCP | 1 | EDV | 1 | | Maier | 2 | EDV | 1 | | Meier | 2 | EDV | 1 | | Christoph Reeg | 3 | Verwaltung | 2 | | junetz.de | 1 | Verwaltung | 2 | | Uli | 1 | Verwaltung | 2 | | JCP | 1 | Verwaltung | 2 | | Maier | 2 | Verwaltung | 2 | | Meier | 2 | Verwaltung | 2 | | Christoph Reeg | 3 | Chefetage | 3 | | junetz.de | 1 | Chefetage | 3 | | Uli | 1 | Chefetage | 3 | | JCP | 1 | Chefetage | 3 | | Maier | 2 | Chefetage | 3 | | Meier | 2 | Chefetage | 3 | +----------------+-------+------------+-------+ 18 rows in set (0.07 sec) mysql>
mysql> SELECT m.Name, m.AbtNr, a.Name, a.AbtNr -> FROM Mitarbeiter m, Abteilung a -> WHERE m.AbtNr = a.AbtNr; +----------------+-------+------------+-------+ | Name | AbtNr | Name | AbtNr | +----------------+-------+------------+-------+ | junetz.de | 1 | EDV | 1 | | Uli | 1 | EDV | 1 | | JCP | 1 | EDV | 1 | | Maier | 2 | Verwaltung | 2 | | Meier | 2 | Verwaltung | 2 | | Christoph Reeg | 3 | Chefetage | 3 | +----------------+-------+------------+-------+ 6 rows in set (0.00 sec) mysql>Vor den Spaltennamen muß jeweils die entsprechende Tabelle genannt werden, da die Namen nicht eindeutig sind. Um nicht jedes Mal den kompletten Tabellennamen benutzen zu müssen, wurden Aliase verwendet (siehe Kapitel 6.6.5).
Über die AbtNr entsteht die Verbindung zwischen den beiden Tabellen. Falls bei der Verknüpfung von mehreren Tabellen nicht das gewünschte Ergebnis erscheint, fehlt häufig eine WHERE-Bedingung, so daß bei einigen Tabellen das kartesische Produkt entsteht. In solchen Fällen kann man einfach nachzählen: Wenn n Tabellen miteinander verknüpft werden sollen, werden (n-1) WHERE-Bedingungen benötigt.
Diese Art der Verbindung wird Equi-Join genannt.
mysql> SELECT m.Name, m.VNr, v.Name, v.MNr -> FROM Mitarbeiter m, Mitarbeiter v -> WHERE m.VNr = v.MNr; +-----------+------+----------------+-----+ | Name | VNr | Name | MNr | +-----------+------+----------------+-----+ | junetz.de | 1 | Christoph Reeg | 1 | | Uli | 1 | Christoph Reeg | 1 | | Maier | 1 | Christoph Reeg | 1 | | JCP | 3 | Uli | 3 | | Meier | 5 | Maier | 5 | +-----------+------+----------------+-----+ 5 rows in set (0.13 sec) mysql>
Die Tabelle `Mitarbeiter` muß zwei Mal innerhalb der FROM-Anweisung auftauchen. Um nachher die Spalten eindeutig bezeichnen zu können, müssen Tabellen-Aliase vergeben werden.
Der einzige Schönheitsfehler bei der Abfrage ist, daß der Mitarbeiter ,,Christoph Reeg`` nicht aufgelistet wird. Im Prinzip ist das logisch, da er keinen Vorgesetzten hat. Dumm ist es trotzdem, und deshalb kommen wir zur nächsten Form des Joins: dem Outer-Join.
Die Syntax unter MySQL lautet (wo sonst die Tabellennamen stehen):
haupttabelle LEFT JOIN tabelle2 ON bedingung oder haupttabelle LEFT JOIN tabelle2 USING (spalte)Bei der unteren Möglichkeit müssen die Spaltennamen in den beiden Tabellen, über die die Verbindung entsteht, gleich sein. Bei der oberen Möglichkeit muß an die Stelle, wo ` bedingung` steht, das eingesetzt werden, was man beim Equi-Join als ` where_condition` schreiben würde. In beiden Fällen kann auch LEFT OUTER JOIN anstelle von LEFT JOIN geschrieben werden - das OUTER ist optional und nur aus Gründen der SQL-Kompatibilität erlaubt.
Um beim oben gezeigten Beispiel zu bleiben: Es sollen alle Mitarbeiter mit deren Vorgesetzten (sofern vorhanden) angezeigt werden. Da die Spaltennamen ungleich sind (in der Haupttabelle `VNr` und in der nachgeordneten Tabelle `MNr`), muß die obere Syntax benutzt werden.
mysql> SELECT m.Name, m.VNr, v.Name, v.MNr -> FROM Mitarbeiter m LEFT JOIN Mitarbeiter v ON m.VNr = v.MNr; +----------------+------+----------------+------+ | Name | VNr | Name | MNr | +----------------+------+----------------+------+ | Christoph Reeg | NULL | NULL | NULL | | junetz.de | 1 | Christoph Reeg | 1 | | Uli | 1 | Christoph Reeg | 1 | | JCP | 3 | Uli | 3 | | Maier | 1 | Christoph Reeg | 1 | | Meier | 5 | Maier | 5 | +----------------+------+----------------+------+ 6 rows in set (0.03 sec) mysql>
Die Mitarbeitertabelle mit dem Alias ,,m`` ist in unserem Fall die Haupttabelle.
Wie man unschwer erkennen kann, wird bei den Attributen, bei denen keine Werte existieren (in diesem Beispiel die beiden rechten Spalten in der ersten Zeile), NULL als Wert genommen.
Übrigens: Man muß natürlich nicht sowohl VNr als auch MNr abfragen (also zwischen SELECT und FROM angeben), da deren Werte wegen der ON-Bedingung (in der sie wiederum stehen müssen) immer gleich sind. Wenn man nur wissen möchte, in welcher Beziehung die einzelnen Mitarbeiter zu den Vorgesetzten stehen, kann man sogar ganz auf das Abfragen der Nummern verzichten. Um nicht völlig den Überblick zu verlieren, vergeben wir dabei noch Aliase:
mysql> SELECT m.Name AS Mitarb, v.Name as Vorges -> FROM Mitarbeiter m LEFT JOIN Mitarbeiter v ON m.VNr = v.MNr; +----------------+----------------+ | Mitarb | Vorges | +----------------+----------------+ | Christoph Reeg | NULL | | junetz.de | Christoph Reeg | | Uli | Christoph Reeg | | JCP | Uli | | Maier | Christoph Reeg | | Meier | Maier | +----------------+----------------+ 6 rows in set (0.03 sec) mysql>
Ein neues Beispiel:
Ich will alle Abteilungen aufgelistet haben, aber mit deren Autos.
mysql> SELECT a.Name, p.Kennzeichen, p.Typ -> FROM Abteilung a, PKW p -> WHERE a.AbtNr = p.AbtNr; +-----------+-------------+---------+ | Name | Kennzeichen | Typ | +-----------+-------------+---------+ | Chefetage | MTK-CR 1 | RR | | EDV | F-JN 1 | VW-Golf | +-----------+-------------+---------+ 2 rows in set (0.04 sec) mysql>Wie man sieht, führt der Equi-Join nicht zum gewünschten Ergebnis. Also das ganze nochmal als Outer-Join. Da die Schlüsselspalten denselben Namen haben, können in diesem Fall beide Syntaxvarianten verwendet werden:
mysql> SELECT a.Name, p.Kennzeichen, p.Typ -> FROM Abteilung a LEFT JOIN PKW p ON a.AbtNr = p.AbtNr; +------------+-------------+---------+ | Name | Kennzeichen | Typ | +------------+-------------+---------+ | EDV | F-JN 1 | VW-Golf | | Verwaltung | NULL | NULL | | Chefetage | MTK-CR 1 | RR | +------------+-------------+---------+ 3 rows in set (0.00 sec) mysql> SELECT a.Name, p.Kennzeichen, p.Typ -> FROM Abteilung a LEFT JOIN PKW p USING (AbtNr); +------------+-------------+---------+ | Name | Kennzeichen | Typ | +------------+-------------+---------+ | EDV | F-JN 1 | VW-Golf | | Verwaltung | NULL | NULL | | Chefetage | MTK-CR 1 | RR | +------------+-------------+---------+ 3 rows in set (0.00 sec) mysql>Als kleine Herausforderung hätte ich jetzt gerne die Abteilungen, die keinen PKW haben. Die Lösung ist eigentlich einfach. Wenn man sich das obige Ergebnis ansieht, stellt man fest (wie auch etwas weiter oben schon beschrieben), daß bei der Abteilung ohne PKW (nämlich ,,Verwaltung``) `Kennzeichen` und `Typ` NULL sind.
mysql> SELECT a.Name, p.Kennzeichen, p.Typ -> FROM Abteilung a LEFT JOIN PKW p USING (AbtNr) -> WHERE Typ IS NULL; +------------+-------------+------+ | Name | Kennzeichen | Typ | +------------+-------------+------+ | Verwaltung | NULL | NULL | +------------+-------------+------+ 1 row in set (0.03 sec) mysql>
DELETE FROM table_name [WHERE where_definition]Für `table_name` ist selbstverständlich der Name der Tabelle einzusetzen, in der gelöscht wird. Wenn keine `where_definition` angegeben wird, werden alle Daten ohne Nachfrage gelöscht! Die `where_definition` muß denselben Anforderungen genügen wie bei der SELECT-Anweisung.
Um vor dem Löschen zu testen, ob auch wirklich nur die richtigen Daten gelöscht werden, kann man erst ein SELECT * statt DELETE machen. Wenn nur Daten angezeigt werden, die gelöscht werden sollen, ersetzt man das SELECT * durch DELETE.
UPDATE table_name SET feld_name=expression,... [WHERE where_definition]Für `table_name` ist selbstverständlich der Name der Tabelle einzusetzen, in der einzelne Einträge geändert werden sollen. `feld_name` ist durch den Namen des Feldes zu ersetzen, dessen Werte geändert werden sollen und `expression` durch den neuen Wert. Falls Werte mehrerer Felder geändert werden sollen, können diese Zuweisungen einfach durch je ein Komma getrennt hintereinander geschrieben werden. Wenn keine `where_definition` angegeben wird, werden alle Tupel geändert! Die ` where_definition` muß denselben Anforderungen genügen wie bei der SELECT-Anweisung.
ALTER TABLE table_name alter_spec alter_spec: ADD [COLUMN] create_definition [AFTER column_name | FIRST] oder CHANGE alter_feld_name create_definition oder ADD PRIMARY KEY (index_spalte,...) oder ADD INDEX (index_spalte,...) oder ADD UNIQUE (index_spalte,...) oder DROP feld_name oder DROP PRIMARY KEY oder RENAME new_table_nameFür `create_definition` gilt dasselbe wie schon für `CREATE TABLE`.
Um das Ganze etwas zu verdeutlichen, hier ein kleines praktisches Beispiel (der Befehl SHOW COLUMNS wird hierbei jeweils nur zur Verdeutlichung der Ergebnisse benutzt):
Es wird folgende Tabelle angelegt:
mysql> CREATE TABLE temp ( -> eins VARCHAR(10) NOT NULL, -> zwei VARCHAR(20), -> PRIMARY KEY(eins) -> ); Query OK, 0 rows affected (0.00 sec) mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) mysql>
Als nächstes soll die Spalte `fuenf` vom Typ VARCHAR(30) eingefügt werden.
mysql> ALTER TABLE temp -> ADD fuenf VARCHAR(30); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | | fuenf | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql>
Nun wird die Spalte `drei` vom Typ VARCHAR(30) nach der Spalte `zwei` eingefügt.
mysql> ALTER TABLE temp -> ADD drei VARCHAR(30) AFTER zwei; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | YES | | NULL | | | fuenf | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.00 sec) mysql>
So gefällt uns das aber noch nicht ganz. Also benennen wir einfach die Spalte `fuenf` in `vier` um:
mysql> ALTER TABLE temp -> CHANGE fuenf vier VARCHAR(30); Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | PRI | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.01 sec) mysql>
Jetzt soll die Spalte `eins` nicht mehr Primärschlüssel sein (nicht die erste Spalte der SHOW-Anweisung!):
mysql> ALTER TABLE temp -> DROP PRIMARY KEY; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.01 sec) mysql>
Die Spalte `drei` soll nun Primärschlüssel werden. Primärschlüssel müssen aber als `NOT NULL` definiert werden. Deshalb zuerst einmal eine kleine Änderung des Datentyps:
mysql> ALTER TABLE temp -> CHANGE drei drei VARCHAR(30) NOT NULL; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | | | | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.00 sec) mysql>
Und nun definieren wir den Primärschlüssel neu:
mysql> ALTER TABLE temp -> ADD PRIMARY KEY(drei); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | drei | varchar(30) | | PRI | | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 4 rows in set (0.01 sec) mysql>
Jetzt, wo wir alles mühsam erstellt haben, fangen wir wieder an, alle Spalten der Reihe nach zu löschen. Als erstes soll die Spalte `drei` gelöscht werden.
mysql> ALTER TABLE temp -> DROP drei; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW columns FROM temp; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql>
Der Name `temp` klingt aber irgendwie langweilig. Deshalb benennen wir die Tabelle in `test` um:
mysql> ALTER TABLE temp -> RENAME test; Query OK, 0 rows affected (0.00 sec) mysql> SHOW columns FROM temp; ERROR 1146: Table 'cr.temp' doesn't exist mysql> SHOW columns FROM test; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | eins | varchar(10) | | | | | | zwei | varchar(20) | YES | | NULL | | | vier | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql>
Zum Schluß löschen wir wieder die ganze Tabelle:
mysql> DROP TABLE test; Query OK, 0 rows affected (0.00 sec) mysql> SHOW columns FROM test; ERROR 1146: Table 'cr.test' doesn't exist mysql>
Die letzte Fehlermeldung besagt, daß die Tabelle nicht existiert. Diese Fehlermeldung bekommt man auch, wenn man sich beim Tabellennamen verschrieben hat (auch Groß-/Kleinschreibung).
Up: Praktischer Teil SQL
Previous: SQL benutzen
Next: Tips & Tricks