Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich KAPITEL 3 Ihre Datenbestände können Sie jetzt nach allen Regeln der Kunst abfragen. Für den Teil der Datenbankbenutzer, die an reinen Auskunftssystemen arbeiten, dürfte damit der Fall bereits erledigt sein. Die Pflege der Daten, d.h. das Einfügen neuer, Überarbeiten vorhandener und Löschen nicht mehr benötigter Daten übernimmt oftmals eine zentrale Stelle mit entsprechendem Personal und einem Datenbankadministrator, der sich um die Wartung der Datenbank kümmert. Wenn Sie aber zum Kreis derjenigen gehören, die den Datenbestand auf dem Laufenden halten müssen, wenn Sie Datenbankanwendungen programmieren oder wenn Sie Administrator und Benutzer in Personalunion sind, müssen Sie auch wissen, wie sich neue Daten in die Datenbank einfügen und vorhandene Daten bearbeiten bzw. löschen lassen. Dieses Kapitel erläutert die dafür verfügbaren SQL-Anweisungen und zeigt außerdem, wie Sie die auf der Begleit-CD enthaltenen Beispieldaten in die Datenbank cd einlesen. Mit der Anweisung INSERT (Einfügen) nehmen Sie neue Datensätze in eine Tabelle auf, UPDATE (Aktualisieren) dient zum Bearbeiten vorhandener Datensätze und schließlich lassen sich mit DELETE (Löschen) Datensätze aus der Datenbank entfernen. Diese Anweisungen gehören zur Kategorie der Datenmanipulationssprache (Data Manipulation Language, DML) von SQL. Bei den Anweisungen UPDATE und DELETE treffen Sie wieder auf die Klauseln, die Ihnen von der SELECT-Anweisung aus Kapitel 2 her bekannt sind. Der letzte Abschnitt dieses Kapitels streift kurz die Anweisungen zum Masseneinfügen, mit denen sich Datensätze aus Dateien mit nur einer einzigen Anweisung auf einen Schlag in eine Tabelle übertragen lassen. 73 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich 1 Die Anweisungen in diesem Kapitel beziehen sich auf die Datenbank cd. Wenn Sie das Datenbanksystem neu gestartet haben, führen Sie als Erstes die Anweisung USE cd aus, um cd zur aktuellen Datenbank zu machen, wie es Kapitel 1 erläutert hat. 3.1 Daten einfügen – INSERT Bevor Sie Daten abrufen, bearbeiten oder löschen können, müssen Sie die Datenbank zuerst einmal »bestücken«, sprich mit Daten füllen. Mit der Anweisung INSERT lassen sich einzelne oder alle Felder eines Datensatzes in eine Tabelle einfügen: Beispiel 3.1 INSERT INTO cddata (artist, id) VALUES ('Donovan', '45376816') Diese Anweisung fügt einen neuen Datensatz in die Tabelle cddata ein und schreibt die Werte Donovan und 45376816 in die Spalten artist bzw. id. Die Anweisung INSERT arbeitet datensatzweise, man kann weder mehrere Datensätze auf einmal einfügen, noch mit mehreren INSERT-Anweisungen nacheinander einzelne Felder desselben Datensatzes füllen. Fehlende Felder ersetzt das Datenbanksystem entweder durch festgelegte Standardwerte oder durch einen speziellen Wert, der einen unbekannten Inhalt kennzeichnet – mehr dazu gleich. 3.1.1 Vollständige Werteliste einfügen Die einfachste Form der Anweisung INSERT sieht wie folgt aus: Syntax: INSERT [INTO] Tabellenname VALUES(Werteliste) Wie der Abschnitt »Syntaxdarstellungen lesen« in Kapitel 2 erläutert hat, ist das in eckigen Klammern stehende Schlüsselwort INTO optional. Mit Tabellenname spezifizieren Sie die Zieltabelle, in die der Datensatz einzufügen ist. Nach dem Schlüsselwort VALUES geben Sie die einzufügenden Werte – jeweils durch Komma getrennt – an. Diese Syntaxform der INSERT-Anweisung verlangt, dass Sie alle Spalten der Zieltabelle in der Werteliste aufführen und dabei auch die Reihenfolge beachten müssen, wie sie die Tabellendefinition vorschreibt. Da die Tabelle cddata der Datenbank cd aus 15 Spalten besteht, müssen Sie auch 15 Werte bereitstellen. 74 Daten einfügen – INSERT In Kapitel 5 erfahren Sie, wie eine Tabellendefinition aufgebaut ist. Als Beispiel nehmen wir eine CD mit der ID 45376816 von Donovan. Die CD enthält 20 Titel, die in der Tabelle cddata jeweils einen Datensatz mit 15 Feldern ergeben. Einen vollständigen Titeleintrag fügen Sie mit folgender Anweisung ein: INSERT INTO cddata VALUES('45376816','Donovan', 'The very best of Donovan','0',4250787,20,'Pop', 'CD','',1,'','Sunshine Superman',275027,'','') jetzt lerne ich 1 Beispiel 3.2 In dieser Anweisung fällt auf, dass einige Felder lediglich aus zwei einfachen Anführungszeichen bestehen. Wenn Sie für ein Feld keinen Wert bereitstellen, muss dieses Feld dennoch in der Werteliste erscheinen, was durch die beiden Anführungszeichen und das Komma symbolisiert wird. Die Anweisung ist aufgrund ihrer Länge zu breit für eine gedruckte Buchseite und wurde deshalb auf drei Zeilen umbrochen. Genauso können Sie auch bei der Eingabe der Anweisung verfahren. Es ist sogar möglich, mitten in einer Zeichenfolge auf eine neue Zeile zu wechseln. Beispielsweise ist folgende Eingabe zulässig (wenn auch wenig sinnvoll): 1 INSERT INTO cddata VALUES('45376816','Dono van', 'The very best of Donovan','0',4250787,20,'Pop', 'CD','',1,'','Sunshine Superman' ,275027,'','') Manchmal ist es nicht nötig oder möglich, für alle Felder Werte anzugeben. Wenn Sie aber in einer Anweisung wie INSERT INTO cddata VALUES ('Wert1', 'Wert2', 'Wert3') Beispiel 3.3 lediglich drei statt 15 Werte angeben, erhalten Sie in MySQL die Fehlermeldung: ERROR 1136: Column count doesn't match value count at row 1 SQL Server zeigt folgende Meldung an: Meldung 213, Ebene 16, Status 4, Server SER, Zeile 1 INSERT-Fehler: Spaltenname oder Anzahl der übergebenen Werte entspricht nicht der Tabellendefinition. Beide Meldungen sagen das Gleiche aus – es fehlen Spaltenwerte. Weil die obige Anweisung nichts über die Spalten aussagt, ermittelt INSERT die Anzahl der Spalten aus der Tabellendefinition, die im Datenbanksystem gespeichert ist. 75 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich 3.1.2 Einzelne Werte einfügen Wenn man nicht alle Werte bereitstellen möchte, kann man die optionale Spaltenliste spezifizieren. Nur für die hier genannten Spalten sind Werte in der Anweisung erforderlich. Die ergänzte Syntax der INSERT-Anweisung lautet: Syntax: INSERT [INTO] Tabellenname [(Spaltenliste)] {[DEFAULT] VALUES | VALUES (Wert[,...n]) | Auswahlanweisung } Die Reihenfolge der Spalten in der Spaltenliste muss nicht mit der Reihenfolge der Spalten in der Tabellendefinition übereinstimmen. Die Werte in der Werteliste müssen aber in der Reihenfolge erscheinen, wie sie durch die Spaltenliste vorgegeben ist: Beispiel 3.4 INSERT INTO cddata (artist, id) VALUES ('Donovan', '45376816') Diese Anweisung stellt für den neu einzufügenden Datensatz lediglich zwei der 15 möglichen Werte bereit. Was passiert mit den übrigen Feldern im Datensatz? Rufen Sie dazu außer id und artist noch einige andere Spalten ab: Beispiel 3.5 SELECT id, artist, category, title, tracknum FROM cddata WHERE id = 45376816 +----------+---------+----------+--------------------------+----------+ | id | artist | category | title | tracknum | +----------+---------+----------+--------------------------+----------+ | 45376816 | Donovan | Pop | The very best of Donovan | 1 | | 45376816 | Donovan | NULL | NULL | NULL | +----------+---------+----------+--------------------------+----------+ 2 rows in set (0.00 sec) Der erste Datensatz stammt noch aus dem Beispiel des letzten Abschnitts, bei dem alle 15 Felder bereitgestellt wurden. Für den zweiten Datensatz haben wir in der obigen Anweisung nur die Felder id und artist angegeben. Diese beiden Werte stehen in den richtigen Spalten, die übrigen Spalten enthalten den Eintrag NULL. NULL ist in jeder Hinsicht ein besonderer Wert. Wenn Sie beispielsweise die WHERE-Klausel in der SELECT-Anweisung wie folgt ergänzen Beispiel 3.6 SELECT id, artist, category, title, tracknum FROM cddata WHERE id = 45376816 AND tracknum <> 1 erhalten Sie nicht etwa den erwähnten zweiten Datensatz, der in der Spalte tracknum den Eintrag NULL enthält (was zweifellos ungleich 1 ist), sondern gar keinen Datensatz zurück! Der folgende Abschnitt erläutert, warum das so ist. 76 Daten einfügen – INSERT jetzt lerne ich Für nicht angegebene Werte kann man anstelle von NULL auch so genannte Standardwerte einfügen lassen, die in der Anweisung zum Erstellen der Tabelle festgelegt werden. Mehr dazu erfahren Sie in Kapitel 5. In der INSERTAnweisung legen Sie mit der Klausel DEFAULT VALUES (die allerdings in MySQL nicht implementiert ist) fest, dass in alle Spalten die entsprechenden Standardwerte eingetragen werden: INSERT INTO cddata DEFAULT VALUES Beispiel 3.7 Wie die obige Syntaxdarstellung gezeigt hat, kann man entweder DEFAULT VALUES, das Schlüsselwort VALUES mit einer Werteliste oder eine Auswahlanweisung angeben. Deshalb ist es mit DEFAULT VALUES nicht möglich, nur einige Werte zu spezifizieren und für die übrigen Werte die Standardwerte bereitstellen zu lassen. Gemäß der in Kapitel 2 im Abschnitt »Syntaxdarstellungen lesen« erläuterten Konventionen stehen die geschweiften Klammern um eine Gruppe von Elementen (hier: DEFAULT VALUES, VALUES und Auswahlanweisung), von denen eines obligatorisch ist – und zwar nur eines und nicht mehrere. 1 Wenn ein Wert nicht angegeben ist, muss das Datenbanksystem einen Standardwert bereitstellen können, was aber nicht immer ohne weiteres möglich ist. Wie bereits erwähnt, erhalten nicht spezifizierte Spalten den Wert NULL zugewiesen. Wenn aber die betreffende Spalte keine NULL-Werte zulässt und die Spalte weder einen Standardwert noch einen Datentyp aufweist, der einen Wert automatisch zuweist, schlägt die INSERT-Anweisung fehl. Mehr zur NULL-Zulässigkeit erfahren Sie in Kapitel 5 beim Thema Tabellendefinition. 3.1.3 Reihenfolge der Spalten Im relationalen Datenbankmodell (siehe Kapitel 5) ist die Reihenfolge der Zeilen und Spalten einer Tabelle nicht relevant und lässt sich per SQL jederzeit ändern. Wenn Sie mit der INSERT-Anweisung alle Spaltenwerte für einen Datensatz einfügen, ohne die Spalten zu spezifizieren, besteht die Gefahr, dass Werte nach Änderungen der Datenbankstruktur in falschen Spalten landen. Deshalb empfiehlt es sich, die Spaltennamen explizit in der Spaltenliste der INSERT-Anweisung aufzuführen. 77 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich 3.1.4 Wahrheitswerte und der besondere Wert NULL Wer schon mit anderen Programmiersprachen zu tun hatte, kennt Wahrheitswerte als Ergebnis logischer Ausdrücke: TRUE (wahr), wenn die formulierte Bedingung zutrifft, und FALSE (falsch), wenn die Bedingung nicht erfüllt ist. Es sind also nur zwei mögliche Werte definiert. Anders in SQL: Neben den hier ebenfalls verwendeten Werten TRUE und FALSE gibt es noch einen dritten Zustand des Ergebnisses: UNKNOWN (unbekannt). Mit diesem Wert kommen Sie immer dann in Berührung, wenn Tabellenspalten keine Daten enthalten. SQL sieht für solche Spalten den besonderen Wert NULL vor. Das ist kein Wert, den man »anfassen« kann, es handelt sich weder um die Zahl 0 noch um eine leere Zeichenfolge – denn das sind schon wieder konkrete Werte. Der Wert NULL wird Spalten zugewiesen, wenn beim Einfügen kein Wert explizit angegeben wird. Im ersten Beispiel der INSERT-Anweisung mit vollständiger Werteliste wurden fehlende Werte durch '', symbolisiert. Was macht SQL mit solchen Werten? Erweitern Sie dazu die zuletzt verwendete INSERTAnweisung um zwei zusätzliche Spalten, eine Zeichenfolgenspalte (category) und eine Zahlenspalte (tracknum): Beispiel 3.8 INSERT INTO cddata (artist, id, category, tracknum) VALUES ('Donovan', '45376816','',''); Rufen Sie wieder die entsprechenden Datensätze ab: Beispiel 3.9 SELECT id, artist, category, title, tracknum FROM cddata WHERE id = 45376816 +----------+---------+----------+--------------------------+----------+ | id | artist | category | title | tracknum | +----------+---------+----------+--------------------------+----------+ | 45376816 | Donovan | Pop | The very best of Donovan | 1 | | 45376816 | Donovan | NULL | NULL | NULL | | 45376816 | Donovan | | NULL | 0 | +----------+---------+----------+--------------------------+----------+ 3 rows in set (0.01 sec) Interessant ist jetzt der dritte Datensatz: Für category und tracknum hat MySQL eine leere Zeichenfolge bzw. den Zahlenwert 0 eingesetzt, weil diese beiden Spalten in der Spaltenliste aufgeführt sind und mit '' in der Werteliste jeweils ein definierter Wert angegeben wurde. In der Spalte title steht dagegen wieder die NULL, weil diese Spalte in der INSERT-Anweisung nicht explizit benannt wurde. Mit dem Wert NULL bringt SQL sozusagen zum Ausdruck: »Ich weiß nicht, was soll es bedeuten.« Im Gegensatz zu anderen Programmiersprachen sind TRUE und FALSE in SQL lediglich ein Ausdrucksmittel, um den logischen Wert verbal zu beschreiben. Dagegen kann man den Wert NULL in Ausdrücken verwenden. Die arithmeti- 78 Daten einfügen – INSERT jetzt lerne ich schen Vergleichsoperatoren liefern aber bei Vergleichen, an denen mindestens ein NULL-Wert beteiligt ist, das Ergebnis NULL zurück. Der Zustand UNKNOWN ist gleichbedeutend mit dem Wert NULL. Zum Beispiel führt die Anweisung mysql> SELECT 1 > NULL; Beispiel 3.10 zum Ergebnis: +----------+ | 1 > null | +----------+ | NULL | +----------+ 1 row in set (0.00 sec) In dieser Anweisung dient SELECT lediglich dazu, das Ergebnis des nachfolgenden Ausdrucks auszugeben (siehe den Abschnitt »SELECT ohne FROM« in Kapitel 2). 1 Für Vergleiche mit NULL-Werten ist der Operator IS NULL vorgesehen: SELECT id, artist, category, title, tracknum FROM cddata WHERE id = 45376816 AND tracknum IS NULL Beispiel 3.11 +----------+---------+----------+-------+----------+ | id | artist | category | title | tracknum | +----------+---------+----------+-------+----------+ | 45376816 | Donovan | NULL | NULL | NULL | +----------+---------+----------+-------+----------+ 1 row in set (0.01 sec) Die logische Umkehrung des Vergleichs erfolgt mit IS NOT NULL: SELECT id, artist, category, title, tracknum FROM cddata WHERE id = 45376816 AND tracknum IS NOT NULL Beispiel 3.12 +----------+---------+----------+--------------------------+----------+ | id | artist | category | title | tracknum | +----------+---------+----------+--------------------------+----------+ | 45376816 | Donovan | Pop | The very best of Donovan | 1 | | 45376816 | Donovan | | NULL | 0 | +----------+---------+----------+--------------------------+----------+ 2 rows in set (0.03 sec) Tests mit Vergleichsoperatoren auf Spalten, die NULL-Werte enthalten, liefern NULL als Ergebnis, während Tests mit dem Operator IS auf Spalten, die NULLWerte enthalten, logisch wahr (TRUE) oder falsch (FALSE) liefern. 79 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich 1 In SQL Server kann man über die Einstellung ANSI_NULLS festlegen, wie NULL-Werte in Vergleichen behandelt werden. Ist ANSI_NULLS auf ON gestellt, liefern Vergleiche mit NULL-Werten nicht das Ergebnis TRUE oder FALSE, sondern UNKNOWN. Dieses Verhalten entspricht dem ANSI-Standard. MySQL erlaubt es, das Ergebnis eines logischen Vergleichs als numerischen Wert aufzufassen und weiterzuverarbeiten: Beispiel 3.13 mysql> SELECT 5 + (3 IS NOT NULL); +---------------------+ | 5 + (3 is not null) | +---------------------+ | 6 | +---------------------+ 1 row in set (0.00 sec) Der Ausdruck 3 IS NOT NULL liefert das Ergebnis TRUE, das MySQL mit dem numerischen Wert 1 beschreibt. Der resultierende Ausdruck 5 + (1) ergibt dann das dargestellte Ergebnis 6. Mit SQL Server kann man solche Spielchen nicht treiben. Führt man hier die gleiche Anweisung aus, erhält man eine Fehlermeldung. 3.1.5 Daten aus einer anderen Tabelle einfügen Nehmen wir an, Sie beziehen Ihre Daten aus einer Quelle, deren Format noch nicht dem Ihrer Datenbanktabellen entspricht. Entweder lassen Sie die Daten im Vorfeld aufbereiten, d.h. durch die Clientanwendung, die auf die Datenbank zugreift, oder Sie lesen die Daten zunächst in eine Hilfstabelle ein, um sie dann später in den richtigen Formaten auf die endgültigen Zieltabellen zu verteilen. Die Beispiele im Buch verwenden natürlich den zweiten Ansatz, um die Möglichkeiten von SQL zu demonstrieren. Um die Daten aus der Hilfstabelle in die endgültige Zieltabelle zu übertragen, kann man die INSERT-Anweisung durch eine Auswahlanweisung (d.h. eine SELECT-Anweisung) ergänzen. Diese Auswahlanweisung holt die gewünschten Daten aus der Hilfstabelle und die eigentliche INSERT-Anweisung fügt sie in die jeweiligen Zielspalten ein. In Kapitel 5 erstellen Sie eine neue Datenbank av, in die Sie die Datensätze der Datenbank cd übernehmen. Dort finden Sie auch ein Beispiel für die Konstruktion INSERT ... SELECT. Der folgende Steckbrief für die INSERT-Anweisung enthält bereits eine einfache Version. 80 Daten einfügen – INSERT jetzt lerne ich Steckbrief: INSERT Fügt einen neuen Datensatz in eine Tabelle ein. Beispiele: (1) INSERT INTO cddata (id, artist, title) VALUES (1234, 'Santana', 'Jingo') (2) INSERT INTO cddata VALUES('45376816','Donovan', 'The very best of Donovan','0',4250787,20,'Pop', 'CD','',1,'','Sunshine Superman',275027,'','') (3) INSERT INTO cddata DEFAULT VALUES (4) INSERT av.cddata SELECT * FROM cd.cddata (1) Fügt einen neuen Datensatz in die Tabelle cddata ein. Die Felder id, artist und title erhalten die Werte »1234«, »Santana« bzw. »Jingo«; in die nicht spezifizierten Spalten der Tabelle cddata schreibt das Datenbanksystem Standardwerte (falls für die jeweilige Spalte spezifiziert) oder NULL. (2) Fügt einen neuen Datensatz in die Tabelle cddata ein, wobei für jede Spalte ein Wert anzugeben ist. (3) Fügt einen neuen Datensatz in die Tabelle cddata ein. In die einzelnen Spalten werden die Standardwerte eingetragen, die in der Definition der Tabelle cddata festgelegt sind. (4) Fügt in die Tabelle cddata der Datenbank av alle Datensätze ein, die mit der Auswahlanweisung SELECT * FROM ... aus der Tabelle cddata der Datenbank cd übernommen werden. Syntax: INSERT [INTO] {Tabellenname | Sichtname} [(Spaltenliste)] {[DEFAULT] VALUES | VALUES (Wert[,...]) | Auswahlanweisung} Argumente: – INTO: Schlüsselwort, das in den meisten Implementierungen von Datenbank-Managementsystemen optional ist. – Tabellenname, Sichtname: Bezeichnet die Tabelle bzw. Sicht, in die der neue Datensatz einzufügen ist. – Spaltenliste: Eine optionale Liste der Spalten, für die Werte in der Anweisung angegeben werden. Fehlt die Spaltenliste, muss man Werte für alle Spalten bereitstellen. 81 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich – [DEFAULT] VALUES: Legt fest, dass das Datenbanksystem für alle Spalten Standardwerte eintragen soll. – Wert: Für jede in Spaltenliste aufgeführte Spalte bzw. für alle Spalten der in die jeweilige Spalte einzutragende Wert. 3.2 Daten modifizieren – UPDATE Die Anweisung UPDATE erlaubt es, gezielt Spaltenwerte einer Tabelle zu ändern. Während INSERT einfach nur einen neuen Datensatz in die Tabelle einfügt, erfüllt die Anweisung UPDATE zwei Aufgaben: 쐽 Suchen der Datensätze, die den spezifizierten Kriterien entsprechen 쐽 Ändern der in der Anweisung angegebenen Werte in den gefundenen Datensätzen Wenn Sie in einer INSERT-Anweisung nicht alle Felder eines Datensatzes spezifiziert haben, können Sie die noch fehlenden Felder desselben Datensatzes nicht im Nachhinein mit einer weiteren INSERT-Anweisung ergänzen. Wie sollte SQL auch den richtigen Datensatz aus der Menge der bereits gespeicherten finden? Eine FROM-Klausel kennt die INSERT-Anweisung nicht. Ist nun das Unternehmen »Einfügen weiterer Werte in denselben Datensatz« gescheitert? Natürlich nicht. Änderungen an einem bestehenden Datensatz kann man über die UPDATE-Anweisung vornehmen. Die Syntax der Anweisung UPDATE lautet: UPDATE Tabellenname SET {Spaltenname | Variablenname} = {DEFAULT | Ausdruck} [,...n] WHERE Bedingungen Hier finden Sie auch die WHERE-Klausel, mit der Sie die zu ändernden Datensätze herausfiltern können. Ohne WHERE-Klausel wirkt die UPDATE-Anweisung auf alle Datensätze der Tabelle. 3.2.1 Werte ändern – SET Das bestimmende Element der UPDATE-Anweisung ist die SET-Klausel. Was sich hinter Spaltenname verbirgt, haben Sie sicherlich schon selbst erraten: Hier spezifizieren Sie die Spalte, die mit dem in Ausdruck angegebenen Wert zu ändern ist. Im einfachsten Fall weisen Sie der Spalte einen neuen Wert zu, d.h. überschreiben gegebenenfalls einen schon vorhandenen Wert. Die Spalte comment ist in allen Datensätzen der Beispieldatenbank leer und bietet sich für Experimente an. Die folgende Anweisung setzt diese Spalte zunächst für alle CDs auf die Zeichenfolge »Eigene Sammlung«: 82 Daten modifizieren – UPDATE UPDATE cddata SET comment = 'Eigene Sammlung' jetzt lerne ich Beispiel 3.14 Rufen Sie die Datensätze zur Kontrolle ab: SELECT id, comment FROM cddata Beispiel 3.15 +----------+-----------------+ | id | comment | +----------+-----------------+ | 667454 | Eigene Sammlung | | 667454 | Eigene Sammlung | | 667454 | Eigene Sammlung | ... | 49639765 | Eigene Sammlung | | 49639765 | Eigene Sammlung | | 49639765 | Eigene Sammlung | +----------+-----------------+ 470 rows in set (0.00 sec) Die für UPDATE in diesem Kapitel angegebenen Beispiele gehen wieder von der Installationsversion der Datenbank cd mit 470 Datensätzen aus. 1 Der Ausdruck kann auch die zu aktualisierende Spalte selbst enthalten. Nehmen wir einmal an, Sie möchten die bislang in Millisekunden angegebene Spielzeit der CDs in Anzahl der Sekunden ausdrücken. Dazu sind die Spalten totallength und tracklength jeweils durch 1000 zu dividieren. Da sich diese Operation auf alle Datensätze bezieht, kann die WHERE-Klausel entfallen. Die UPDATE-Anweisung sieht dann folgendermaßen aus: UPDATE cddata SET totallength = totallength / 1000, tracklength = tracklength / 1000 Beispiel 3.16 +----------+-------------+-------------+ | id | totallength | tracklength | +----------+-------------+-------------+ | 667454 | 648 | 201 | | 667454 | 648 | 240 | | 667454 | 648 | 208 | | 1335934 | 919 | 211 | ... | 49639765 | 4418 | 233 | | 49639765 | 4418 | 226 | | 49639765 | 4418 | 122 | | 49639765 | 4418 | 342 | +----------+-------------+-------------+ 470 rows in set (0.00 sec) 83 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich 1 Wie eingangs erwähnt, kann man die Ausführung der UPDATE-Anweisung in Teile gliedern. Dabei entspricht der erste Teil einer SELECT-Anweisung. Um sicher zu sein, dass UPDATE auch die richtigen Datensätze aktualisiert, empfiehlt es sich in der Testphase, zur Kontrolle zunächst eine SELECT-Anweisung mit der gleichen WHERE-Bedingung wie in der geplanten UPDATE-Anweisung auszuführen. Damit erhält man alle Datensätze zurück, die letztlich von der UPDATE-Anweisung beeinflusst werden. 3.2.2 UPDATE mit WHERE-Klausel Abgesehen von Fällen, wie sie der letzte Abschnitt an einem Beispiel gezeigt hat, ändert man Datensätze normalerweise nicht im Rundumschlag, sondern abhängig von bestimmten Kriterien. Die Syntax der UPDATE-Anweisung sieht deshalb eine WHERE-Klausel vor, in der Sie genau wie bei SELECT bestimmte Bedingungen formulieren können. Angenommen, Sie haben die Spielzeiten mit der obigen Anweisung durch 1000 dividiert und anschließend neue Datensätze eingefügt. Die Spalten totallength und tracklength der neuen Datensätze enthalten aber wieder die Zeiten in Millisekunden. Wenn Sie die einfache UPDATE-Anweisung noch einmal ausführen, werden die bereits durch 1000 dividierten Werte noch einmal durch 1000 geteilt. Als Kriterium, ob die Zeiten in einem Datensatz durch 1000 zu teilen sind, kann man die Gesamtspielzeit (totallength) heranziehen. In den Beispieldatensätzen bewegen sich diese Werte zwischen 648454 und 4747987 Millisekunden. Durch 1000 geteilt ergeben sich Werte zwischen 648 und 4748. Wenn also in der Spalte totallength ein Wert größer als 4748 steht, muss es sich um einen neu eingefügten Datensatz handeln, dessen Zeiten anzupassen sind. Um auf der sicheren Seite zu sein, wählen wir 20000 als Grenzwert und schreiben die UPDATE-Anweisung wie folgt: Beispiel 3.17 UPDATE cddata SET totallength = totallength / 1000, tracklength = tracklength / 1000 WHERE totallength > 20000 Diese Anweisung aktualisiert die Spalten totallength und tracklength eines Datensatzes nur dann, wenn der Wert in totallength größer als 20000 ist und damit auf einen neuen Datensatz hinweist. 1 84 SQL Server erlaubt in der UPDATE-Anweisung eine FROM-Klausel. Damit ist es möglich, Spalten aus verschiedenen Tabellen in der Bedingung zu verknüpfen. Kapitel 7 geht näher auf das Thema Verknüpfungen ein. Ebenfalls in diesem Kapitel geht es um Unterabfragen in der WHERE-Klausel einer UPDATEAnweisung. Daten löschen – DELETE jetzt lerne ich Steckbrief: UPDATE Modifiziert festgelegte Spaltenwerte bereits vorhandener Datensätze in einer Tabelle oder Sicht. Beispiele: (1) UPDATE cddata SET id = '0000' WHERE title LIKE '%xxx%' (2) UPDATE cddata SET totallength = totallength / 1000, tracklength = tracklength / 1000 WHERE totallength > 20000 (1) Setzt den Wert der Spalte id auf die Zeichenfolge »0000« für alle Datensätze, die in der Spalte title an einer beliebigen Stelle die Zeichenfolge »xxx« enthalten. (2) Teilt alle Werte in den Spalten totallength und tracklength durch 1000 für alle Datensätze, die in der Spalte totallength einen Wert größer als 20000 aufweisen. Syntax: UPDATE Tabellenname SET {Spaltenname | Variablenname} = {DEFAULT | Ausdruck} [,...n] WHERE Bedingungen Argumente: – Tabellenname: Gibt die Tabelle an, in der Spaltenwerte zu modifizieren sind. – Spaltenname: Bezeichnet die Spalte, deren Werte zu modifizieren sind. – Variablenname: Eine bereits deklarierte Variable, der das Ergebnis von Ausdruck zugewiesen wird. – Ausdruck: Ein einzelner Wert von einer Variablen, einem Literalwert, einem Ausdruck oder einer Unterabfrage. – Bedingungen: Gibt die Bedingungen an, denen die zu aktualisierenden Datensätze genügen müssen. 3.3 Daten löschen – DELETE Die letzte Anweisung der Datenmanipulationssprache hat die einfachste Syntax, aber die radikalste Wirkung: DELETE löscht Datensätze. Die Syntax ist überschaubar: DELETE [FROM] Tabellenname [WHERE Bedingungen] 85 jetzt lerne ich 3 Daten modifizieren – INSERT, UPDATE und DELETE Das Schlüsselwort FROM ist optional; in Tabellenname geben Sie die Tabelle an, aus der die Datensätze zu löschen sind. Wenn Sie die WHERE-Klausel vergessen, löscht SQL gnadenlos sämtliche Datensätze in der Tabelle. Die Tabelle an sich bleibt zwar erhalten, doch ihr Inhalt landet im Nirwana. In Kapitel 5 lernen Sie mit TRUNCATE TABLE eine Anweisung kennen, die das Gleiche noch schneller erledigt. Sinnvoll ist DELETE also nur zusammen mit der WHERE-Klausel, um einzelne Datensätze zu löschen, die beispielsweise veraltet oder infolge einer Aktualisierung ungültig geworden sind. Wenn Sie die weiter oben mit INSERT eingefügten Titel wieder löschen möchten, führen Sie folgende Anweisung aus: Beispiel 3.18 DELETE FROM cddata WHERE id = 45376816 Das Ergebnis ist genauso unspektakulär wie die DELETE-Anweisung selbst: Query OK, 1 row affected (0.28 sec) Falls Sie mehrere Datensätze für die CD mit der ID 45376816 eingefügt haben, erscheinen entsprechend mehr Spalten in der Meldung. 2 Überlegen Sie genau, welche Auswirkung die DELETE-Anweisung auf die Tabelle hat und haben könnte. Im Beispiel ist die WHERE-Bedingung mit der Spalte id formuliert, die eindeutige Werte enthält. Wenn Sie als Bedingung WHERE artist like '%donovan%' angeben, löschen Sie zwar in der hier verwendeten Beispieltabelle nur die Datensätze, die Sie zuletzt mit den weiter oben vorgestellten INSERT-Anweisungen in die Datenbank eingefügt haben (weil es keine anderen DonovanTitel in der Datenbank gibt), bei einer größeren Sammlung können aber durchaus mehrere CDs betroffen sein. Der Abschnitt zur UPDATE-Anweisung hat bereits darauf hingewiesen, dass es gerade in der Testphase sinnvoll ist, zunächst eine SELECT-Anweisung mit identischer WHERE-Klausel auszuführen und erst nach positivem Befund die DELETE-Anweisung auszulösen. Eine hundertprozentige Sicherheit gegen Überraschungen bietet das zwar nicht, weil auch Datensätze hinzukommen können, die Sie mit der SELECT-Anweisung für den aktuellen Datenbestand noch nicht »erwischt« haben, doch sind Ihre Sinne auf jeden Fall sensibilisiert, wenn Sie feststellen mussten, dass die zweite Version auch andere CDs betreffen kann, während die erste Version mit eindeutiger ID in der WHEREKlausel sicher ist. 86 Daten importieren Auch für die DELETE-Anweisung bietet SQL Server eine FROM-Klausel (nicht zu verwechseln mit dem optionalen Schlüsselwort FROM unmittelbar nach DELETE, um Spalten aus verschiedenen Tabellen in der Bedingungsklausel zu verknüpfen). Mehr dazu finden Sie in Kapitel 7. jetzt lerne ich 1 Steckbrief: DELETE Löscht Datensätze aus einer Tabelle oder Sicht. Beispiel: DELETE FROM cddata WHERE id = '123456' Löscht aus der Tabelle cddata alle Datensätze, die in der Spalte id den Wert '123456' enthalten. Syntax: DELETE [FROM] {Tabellenname | Sichtname} WHERE Bedingungen Argumente: – FROM: Im SQL99-Standard und SQL Server optionales Schlüsselwort. – Tabellenname oder Sichtname: Die Tabelle bzw. die Sicht, aus der die Datensätze zu löschen sind. – Bedingungen: Gibt die Bedingungen an, die die zu löschenden Datensätze erfüllen müssen. 3.4 Daten importieren Normalerweise – d.h. mit den im ANSI-Standard definierten Anweisungen – können Sie jeweils nur einen einzelnen Datensatz in eine Tabelle einfügen (sieht man einmal davon ab, dass sich mit INSERT auch mehrere Datensätze von einer Tabelle in eine andere übertragen lassen). Für jeden einzufügenden Datensatz müssen Sie eine INSERT-Anweisung erzeugen und ausführen. Bei einer kleinen Beispieldatenbank fällt dieser Aufwand kaum ins Gewicht. Wenn Sie aber Tausende oder Millionen Datensätze aus externen Quellen einlesen möchten, ist die einfache INSERT-Anweisung umständlich und verschlingt ziemlich viel Zeit, da alle bisher vorgestellten Anweisungen protokolliert werden. Das Datenbanksystem führt sozusagen Buch darüber, was alles mit der Datenbank passiert, um im Falle eines Absturzes die protokollierten Operationen erneut ausführen und die Datenbank in den Zustand vor dem Absturz wiederherstellen zu können. 87 jetzt lerne ich 3 Daten modifizieren – INSERT, UPDATE und DELETE Wenn aber die Daten ohnehin in einer externen Quelle vorliegen, könnte man selbst bei einem Absturz der Datenbank erneut auf diese Daten zugreifen und sie noch einmal einlesen. Nach der nächsten Komplettsicherung der Datenbank kann man dann auch die Quelldaten löschen. Wozu also der Aufwand, jeden einzelnen Datensatz beim Einfügen zu protokollieren? Genau für diesen Zweck bieten fast alle Datenbanksysteme Anweisungen für so genannte Massenoperationen. Diese werden zwar nicht protokolliert, laufen aber ungleich schneller ab. Auch wenn der ANSI-Standard solche Anweisungen nicht vorsieht, sollten Sie sie kennen, weil sich damit das Einfügen großer Datenmengen effizienter realisieren lässt: MySQL stellt die Anweisung LOAD DATA INFILE bereit, in SQL Server heißt die vergleichbare Anweisung BULK INSERT. Dieser Abschnitt erläutert, wie die Daten für die Beispieldatenbank cd mit diesen Anweisungen erzeugt wurden. Damit sich Massenoperationen ausführen lassen, brauchen Sie eine geeignete Datenquelle, in der die Daten im benötigten Format vorliegen. Die aus der Datenbank von http://www.cdarchiv.de abgerufenen Daten wurden zunächst als Textdatei gespeichert und dann mithilfe eines kleinen Visual Basic-Programms zeilenweise in die Datei cddata.txt übernommen. Diese Textdatei hat folgenden Inhalt (Ausschnitt): 667454왘Sixpence None The Richer왘Kiss me왘0왘648454왘3왘Rock/Pop왘Maxi CD왘왘1왘왘Kiss me (Radio Remix)왘201094왘왘왘 667454왘Sixpence None The Richer왘Kiss me왘0왘648454왘3왘Rock/Pop왘Maxi CD왘왘2왘왘Sad but true (Previously unreleased)왘239641왘왘왘 667454왘Sixpence None The Richer왘Kiss me왘0왘648454왘3왘Rock/Pop왘Maxi CD왘왘3왘왘Kiss me (Live in Hollywood)왘207721왘왘왘 1335934왘Marque왘One to make her happy왘0왘919054왘4왘Rock/Pop왘Maxi CD왘왘1왘왘One to make her happy (Radio Edit)왘211294왘왘왘 Wenn Sie die Datei cddata.txt in einem Editor öffnen, sieht sie etwas anders aus als hier dargestellt. Zur Verdeutlichung steht im obigen Ausschnitt das Zeichen 왘 anstelle des Tabulatorzeichens, das in einem Editor nicht als Zeichen an sich sichtbar ist. Jeder Datensatz stellt die Werte für einen Titeleintrag in der Datenbank cd dar. Das Tabulatorzeichen trennt die einzelnen Felder eines Datensatzes. Wenn ein Feld keine Daten enthält, schließt sich gleich das Tabulatorzeichen als Trennzeichen zum nächsten Feld an. Eine Zeile wird durch das Zeichen für Neue Zeile beendet; der nächste Titeleintrag beginnt damit am Anfang der nächsten Zeile. 88 Daten importieren jetzt lerne ich Dieses Format – Trennung der einzelnen Felder durch Tabulatorzeichen, Zeilenabschluss durch Zeichen für neue Zeile – ist gleichzeitig das Standardformat, das die im Buch verwendeten Datenbanksysteme und auch andere Systeme als Format für die Übernahme von Textdaten in programmeigene Datenformate verwenden. 3.4.1 Daten importieren – MySQL Die MySQL-Anweisung LOAD DATA INFILE bietet die Möglichkeit, Daten aus einer (Text-) Datei in eine Tabelle zu importieren: LOAD DATA INFILE "C:/JLISQL/Data/CDData.txt" INTO TABLE cddata; Beispiel 3.19 In dieser Form verwendet die Anweisung Standardwerte für die Zeichen, mit denen die einzelnen Felder in der Textdatei voneinander getrennt sind (Tabulatoren zwischen den Feldern, Zeichen für neue Zeile am Ende der Zeile). Wenn Sie in der Textdatei andere Trennzeichen verwenden, können Sie das in der LOAD DATA INFILE-Anweisung wie folgt spezifizieren: LOAD DATA INFILE "C:/JLISQL/Data/CDIntro.txt" INTO TABLE cddata FIELDS TERMINATED BY ',' ENCLOSED BY '"'; Beispiel 3.20 Das Schlüsselwort FIELDS leitet die Spezifikation für die Feldtrennzeichen ein. Die Klausel TERMINATED BY gibt das Trennzeichen zwischen den einzelnen Feldern an (im Beispiel ein Komma). Mit ENCLOSED BY können Sie festlegen, in welche Begrenzer Zeichenfolgen eingeschlossen sind. Wenn die zu importierende Zeichenfolge ein Feldtrennzeichen (im Beispiel das Komma) enthält, würde dieses als Trennzeichen zwischen zwei Feldern interpretiert, was verständlicherweise zu Fehlern führt. In so einem Fall umschließt man die Zeichenfolge meistens mit Anführungszeichen. Die Importanweisung ignoriert dann die zwischen dem ersten und zweiten Anführungszeichen in der Zeichenfolge enthaltenen Trennzeichen. Wenn die importierten Datensätze nicht für alle Felder einen Wert enthalten, schreibt MySQL in die leeren Spalten den Wert '' (eine leere Zeichenfolge). Falls Sie den Wert NULL in leere Spalten eintragen möchten, müssen Sie das in der Textdatei mit \N kennzeichnen. 89 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich 3.4.2 Daten importieren – SQL Server Die zu LOAD DATA INFILE vergleichbare Anweisung in SQL Server heißt BULK INSERT. Beispiel 3.21 BULK INSERT cddata FROM "C:\JLISQL\Data\CDDataS.txt" Als Standardtrennzeichen verwendet SQL Server genau wie MySQL das Tabulatorzeichen (\t) und als Zeilenabschlusszeichen das Zeichen für neue Zeile (\n). Um andere Zeichen zu spezifizieren, leiten Sie mit dem Schlüsselwort WITH einen Block für optionale Werte ein (vergleichbar mit FIELDS in der MySQL-Anweisung LOAD DATA INFILE). Das Feldtrennzeichen legen Sie mit FIELDTERMINATOR und das Zeilenabschlusszeichen mit ROWTERMINATOR fest. Eine Option analog zu ENCLOSED BY von MySQL ist in BULK INSERT nicht verfügbar. Standardmäßig gilt das Anführungszeichen. Die folgende Anweisung legt das Komma als Feldtrennzeichen fest; für die übrigen Optionen gelten die Standardwerte: Beispiel 3.22 BULK INSERT cddata FROM "C:\JLISQL\Data\CDDataS.txt" WITH ( FIELDTERMINATOR=',' ) Die Anweisung BULK INSERT kennt noch eine ganze Reihe weiterer Optionen, auf die wir aber im Rahmen dieser Einführung nicht eingehen und auf die Dokumentation zu SQL Server verweisen. 1 Beispiel 3.23 SQL Server bietet mit bcp (bulk copy program) ein Kommandozeilenwerkzeug, das es nicht nur erlaubt, Datensätze in eine Datenbank zu importieren, sondern auch aus einer Datenbank zu exportieren. Die Formate für das Importieren bzw. Exportieren lassen sich mit unzähligen Schaltern auf der Befehlszeile sowie über eine Formatdatei steuern. bcp CD..CDData in CDData.csv -t, -Spro -T Gerade diese vielfältigen Möglichkeiten sind es aber auch, die bcp zur Glaubensfrage werden lassen. Es ist oftmals nicht ganz einfach, die richtige Kombination von Parametern für einen bestimmten Anwendungsfall zu finden. Probleme tauchen vor allem bei Datumswerten, Zeichenfolgen mit Feldtrennzeichen und der Konvertierung von Datentypen auf. Das Programm bcp stammt noch aus den Anfangstagen von SQL Server. Inzwischen steht mit den Data Transformation Services (DTS) ein grafisch orientiertes und äußerst flexibles Werkzeug zur Verfügung, mit dem sich unter anderem Daten aus heterogenen Quellen importieren und auch wieder exportieren lassen. 90 Zusammenfassung 3.5 jetzt lerne ich Zusammenfassung Dieses Kapitel hat die Anweisungen INSERT, UPDATE und DELETE behandelt, die zur Kategorie der Datenmanipulationssprache (DML) von SQL gehören. INSERT fügt jeweils einen neuen Datensatz ein. Man kann entweder alle oder ausgewählte Werte bereitstellen. Für nicht spezifizierte Spalten setzt das Datenbanksystem automatisch Standardwerte ein. Je nachdem, wie die Anweisung formuliert ist, handelt es sich dabei um den besonderen Wert NULL für unbekannte Daten bzw. 0 für Zahlenspalten und die leere Zeichenfolge für Zeichenspalten. Man kann aber auch eigene Standardwerte in der Tabellendefinition festlegen (siehe Kapitel 5). Die Anweisung UPDATE erlaubt es, einen oder mehrere Werte in bereits vorhandenen Datensätzen zu ändern. In der WHERE-Klausel der UPDATE-Anweisung legt man die Kriterien fest, für welche Datensätze die Änderungen wirksam werden. Die Anweisung DELETE löscht vollständige Datensätze aus einer Tabelle. Dabei ist besonders auf die richtige Formulierung der WHERE-Klausel zu achten, damit nicht versehentlich die falschen oder zu viele Datensätze gelöscht werden. Schließlich ist dieses Kapitel kurz auf die Anweisungen zum Masseneinfügen eingegangen, die zwar nicht im ANSI-Standard vorgesehen, aber in vielen Datenbanksystemen realisiert sind. In MySQL handelt es sich um die Anweisung LOAD DATA INFILE, SQL Server stellt die Anweisung BULK INSERT bereit. 3.6 Kontrollfragen 1. Muss man eine längere SQL-Anweisung auf ein und derselben Zeile eingeben oder kann man sie auf mehrere Zeilen aufteilen? 2. Wenn man einen Datensatz mit INSERT einfügt und nur bestimmte Spaltenwerte bereitstellt, kann man dann mit der Klausel DEFAULT VALUES erreichen, dass die übrigen Spalten Standardwerte erhalten? 3. Kann man mit zwei unmittelbar nacheinander ausgeführten INSERT-Anweisungen in der ersten Anweisung z.B. zwei Werte und in der zweiten Anweisung nochmals drei Werte in denselben neuen Datensatz einfügen? 4. Müssen die Spalten in der Spaltenliste einer INSERT-Anweisung in der Reihenfolge erscheinen, wie sie durch die Tabellendefinition festgelegt ist? 5. Wie lässt sich in einer INSERT-Anweisung erreichen, dass eine bestimmte Spalte den Wert NULL erhält? 6. Kann man sich auf die Aussage »der boolesche Wert TRUE wird durch 1 dargestellt, der boolesche Wert FALSE durch 0« in jedem Fall verlassen? 91 3 Daten modifizieren – INSERT, UPDATE und DELETE jetzt lerne ich 7. Gehört die WHERE-Klausel zu den obligatorischen Elementen einer UPDATEAnweisung? 8. Erlaubt die DELETE-Anweisung, einzelne Spalten einer Tabelle zu löschen? 3.7 Übungen 1. Schreiben Sie INSERT-Anweisungen, um die Titel der im Kapitel bereits erwähnten Donovan-CD in die Tabelle cddata einzufügen. Die Daten für diese CD finden Sie im Verzeichnis \JLISQL\Data in der Datei Donovan.txt. Hinweis: Die Felder der einzelnen Datensätze sind durch Tabulatoren getrennt. Wenn Sie die Datei in Ihrem Editor öffnen und unter einem anderen Namen wie zum Beispiel Donovan.sql speichern (um die Datei Donovan.txt unverändert für Übung 2 verfügbar zu haben), brauchen Sie nur noch die erforderlichen SQL-Elemente für die einzelnen INSERT-Anweisungen vor bzw. hinter die Datensätze zu schreiben und das Format der Datensätze anzupassen (z.B. Tabulatoren durch Kommas ersetzen und Anführungszeichen ergänzen). Beschränken Sie sich auf zwei oder drei Datensätze und löschen Sie die anderen. Die Datei Donovan.sql können Sie dann ausführen, wie es Kapitel 1 für die Installationsskripts beschrieben hat. 2. Schreiben Sie für das von Ihnen verwendete Datenbank-Managementsystem eine Anweisung zum Masseneinfügen, um alle Datensätze der Datei Donovan.txt (siehe Übung 1) in die Tabelle cddata der Datenbank cd einzulesen. 3. Schreiben Sie eine UPDATE-Anweisung, um die in Millisekunden angegebenen Zeitwerte in Minuten umzuwandeln. Formulieren Sie die Anweisung so, dass Sie sie mehrfach ausführen können, ohne dass bereits geänderte Werte noch einmal geändert werden. 4. Löschen Sie die in den Übungen 1 bzw. 2 eingefügten Datensätze aus der Tabelle cddata. Vergewissern Sie sich, dass die Tabelle wieder 470 Datensätze (wie nach der Installation) enthält. 92