Document

Werbung
jetzt lerne ich
Datenbanken mit
Visual Basic .NET
Der einfache Einstieg mit ADO.NET,
SQL, Jet-Engine und XML
PETER MONADJEMI
Schnellkurs SQL
jetzt lerne ich
KAPITEL 3
Die Datenbanksprache SQL steht bei ADO.NET im Mittelpunkt. Mit ihrer
Hilfe werden Datensätze abgerufen, gelöscht, aktualisiert und spezielle Informationen, wie die Anzahl der Datensätze, die Summe über einzelne Spalten
und vieles mehr, abgerufen. Auch gespeicherte Prozeduren in einer SQL-Server-Datenbank werden in SQL programmiert. Für (angehende) Datenbankprogrammierer sind SQL-Kenntnisse daher so wichtig wie gute Tischmanieren für Anwärter des diplomatischen Corps. In diesem Kapitel erhalten Sie
einen Schnellkurs in SQL, der Ihre SQL-Kenntnisse auf den Stand bringt, wie
er für die Alltagsaufgaben mit ADO.NET benötigt wird.
Die Themen für dieses Kapitel:
쐽 SQL – ein Standard mit Geschichte
쐽 SQL und Microsoft = T-SQL
쐽 SQL trainieren
쐽 Abfragen über SELECT
쐽 Datensätze einfügen mit INSERT
쐽 Datensätze aktualisieren mit UPDATE
쐽 Datensätze löschen mit DELETE
쐽 Abfragen über mehrere Tabellen – die Joins
쐽 SQL-Funktionen
쐽 SQL für etwas Fortgeschrittene: Gruppierungen und Unterabfragen
101
3 Schnellkurs SQL
쐽 Datenbanken und Tabellen anlegen
쐽 Etwas mehr SQL gibt es in Kapitel 6, in dem im Zusammenhang mit
gespeicherten Prozeduren und Funktionen die Microsoft SQL-Variante
T-SQL vorgestellt wird.
0
1
Dieses Kapitel kann die wichtigen Bereiche aus Platzgründen nur streifen.
Eine gründliche Einführung zum Thema SQL finden Sie in dem empfehlenswerten Buch Jetzt lerne ich SQL von Frank Langenau (Markt+Technik), in
dem außerdem die populären DBMS MDSE und MySQL gegenübergestellt
werden.
Der besseren Lesbarkeit wegen werden SQL-Kommandos und -Schlüsselwörter in diesem Kapitel (und weitestgehend im gesamten Buch) in Großbuchstaben dargestellt. Für die Programmierung als auch das Austesten mit
SQL-Tools spielt die Groß-/Kleinschreibung aber keine Rolle.
3.1
SQL – ein Standard mit Geschichte
offizielle SQL-Standard lautet SQL 92 und stammt, Sie werden es sich schon
denken können, aus dem Jahre 1992. Das hat aber nicht viel zu bedeuten, da
innerhalb der Microsoft-Welt natürlich Microsoft den Ton angibt und mit
T-SQL einen eigenen SQL-Standard geschaffen hat, der sich zu 95.5% an
SQL 92 anlehnen dürfte1. Es gibt auch einen Nachfolger von SQL 92 mit
dem Namen SQL 99, der SQL 92 eigentlich ersetzen soll. Inwieweit diese
Absicht tatsächlich einen Einfluss auf die SQL-Dialekte der bekannten Datenbankhersteller hat, entzieht sich meiner Kenntnis.2
1. Falls Sie bislang auf die Definition gewartet haben: SQL ist offiziell keine Abkürzung mehr
(früher stand es einmal für »Structured Query Language«).
2. Ich gehe davon aus, dass die offizielle Entwicklung des SQL-Standards praktisch keine Bedeutung mehr hat und ein eventuell doch noch verabschiedeter Standard keinen Einfluss auf TSQL haben dürfte, das vollkommen unabhängig von einem offiziellen Standard von Microsoft
weiterentwickelt wird. Hier gilt das Motto »Der beste Standard ist der, den man jeden Tag
benutzen kann«.
102
SQL und Microsoft = T-SQL
Wer es ganz genau wissen möchte, dem sei das Standardwerk zu SQL empfohlen: Guide to SQL Standard von Chris Date und Hugh Darwen (Verlag
Addison Wesley, ISBN 0201964260). Doch Vorsicht, erwarten Sie keine
locker, flockige Einführung im Stile eines »Jetzt lerne ich«-Buches. Das ist
»Hardcore-SQL«.
3.2
1
SQL und Microsoft = T-SQL
In der Microsoft-Welt spielt SQL eine wichtige Rolle, allerdings in Gestalt von
T-SQL (Transact SQL), das sich in einigen Details von SQL 92 unterscheidet.
Diese Details betreffen Kleinigkeiten und den Umstand, dass nicht alle Kommandos, die durch SQL 92 definiert werden, in T-SQL enthalten sind. Für die
praktische Programmierung hat dies aber keine Auswirkungen, zumal sich
nur die wenigsten .NET-Programmierer auch in anderen Welten bewegen
dürften. T-SQL unterscheidet sich von SQL vor allem durch den Umstand,
dass es viele neue Kommandos und Funktionen umfasst, mit denen sich zum
Beispiel kleine Programme (die gespeicherten Prozeduren und Funktionen)
programmieren lassen. Anders als SQL, das sich auf seine Kernbereiche beschränkt, ist T-SQL bereits eine richtige kleine Programmiersprache, wobei
T-SQL-Programme stets innerhalb der Datenbank ausgeführt werden und
zum Beispiel keine Ein- und Ausgaben durchführen (es gibt allerdings über
eine Systemprozedur die Möglichkeit, auf COM-Komponenten zuzugreifen).
Der »harte Kern« von SQL besteht nur aus wenigen Kommandos: SELECT, INSERT, UDPATE und DELETE und einer Hand voll Funktionen, wie MAX, AVG oder
TOP. Ganz so einfach ist SQL dann aber noch nicht, denn es gibt zahlreiche
Befehlswörter und spezielle Funktionen, mit denen ein SQL-Kommando angereichert wird. SQL muss daher wie eine Programmiersprache gelernt werden. Es dauert daher eine Weile, bis Sie in der Lage sein werden, die gewünschten Daten aus einer Datenbank abzurufen, und es kann Jahre dauern,
bis Sie auch die Feinheiten beherrschen. Geht es lediglich darum, Datensätze
nach einfachen Kriterien auszuwählen ist SQL kinderleicht. Sollen jedoch Beziehungen zwischen Tabellen berücksichtigt werden, kann es richtig »kompliziert« werden. Hier eine kleine Kostprobe, die den Unterschied deutlich machen wird. Die folgende Abfrage gibt die Namen aller Angestellten der
Northwind-Firma zurück:
SELECT LastName FROM Employees
Doch wie wäre es, wenn Sie die Summe aller Umsätze sehen möchten, die jeder Angestellte im Jahr 1994 gemacht hat? Das wäre natürlich toll, denn ansonsten müssten Sie relativ viel programmieren. Diese Information steckt natürlich nicht in einer einzigen Tabelle (auch wenn dies denkbar wäre, wäre
dies im Allgemeinen kein guter Ansatz), sie ergibt sich vielmehr aus der Kombination verschiedener Tabellen:
103
3 Schnellkurs SQL
SELECT Employees.LastName, SUM([Order Details].UnitPrice*[Order
Details].Quantity-[Order Details].UnitPrice/100*[Order
Details].Discount) AS Umsatz FROM [Order Details], Orders, Employees
WHERE [Order Details].OrderID=Orders.OrderID AND
Orders.EmployeeID=Employees.EmployeeID GROUP BY Employees.LastName
Diese Abfrage ist schon »ein wenig« komplizierter. Der Aufwand, sie zu verstehen, lohnt sich in jedem Fall, denn Sie erspart Ihnen nicht nur mehrere
Dutzend Zeilen Visual Basic-Code, sondern dürfte auch deutlich schneller sein
als seine Schleife, die eventuell zuerst alle Angestellten durchläuft, zu jedem
Angestellten den Umsatz abfragt und diesen aufaddiert. Es lohnt sich daher,
SQL gut zu beherrschen, denn es ist der Schlüssel zu den Inhalten einer Datenbank. Tabelle 3.1 gibt einen Überblick über die wichtigsten SQL-Kommandos.
Tabelle 3.1:
SQL-Kommando
Die wichtigsten
SQL-Komman- SELECT *FROM <Tabelle>
dos im Überblick SELECT Feld1, Feld2 FROM <Tabelle>
Bedeutung
Gibt alle Felder der angegebenen Tabelle
zurück.
Gibt nur die angegebenen Felder der angegebenen Tabelle zurück.
SELECT * FROM <Tabelle> WHERE
Feld1 < Wert
Gibt alle Datensätze zurück, die ein auf
WHERE folgendes Kriterium erfüllen.
SELECT MAX(Feld1) FROM <Tabelle>
Gibt den größten Wert der Spalte Feld1 als
Wert zurück.
UPDATE <Tabelle> SET Feld1=Wert1,
Feld2=Wert2 WHERE Feld1=Wert3
Aktualisiert die aufgeführten Felder der
Tabelle mit den angegebenen Werten,
wobei der zu aktualisierende Datensatz das
auf WHERE folgende Kriterium erfüllen muss.
INSERT INTO <Tabelle>
VALUES(Wert1,Wert2,Wert3)
Aktualisiert die Tabelle mit den in Klammern aufgeführten Werten. Diese Variante
geht davon aus, dass jedes der Felder mit
einem Wert belegt wird.
INSERT INTO <Tabelle> (Feld1,
Feld3) VALUES(Wert1, Wert3)
Aktualisiert die Tabelle mit den in Klammern aufgeführten Werten. Diese Variante
geht davon aus, dass nur bestimmte Felder
mit einem Wert belegt werden. Identitätsfelder (auch AutoIncrement genannt) werden
hier nicht aufgeführt, da ihr Inhalt automatisch von der Datenbank gesetzt wird.
DELETE FROM <Tabelle> WHERE
Feld1=Wert1
Löscht alle Datensätze aus der Tabelle, die
das angegebene Kriterium erfüllen.
3.2.1
Die Jet-Engine spricht auch SQL
In einer perfekten Welt gäbe es nur ein SQL, an das sich alle halten würden.
Doch aus den verschiedenen Gründen ist das nicht der Fall. Selbst innerhalb
104
SQL trainieren
der Microsoft-Welt gibt es verschiedene SQL-Dialekte. Neben T-SQL existiert
der SQL-Dialekt, der von der Jet-Engine verwendet wird und der sich ebenfalls eng an SQL 92 anlehnt. Gegenüber T-SQL gibt es ein paar wichtige Unterschiede:
쐽 Für die Platzhalter % und _ (der Unterstrich) werden die Symbole * und ?
verwendet. Allerdings sorgt OLE DB dafür, dass auch bei Jet-SQL % und
_ verwendet werden können. ADO.NET übernimmt dies natürlich beim
verwalteten Provider für OLE DB, so dass es keine Probleme geben sollte.
쐽 Jet-SQL unterstützt die (alten) Visual Basic-Funktionen wie DateDiff,
DateValue, Left, Right usw., was eine sehr praktische Angelegenheit ist,
da sich SQL-Abfrage beinahe so wie reguläre Visual Basic-Abfragen formulieren lassen. Auch T-SQL umfasst derartige Funktionen (allerdings
nicht in dieser Vielfalt), die aber eine etwas andere Syntax besitzen.
쐽 Jet-SQL unterstützt einen eigenen Abfragetyp, den es bei T-SQL nicht
gibt. Dafür kennt Jet-SQL keine gespeicherten Prozeduren, Funktionen
usw.
쐽 Bei den Datumsformaten gibt es geringfügige Unterschiede bei der Frage,
welche verschiedenen Variationen, ein Datum darzustellen, erkannt werden.
Die Auflistung macht deutlich, dass die Unterschiede im Allgemeinen zu gering sind, als dass sie sich in der Praxis auswirken könnten. Interessant werden diese Unterschiede auch nur dann, wenn ein Programm beide Datenbanktypen unterstützen soll oder wenn ein Programm von Jet-SQL auf
T-SQL »umgestellt« wird.
3.3
SQL trainieren
SQL lernt sich am besten durch Ausprobieren vieler kleiner Übungen. Zwar
wäre es kein allzu großer Aufwand, jedes SQL-Kommando in eine kleine Konsolenanwendung einzufügen, die das Kommando ausführt und das Ergebnis
in der Konsole ausgibt, aber es gibt noch eine bequemere Lösung. Diese besteht aus einem kleinen Programm, in dem Sie das SQL-Kommando nur eintippen und nach Drücken von Í das Ergebnis in einem DataGrid sehen. Einen solchen SQL-Trainer finden Sie an verschiedenen Stellen:
쐽 Auf der Buch-CD in Gestalt des Projekts SQLTrainer.sln im Verzeichnis
\Quellen\SQLTrainer.
쐽 In Gestalt des Query Analyzers, eines Zubehörprogramms des SQL Servers, das aber leider nicht bei der MSDE dabei ist.
105
3 Schnellkurs SQL
쐽 In Gestalt von QueryExpress, einem kostenlosen .NET-Programm von
Joseph Albahari, das beinahe die perfekte Ergänzung zur MSDE ist und
das Sie zum Beispiel zum Ausprobieren der SQL-Kommandos in diesem
Kapitel verwenden können.
Abb. 3.1:
QueryExpress
erlaubt das
schnelle Ausprobieren von
SQL-Kommandos.
3.3.1
QueryExpress als Allround-Werkzeug
Manche Tools sind beinahe zu schön, um wahr zu sein. In diese Kategorie fällt
QueryExpress von Joseph Albahari. Zu mindestens für alle Leserinnen und
Leser, die nur über die MSDE verfügen und nun ein Werkzeug brauchen, mit
dem sie die Struktur einer SQL-Server-Datenbank sichtbar machen und SQLKommandos gegen eine Datenbank ausführen können. QueryExpress, bei
dem es sich ebenfalls um eine .NET-Anwendung handelt, erledigt beide Aufgaben souverän und ist zudem kostenlos erhältlich. Download und Info unter
http://www.albahari.com/queryexpress.html.
Die Bedienung von QueryExpress ist sehr einfach (und an das Vorbild Query
Analyzer des SQL Server angelehnt). Als Erstes stellen Sie die Verbindung zu
einer Datenbank her. Anschließend wird ein SQL-Fenster geöffnet, in dessen
linker Hälfte eine Datenbank ausgewählt wird und daraufhin die Tabellen und
Felder dieser Datenbank in einer typischen Baumstruktur erscheinen. Die
rechte Fensterhälfte ist für die Eingabe beliebiger SQL-Kommandos gegen die
ausgewählte Datenbank gedacht. Ein Kommando wird über Í ausgeführt,
wobei das Ergebnis in einem Grid (alternativ als Text) in der unteren Hälfte angezeigt wird, zusammen mit der Ausführungszeit in Sekunden. Sie können beliebig viele SQL-Fenster öffnen und den Inhalt eines Fensters als Textdatei mit
106
SQL trainieren
der Erweiterung .sql speichern, um es zu einem späteren Zeitpunkt wieder laden zu können.
Abb. 3.2:
Beim QueryExpress ist am
Anfang eine
Anmeldung
erforderlich.
3.3.2
Wenn alle Stricke reißen – Osql.exe hilft immer
Sowohl eine reguläre SQL-Server-Installation als auch die MSDE installieren
ein kleines Kommandozeilentool mit dem Namen Osql.exe (bzw. Isql.exe bei
einem SQL Server), das im Prinzip eine große Hilfe sein kann, wenn man damit leben kann, dass es keine Benutzeroberfläche, sondern nur eine spartanische Kommandozeile gibt. Die Hauptaufgabe von Osql ist es, über SQLSkripte Datenbanken komplett anzulegen oder Elemente zu vorhandenen
Datenbanken hinzuzufügen. Aber auch Abfragen können damit ausgeführt
werden, da ein SQL-Skript beliebige T-SQL-Kommandos enthalten kann.
Und hat man sich an die schlichte Kommandozeile erst einmal gewöhnt, geht
manches für erfahrene Anwender schneller von der Hand als mit Query Analyzer & Co.
Das folgende SQL-Skript, das in einer Datei Test.sql enthalten ist, soll mit
Hilfe von Osql.exe ausgeführt wird:
USE Northwind;
SELECT LastName, City FROM Employees;
=
Beim Aufruf von Osql werden Anmeldung und das Ausführen des SQLSkripts in einem Aufwasch erledigt:
osql -S "(local)" -E -i test.sql
107
3 Schnellkurs SQL
jetzt lerne ich
Achten Sie bei den Schaltern auf die Groß-/Kleinschreibung, -e ist nicht das
Gleiche wie –E. Eine Liste der wichtigsten Schalter enthält Tabelle 3.2. In der
Regel führen SQL-Skripte keine Abfragen durch, sondern sind dazu da, komplette Datenbanken anzulegen. Die SQL-Server-Version der Northwind-Datenbank erhalten Sie auf der Microsoft-Webseite lediglich in Gestalt einer kleinen SQL-Skriptdatei. Wenn Sie diese Datei mit Osql.exe ausführen, wird die
komplette Datenbank auf dem ausgewählten Server angelegt.
Rufen Sie Osql ohne weitere Schalter außer denen, die für die Anmeldung erforderlich sind, auf, gelangen Sie in den Editormodus. Hier können Sie ein
SQL-Skript Zeile für Zeile zusammensetzen und es am Ende mit einem GO
ausführen. Möchten Sie ein SQL-Kommando ausführen, aber mit Osql weiterarbeiten, um eventuell weitere SQL-Kommandos auszuführen, geben Sie
einfach GO ein. Ein EXIT oder QUIT beendet den Editor wieder. Ein RESET
macht alle bisher eingegebenen Zeilen ungültig, und wenn Sie den Editor
scheinbar gar nicht mehr verlassen können, drücken Sie Ÿ+C.
Tabelle 3.2:
Schalter
Die wichtigsten
Schalter von -S
Osql.exe -d
108
Bedeutung
Gibt den Servernamen an.
Gibt den Datenbanknamen an (entspricht dem USE-Kommando).
-L
Listet alle registrierten Server auf.
-i
Auf diesen Schalter folgt der Name der SQL-Skriptdatei.
-?
Listet die Schalter auf.
-U
Benutzername für Login.
-H
Hostname für Login.
-l
Legt Login-Timeout fest.
-c
Ende des Kommandos.
-Q
Abfrage ausführen und wieder beenden.
-o
Auf diesen Schalter folgt der Name einer Datei, in welche die Ausgabe eingetragen wird.
-P
Kennwort für Login.
-E
Verbindung wird ohne Login mit integrierter Windows-Sicherheit
durchgeführt.
-w
Legt die Breite einer Spalte fest.
-q
Führt das folgende SQL-Kommando aus, das in Anführungsstriche
gesetzt wird. Mehrere Kommandos werden durch ein Semikolon
getrennt.
Abfragen über SELECT
3.4
jetzt lerne ich
Abfragen über SELECT
Das SELECT-Kommando ist das mit Abstand wichtigste SQL-Kommando. Es
gibt einen oder mehrere Datensätze aus einer oder mehreren Tabellen zurück,
wobei über die WHERE-Klausel eines oder mehrere Filterkriterien angegeben
werden können.1
Das folgende Kommando gibt alle Datensätze der Tabelle Employees zurück:
SELECT * From Employees
=
Ein SELECT-Kommando wird entweder über die ExecuteReader-Methode des
OleDbCommand-Objekts (bzw. SqlCommand) oder über ein OleDbDataAdapter-Objekt (bzw. SqlDataAdapter) ausgeführt. Möchte man die Anzahl der Datensätze erfahren, geschieht dies am einfachsten über die Count-Eigenschaft der
Rows-Auflistung des DataTable-Objekts. Bei einem DataReader muss erst die
komplette Datensatzgruppe in einer Schleife durchlaufen werden. Hier ist es
oft einfacher, zuerst die SQL-Funktion COUNT mit der ExecuteScalar-Methode
auszuführen – mehr dazu in Kapitel 3.9.
Beim Microsoft SQL Server können mehrere SELECT-Kommandos zusammengefasst (Batch-Ausführung) und die Ergebnissets einem SqlDataReader
zugewiesen werden. Über die NextResult-Methode wird auf das nächste Ergebnisset umgeschaltet, ohne dass erneut eine Datenbankabfrage durchgeführt wird.
3.5
0
Datensätze einfügen mit INSERT
Das INSERT INTO-Kommando fügt einen oder mehrere Datensätze in eine Tabelle ein. Dabei kommt es darauf an, dass Einschränkungen (in der Regel Primärschlüsseleinschränkungen) nicht verletzt werden. Mit anderen Worten, es
kann zum Beispiel kein Datensatz eingefügt werden, dessen Wert für ein Primärschlüsselfeld dazu führen würde, dass der Wert doppelt vorkommt (Primärschlüssel müssen stets eindeutig sein).
1. Wie im richtigen Leben dient auch bei SQL eine Klausel dazu, eine getroffene Absprache einzuschränken oder genauer zu definieren.
109
3 Schnellkurs SQL
jetzt lerne ich
=
Das folgende Kommando fügt einen neuen Datensatz in die Tabelle Employees ein.
INSERT INTO Employees (LastName, FirstName, Hiredate) VALUES
('Monadjemi', 'Peter','1.4.2004'
Das Feld EmployeeID wird nicht aufgeführt, da es ein AutoIncrement-Feld
(beim SQL Server auch Identitätsfeld genannt) ist, das von der Datenbank einen fortlaufenden Wert erhält.
1
0
Beim Microsoft SQL Server kann ein Identitätsfeld über die T-SQL-Variable
@@Identity angesprochen werden.
Soll eine Einfügeoperation in einer SQL Sever-Datenbank den aktuellen
Wert der Identitätsspalte, die in der Regel den Primärschlüssel der Tabelle
darstellt, zurückgeben, geschieht dies am einfachsten über eine gespeicherte
Prozedur, die den @@Identity-Wert als Parameter zurückgibt.
3.6
Datensätze aktualisieren mit
UPDATE
Das UPDATE-Kommando aktualisiert einen oder mehrere Felder in einen oder
mehrere Datensätze in einer Tabelle (es kann pro Kommando immer nur eine
Tabelle aktualisiert werden). Der Wert wird einem Feld über das SET-Schlüsselwort zugewiesen, wobei mehrere Felder durch Kommata getrennt werden.
Welche Datensätze aktualisiert werden, wird über die WHERE-Klausel festgelegt.
=
Das folgende SQL-Kommando senkt die Preise aller Produkte der Tabelle
Products, die mit Discontinued=1 als Auslaufprodukte gekennzeichnet sind,
um 10%.
UPDATE Products SET UnitPrice = UnitPrice * 0.9 WHERE Discontinued=1
Wird dieses Kommando mit ExecuteNonQuery ausgeführt, erhält man von der
Methode die Anzahl der geänderten Datensätze zurück.
Sollen mehrere Felder pro Datensatz aktualisiert werden, werden diese im
UPDATE-Kommando durch Kommata getrennt zusammengefasst:
UPDATE Products SET UnitPrice = UnitPrice * 0.9, ReorderLevel = 0
WHERE Discontinued=1
110
Datensätze löschen mit DELETE
3.7
jetzt lerne ich
Datensätze löschen mit DELETE
Das DELETE-Kommando löscht einen oder mehrere Datensätze aus einer Tabelle. Sollen nicht alle Datensätze gelöscht werden, muss über die WHERE-Klausel ein Kriterium angegeben werden.
Das folgende SQL-Kommando löscht aus der Tabelle Employees alle Datensätze mit einer EmployeeID größer 9:
DELETE FROM Employees WHERE EmployeeID>9
=
Wird dieses Kommando mit ExecuteNonQuery ausgeführt, erhält man von der
Methode die Anzahl der gelöschten Datensätze zurück.
Speziell beim Microsoft SQL Server als auch beim Oracle SQL Server gilt,
dass umfangreichere Einfüge-, Lösch- oder Aktualisierungsaktionen aus Performancegründen besser über gespeicherte Prozeduren ausgeführt werden.
Mehr dazu in Kapitel 6.
3.8
0
Abfragen über mehrere Tabellen –
die Joins
Bei einer JOIN-Operation werden die Datensätze aus zwei oder mehr Tabellen
verknüpft, also zu einer virtuellen Tabelle zusammengefasst. In der Regel wird
dabei ein Kriterium bestehend aus Feldern, welche die zu verknüpfenden
Tabellen gemeinsam haben, verwendet, damit nur bestimmte Felder in die
Ergebnismenge übernommen werden. Das klassische Beispiel für eine JOINOperation liegt vor, wenn alle Datensätze in einer Master-Details-Beziehung
zusammengefasst werden sollen. Eine solche Beziehung liegt in der Beispieldatenbank Northwind zwischen den Tabellen Orders (Master) und Order
Details (Details) oder Customers (Master) und Orders (Details) vor. Warum?
Nun, weil zu jedem Auftrag eine bestimmte Anzahl an Bestelldetails und zu jedem Kunden eine bestimmte Anzahl an Aufträgen gehören. Man spricht auch
von einer 1:n-Beziehung.
Möchte man feststellen, welche Bestellungen für ein Produkt vorliegen, geht
dies am einfachsten über eine Join-Operation:
SELECT Products.ProductID, ProductName, OrderID FROM Products,
[Order Details] WHERE Products.ProductID = [Order Details].ProductID
ORDER BY Products.ProductID
=
111
3 Schnellkurs SQL
jetzt lerne ich
In diesem Fall wird eine vereinfachte SQL-Syntax verwendet, das heißt, auf
das offizielle JOIN-Befehlswort wird verzichtet, zumal dieses beim Oracle
SQL Server nicht unterstützt wird. Voll ausgeschrieben lautet das obige
Kommando wie folgt:
SELECT Products.ProductID, ProductName, OrderID FROM Products INNER
JOIN [Order Details] ON Products.ProductID = [Order
Details].ProductID ORDER BY Products.ProductID
Hier liegt ein sog. Inner Join vor, bei dem jedem Datensatz der Master-Tabelle eine bestimmte Anzahl an Datensätzen der Details-Tabelle zugeordnet
wird. Pro vorhandener Beziehung, die über das gemeinsame Feld ProductID
hergestellt wird (das in beiden Tabellen durchaus unterschiedliche Namen
tragen kann), wird ein neuer Datensatz in einer virtuellen Tabelle angelegt,
der alle Felder aus beiden Datensätzen enthält.
1
0
Kommen in beiden Tabellen Felder mit gleichen Namen vor, muss dem Feldnamen der Tabellenname vorangestellt werden. Aus ProductID wird so Products.ProductID.
Kommen in einem SQL-Kommando relativ viele Felder vor, denen der Tabellenname vorangestellt werden muss, kann es eine kleine Abkürzung sein,
über AS einen Aliasnamen für die Tabelle zu verwenden. Das folgende SQLKommando funktioniert nur beim Microsoft SQL Server (T-SQL):
SELECT P.ProductID, ProductName, OrderID FROM Products AS P INNER
JOIN [Order Details] ON P.ProductID = [Order Details].ProductID
ORDER BY P.ProductID
1
ADO.NET erlaubt keine Aktualisierungen bei DataTables, die aus mehreren
Tabellen entstanden sind. Dies ist eine Einschränkung von Join-Operationen, welche die Programmierung deutlich aufwändiger macht, als sie sein
könnte.
3.9
SQL-Funktionen
SQL stellt eine Reihe von Funktionen zur Verfügung, die, da sie die Felder in
mehreren Datensätze zusammenfassen, als Aggregatfunktionen bezeichnet
werden. Stellvertretend werden im Folgenden die häufig benutzten Aggregatfunktionen COUNT, MAX und AVG vorgestellt. Tabelle 3.3 stellt die wichtigsten
SQL-Funktionen zusammen.
112
SQL für etwas Fortgeschrittene: Gruppierungen und Unterabfragen
jetzt lerne ich
SQL-Aggregatfunktionen werden über die ExecuteScalar-Methode des Command-Objekts ausgeführt.
Funktion
Bedeutung
AVG
Berechnet den Durchschnitt über alle Werte einer Spalte.
COUNT
Zählt die Anzahl an Datensätzen.
LEFT
Gibt die ersten n Zeichen vom Anfang einer Zeichenkette zurück.
LEN
Gibt die Länge einer Zeichenkette zurück.
MAX
Gibt den größten Wert einer Spalte zurück.
MIN
Gibt den kleinsten Wert einer Spalte zurück.
POWER
Potenziert einen Ausdruck um den angegebenen Faktor.
RIGHT
Gibt die ersten n Zeichen vom Ende einer Zeichenkette zurück.
STDEV
Berechnet die Standardabweichung der Werte einer Spalte.
VAR
Berechnet die Variante der Werte einer Spalte.
Die COUNT-Funktion zählt einfach nur die Anzahl an Datensätzen, die ein bestimmtes Kriterium erfüllen.
SELECT COUNT(*) FROM Products WHERE Discontinued=1
Tabelle 3.3:
Wichtige SQLFunktionen
beim Microsoft
SQL Server
2000
=
Die MAX-Funktion gibt den größten Wert in einer Spalte von nummerischen
Werten zurück:
SELECT Max(EmployeeID) FROM Employees
Die AVG-Funktion berechnet den Durchschnitt in einer Spalte von nummerischen Werten. Die folgende Abfrage gibt den Durchschnittspreis aller an einem bestimmten Datum verkauften Artikel zurück:
SELECT AVG(UnitPrice) FROM Orders, [Order Details] WHERE
Orders.OrderID=[Order Details].OrderID AND OrderDate='9.9.1996'
3.10
SQL für etwas Fortgeschrittene:
Gruppierungen und Unterabfragen
Bislang war SQL relativ einfach, auch wenn bereits etwas Übung und Erfahrung dazu gehört, ein UPDATE-Kommando aus dem Kopf formulieren zu können (wie Sie in Kapitel 4 lernen werden, ist es sehr viel praktischer, für alle variablen Werte Platzhalter zu übergeben, anstatt den SQL-String einzeln
zusammenzubauen). SQL kann jedoch noch sehr viel mehr, was im Folgenden mit den Gruppierungen und Unterabfragen nur angedeutet werden.
113
jetzt lerne ich
3 Schnellkurs SQL
3.10.1
Gruppierungen mit der Group By-Klausel
Ein wichtiger Aspekt bei SQL sind Gruppierungen über die GROUP BY-Klausel
und gegebenenfalls das HAVING-Prädikat.
=
Die folgende Abfrage gibt die Anzahl der verkauften Produkte pro Kategorie
zurück:
SELECT COUNT(*) AS Anzahl, CategoryName FROM Categories, Products,
[Order Details] WHERE Products.ProductID=[Order Details].ProductID
AND Categories.CategoryID = Products.CategoryID GROUP BY
CategoryName
Dass diese Abfrage etwas umfangreicher ist, hat nur indirekt etwas mit der
GROUP BY-Klausel zu tun, sondern mit dem Umstand, dass Gruppierungen
nur dann einen echten Vorteil bringen, wenn sie im Rahmen einer etwas
umfangreicheren Abfrage eingesetzt werden. Gruppierungen können auch
sehr einfach sein, wie das folgende Beispiel belegt, das die Produkte nach
Kategorien gruppiert und die Anzahl der Produkte pro Kategorie zurückgibt:
SELECT Count(*) AS Anzahl, CategoryID FROM Products GROUP BY
CategoryID
Abb. 3.3:
QueryExpress
zeigt das Resultat der GROUP
BY-Abfrage an.
114
SQL für etwas Fortgeschrittene: Gruppierungen und Unterabfragen
1
Die folgende Abfrage gibt die Anzahl aller Produkte mit ihrer ProductID zurück, die mit einem Rabatt verkauft wurden:
SELECT Count(ProductID) AS Anzahl, ProductID FROM [Order Details]
Where Discount > 0 GROUP BY ProductID ORDER BY ProductID
jetzt lerne ich
=
Der nächste Schritt könnte darin bestehen herauszufinden, wie viel »Verlust«
das Geschäft mit der Rabattierung gemacht hat. Auch das ist per SQL relativ
einfach möglich:
SELECT SUM(UnitPrice*Quantity) - SUM((UnitPrice*1Discount)*Quantity) AS RabattDiff FROM [Order Details] WHERE
Discount > 0
Diese Abfrage gibt am Ende einen Wert zurück (bei ADO.NET würde sie daher über die ExecuteScalar-Methode eines Command-Objekts ausgeführt
werden), der für die Differenz der Summen der verkauften Produkte und der
verkauften Produkte inklusive Rabatt steht.
Die folgende Abfrage gibt an, wie oft die einzelnen Produkte rabattiert verkauft wurden:
SELECT COUNT(ProductName) AS Anzahl, ProductName FROM Products,
[Order Details] WHERE [Order Details].Discount>0 AND
Products.ProductID = [Order Details].ProductID GROUP BY ProductName
ORDER BY Anzahl DESC
Und bei welchem Produkt hat die Firma den meisten Verlust bezogen auf die
Rabattierung gemacht? Bevor es richtig kompliziert wird, verrät Ihnen der
Autor einen kleinen »Trick«, der SQL-Programmierern oft aus der Patsche
hilft: das TOP-Prädikat, das stets die obersten n Datensätze zurückgibt. Indem
die Abfrage also nach der Differenz zwischen Verkaufspreis und Rabattpreis
absteigend sortiert und nur den ersten Datensatz zurückgibt, erhalten Sie
den Datensatz mit dem größten Verlust:
SELECT TOP 1 SUM(UnitPrice*Quantity) AS Betrag, SUM ((UnitPrice*1Discount)*Quantity) AS Rabatt, SUM(UnitPrice*Quantity) – SUM
(UnitPrice*1-Discount*Quantity) AS RabattDiff, ProductID FROM [Order
Details] WHERE Discount > 0 GROUP BY ProductID Order BY RabattDiff
DESC
Das Beispiel zeigt sehr schön, wie ein cleveres SQL-Kommando die Programmierung vereinfachen kann. Natürlich gibt es aber auch Situationen, an
denen selbst SQL an seine Grenzen stößt. Entweder weil das SQL-Kommando so kompliziert werden würde, dass es »kein Mensch mehr versteht«1, oder
die Abfrage gar nicht möglich ist. Hier kommen die gespeicherten Prozeduren oder Funktionen ins Spiel (Kapitel 6), mit denen sich mehrere SQLKommandos zusammenfassen.
1. Bekanntlich verbringen Entwickler in der Industrie 47% ihrer Zeit damit, sich in den Programmcode einzuarbeiten, den andere »verbrochen« haben.
115
jetzt lerne ich
3 Schnellkurs SQL
Das Ergebnis der ersten Abfrage als Variable kann in einer folgenden Abfrage enthalten sein oder doch wieder die gute, alte Visual Basic-Programmierung.
Abb. 3.4:
Alles andere
als trivial – diese Abfrage gibt
das Produkt zurück, für das es
den größten
Rabattbetrag
gibt.
Eine (lästige) Einschränkung und eine echte Hürde auf dem Weg zum SQLExperten ist der Umstand, dass auf SELECT neben einer Aggregatfunktion nur
Felder folgen dürfen, die über GROUP BY aufgeführt werden. Möchte man daher in dem obigen Beispiel auch die Kategorienamen erhalten, muss eine Unterabfrage zum Einsatz kommen.
3.11
Unterabfragen
SQL-Abfragen können verschachtelt werden, das heißt auf die WHERE-Klausel
können weitere Abfragen folgen, deren Ergebnis zum Beispiel als Einschränkungskriterium verwendet wird. Diese Unterabfragen (engl. »Subqueries«) gehören bereits zu den etwas anspruchsvolleren Themen bei SQL. Sie werden
zwar nur relativ selten benötigt, doch wer sie beherrscht, kann sich viel Programmierarbeit sparen. Bezüglich ADO.NET gibt es keine Besonderheiten zu
beachten, da sie exakt wie eine einfache SELECT-Abfrage ausgeführt werden.
=
116
Das folgende Beispiel gibt alle Produkte aus, deren Preis größer als der
Durchschnittspreis aller Produkte ist:
SELECT ProductName, UnitPrice FROM Products WHERE UnitPrice >
(SELECT AVG(UnitPrice) FROM Products) ORDER BY UnitPrice
Datenbanken und Tabellen anlegen
jetzt lerne ich
Das folgende Beispiel gibt zusätzlich auch die Anzahl an Bestellungen dieser
Produkte zurück:
SELECT COUNT(OrderID), OrderID FROM Products, [Order Details] WHERE
Products.UnitPrice > (SELECT AVG(UnitPrice) FROM Products) AND
Products.ProductID = [Order Details].ProductID GROUP BY OrderID
ORDER BY OrderID DESC
Häufig lässt sich eine kompliziert wirkende Unterabfrage durch eine deutlich
einfachere Join-Verknüpfung ersetzen.
Unterabfragen in eine Abfrage einbauen
Eine komplette Unterabfrage kann als Feldname in eine SELECT-Abfrage eingebaut werden, so dass das Ergebnis der Unterabfrage in die von der Abfrage
zurückgegebenen Felder aufgenommen wird.
Das folgende Beispiel gibt die Namen aller Kunden mit der Anzahl ihrer Bestellungen sortiert nach dieser Anzahl zurück.
SELECT CompanyName, CustomerID, (SELECT Count(*) FROM Orders WHERE
Orders.CustomerID=Customers.CustomerID) AS [Anzahl Aufträge] FROM
Customers ORDER BY [Anzahl Aufträge]
=
Spätestens an dieser Stelle wird deutlich, dass sich mit SQL einiges anstellen
lässt und profunde SQL-Kenntnisse beinahe genauso wichtig sind wie gute
Programmierkenntnisse. Trotz aller Veränderungen in den letzten Jahren und
Jahrzehnten hat SQL nichts an Bedeutung verloren. Im Gegenteil, mit
ADO.NET rückt die (offiziell 1986 standardisierte) Datenbankabfrage erneut
in den Mittelpunkt.
3.12
Datenbanken und Tabellen anlegen
SQL kann auch das Anlegen von Datenbanken, Tabellen und anderen Inhalten, wie gespeicherte Prozeduren, übernehmen. Auch wenn dafür meistens
ein komfortables Programm wie Microsoft Access (ab Version 2000) oder der
Enterprise Manager des SQL Servers besser geeignet ist, wenn es sein muss,
geht es auch programmgesteuert, indem die SQL-Kommandos über ein SqlCommand-Objekt und dessen ExecuteNonQuery-Methode der Reihe nach ausgeführt werden. Es gibt sogar einen wichtigen Vorteil. Dieser besteht darin, dass
das Anlegen jederzeit auf Knopfdruck wiederholt werden kann. Muss ein Programm die benötigte Datenbank erst anlegen, ist dies, neben einem SQLSkript, sogar die einzige mögliche Variante.
117
jetzt lerne ich
3 Schnellkurs SQL
3.12.1
Das CREATE-Kommando
Das universelle CREATE-Kommando ist für praktisch alles zuständig, was innerhalb einer SQL-Server-Datenbank angelegt werden kann: Tabellen, Indices,
Einschränkungen, Trigger, gespeicherte Prozeduren und sogar Datenbanken.
=
Das folgende Kommando legt eine neue Datenbank für den lokalen SQL
Server an.
CREATE DATABASE TestDB
Auch wenn dieses Kommando im Datenbankalltag mit zusätzlichen Parametern, etwa einer Mindestgröße für die Datenbank, aufgerufen wird, reicht
diese Variante vollkommen aus.
Die soeben frisch angelegte Datenbank besitzt noch keine Tabellen. Das kann
ebenfalls das CREATE-Kommando erledigen, nur dass es anstelle von CREATE
DATABASE nun CREATE TABLE heißen muss und zusätzlich zum Tabellennamen
auch alle Felder der Tabelle sowie gegebenenfalls auch Einschränkungen aufgeführt werden.
=
Das folgende Beispiel fügt zur aktuellen Datenbank eine Tabelle mit dem Namen »Autoren« hinzu, die über die Felder AutorID und AutorName verfügt und
bei der das Feld AutorID mit einem Primärschlüssel versehen wird. Außerdem darf AutorID keine Nullwerte erhalten, das Feld AutorName dagegen
schon.
CREATE TABLE Autoren (AutorID int NOT NULL CONSTRAINT pkAuID PRIMARY
KEY, AutorName varchar(64) NULL )
Abb. 3.5:
Auch das Anlegen von Tabellen ist in Query
Express problemlos
möglich.
118
Datenbanken und Tabellen anlegen
Auch diese »Sorte« von SQL-Kommandos können Sie mit dem Query Analyzer aus einer SQL Server 2000-Installation oder QueryExpress (siehe Kapitel 3.3.1) ausführen.
3.12.2
jetzt lerne ich
1
Die Kommandos ALTER und DROP
Für Datenbanken und deren Elemente, die bereits existieren und nun geändert werden sollen, gibt es das ALTER-Kommando, das einfach anstelle von
CREATE eingesetzt wird.
Das folgende SQL-Kommando ändert den Namen einer vorhandenen Datenbank:
ALTER DATABASE TESTDB MODIFY NAME = TESTDBNEU
=
Regelrecht brisant ist das DROP-Kommando, denn es entfernt ein Datenbankelement oder die Datenbank selber ohne viel Aufhebens.
Das folgende SQL-Kommando löscht die Datenbank TestDBNeu.
DROP DATABASE TestDBNeu
Das war’s – weg ist die Datenbank samt ihrem Inhalt. Führen Sie daher dieses Kommando nie einfach nur zum Spaß aus oder weil Sie neugierig sind,
ob wirklich kein Warnhinweis erscheint (es erscheint keiner). Natürlich müssen Sie beim SQL Server mit einem Benutzerkonto angemeldet sein, das die
erforderlichen Berechtigungen besitzt, und das obige Kommando kann nur
ausgeführt werden, wenn eine andere Datenbank als die zu löschende Datenbank die aktive Datenbank ist. Aber es zeigt sehr eindrucksvoll, wie
mächtig SQL beim SQL Server ist.
3.12.3
=
Die Datentypen des SQL Servers
Der SQL Server arbeitet mit einem eigenen und sehr umfangreichen Satz an
Datentypen, die in Tabelle 3.4 aufgeführt sind. Die Datentypen sind (natürlich) nicht mit jenen von Visual Basic.NET identisch, wenngleich es gewisse
Übereinstimmungen gibt. Die rechte Spalte enthält daher meistens einen Datentypen in Visual Basic.NET, der »in etwa« passen könnte. Ein Strich bedeutet, dass es ein vergleichbares Pendant gibt.
119
3 Schnellkurs SQL
jetzt lerne ich
0
Die SQL-Server-Datentypen werden in der .NET-Klassenbibliothek über die
Enumeration SqlDbType im Namespace System.Data.SqlTypes zur Verfügung gestellt. Das ist sehr praktisch, wenn Sie beim Aufruf einer gespeicherten Prozedur (siehe Kapitel 6) den richtigen Parameter auswählen möchten.
Parallel gibt es die Enumeration SqlTypes im gleichen Namespace. Sie enthält die Namen der SQL-Server-Datentypen, dieses Mal aber angepasst an
die zur Auswahl stehenden Datentypen im .NET Framework. Anstelle von
Binary heißt es SqlBinary, anstelle von Float heißt es SqlDouble. Mit anderen Worten, diese Auflistung nimmt bereits die Zuordnung zwischen SQLServer- und .NET-Datentyp vor und erleichtert die Auswahl des richtigen
Typs.
1
Tabelle 3.4:
Die Datentypen des SQL
Servers und
ihre Pendants
(sofern vorhanden) bei Visual
Basic.NET in
der Übersicht
120
Mit SQL Server 2005 wird es eine sehr viel engere Übereinstimmung zwischen den Datentypen des SQL Servers und denen, die bei .NET durch das
CTS (Common Type System) vorgegeben sind.
Datentyp
Bedeutung
CTS-Pendant bei SQL-Types
Visual Basic.NET
Bigint
Große 64-Bit-Ganzzahl im
Bereich –2^63 bis 2^63 –1.
Long
SqlInt64
Int
32-Bit-Ganzzahl im Bereich
–2^32 bis 2^32 –1.
Integer
SqlInt32
Smallint
16-Bit-Ganzzahl im Bereich
–32.678 bis +32.767
Short
SqlInt16
Tinyint
Kleine 8-Bit-Ganzzahl im
Bereich 0 bis 255.
Byte
SqlByte
Bit
Ganzzahl, die nur die Werte 0
und 1 annehmen kann.
Byte bzw. Boolean
-
Decimal
Feste Nachkommazahl im
Bereich –10^38 bis
+10^38 –1.
Decimal
SqlDecimal
Numeric
Entspricht decimal.
-
SqlDecimal
Money
- (Decimal)
Feste Nachkommazahl im
Bereich –2^63 bis +2^63–1,
die aufgrund einer festen Genauigkeit von fünf Nachkommastellen speziell für Geldbeträge
geeignet ist.
SqlMoney
Datenbanken und Tabellen anlegen
Datentyp
Bedeutung
CTS-Pendant bei SQL-Types
Visual Basic.NET
Smallmoney
Wie money, nur dass der
Wertebereich zwischen
–214,748.3648 und
+214,748.3647 liegt.
- (Decimal)
SqlMoney
Float
Doppelt genaue Fließkommazahl mit bis zu 15 Nachkommastellen.
Double
SqlDouble
Real
Einfach genaue Fließkommazahl mit bis zu sieben Nachkommastellen.
Single
SqlSingle
DateTime
Datumstyp
Date
SqlDateTime
- (Date)
SqlDateTime
Smalldatetime Datumstyp mit einem deutlich
jetzt lerne ich
Tabelle 3.4:
Die Datentypen des SQL
Servers und
ihre Pendants
(sofern vorhanden) bei Visual
Basic.NET in
der Übersicht
(Forts.)
kleineren Datumsbereich als
Wertebereich und einer Genauigkeit von nur einer Minute.
Char
ANSI-Zeichenkette fester Länge, - (String)
die bis zu 8.000 Zeichen umfassen kann.
SqlString
Varchar
- (String)
ANSI-Zeichenkette variabler
Länge, die bis zu 8.000 Zeichen
umfassen kann.
SqlString
Text
ANSI-Zeichenkette variabler
Länge, die bis zu 2 Milliarden
Zeichen umfassen kann.
SqlString
Nchar
- (String)
Unicode-Zeichenkette fester
Länge, die bis zu 4.000 Zeichen
umfassen kann
SqlString
Nvarchar
Unicode-Zeichenkette variabler - (String)
Länge, die bis zu 4.000 Zeichen
umfassen kann.
SqlString
Ntext
Unicode-Zeichenkette variabler
Länge, die bis zu 1 Milliarden
Zeichen umfassen kann.
SqlString
Binary
Binäres Feld fester Länge, das
bis zu 8.000 Bytes groß werden
kann.
SqlBinary
Varbinary
Binäres Feld variabler Länge,
das bis zu 8.000 Bytes groß
werden kann.
-
SqlBinary
Image
Binäres Feld variabler Länge,
das bis zu 2 Milliarden Bytes
groß werden kann.
-
SqlBinary
String
String
121
jetzt lerne ich
3 Schnellkurs SQL
3.12.4
Die Rolle der Einschränkungen
Jede Tabelle kann mit einer oder mehreren Einschränkungen (engl. »Constraints«) versehen werden, die sich auf einzelne Felder der Tabelle beziehen.
Einschränkungen sollen die Integrität einer Datenbank sicherstellen und sind
die Grundlagen für Beziehungen zwischen zwei Tabellen, die in der Datenbank gespeichert werden und zum Beispiel dafür sorgen, dass, wenn ein Datensatz aus einer »Elterntabelle« mit einem Primärschlüssel gelöscht wird, automatisch (ohne, dass dafür ein so genannter Trigger für die Tabelle definiert
werden muss) alle Datensätze aus einer dazu in Beziehung stehenden »Kindtabelle« gelöscht werden, die den Wert des Primärschlüsselfeldes in ihrem
Fremdschlüsselfeld enthalten. Die bekannteste Einschränkung ist die Primärschlüsseleinschränkung, die einem Feld auferlegt, dass es bezogen auf die
Spalte nur eindeutige Werte besitzen darf. Beim SQL Server 2000 werden
folgende Einschränkungen unterschieden:
쐽 Primary Key
쐽 Unique
쐽 Foreign Key
쐽 Check
쐽 Not Null
Die Primary Key-Einschränkung bewirkt, dass das Feld (oder die Felder) einen
eindeutigen Wert innerhalb der Spalte besitzen müssen. Jede Tabelle sollte einen Primärschlüssel besitzen, wenngleich dies nicht obligatorisch ist. Über
den Primärschlüssel wird erreicht, dass jeder Datensatz innerhalb der Tabelle
unterscheidbar ist.
Die Unique-Einschränkung bewirkt ebenfalls, dass der Feldwert innerhalb der
Spalte eindeutig sein muss, nur dass das Feld nicht zum Primärschlüssel gehören muss.
Die Foreign Key-Einschränkung (Fremdschlüsseleinschränkung) verhindert
jede Aktion, die eine Verbindung zwischen zwei zueinander in einer Beziehung stehenden Tabellen zerstören würde. Ein Fremdschlüssel ist ein Feld in
einer Tabelle, das den gleichen Wert besitzt wie ein anderes Feld in einer anderen Tabelle, das dort ein Primärschlüssel ist. Über die Foreign Key-Einschränkung wird die so genannte referentielle Integrität der Datenbank gewährleistet. Dieser kompliziert klingende Begriff hat eine recht einfache
Bedeutung, die in diesem Buch an verschiedenen Stellen erklärt wird. Hier
noch einmal die Kurzform: Würde aus der Northwind-Datenbank ein Datensatz aus der Tabelle Customers gelöscht werden, gäbe es in der Orders-Tabelle eine Reihe von Datensätzen dieses Kunden, zu denen nun kein passender Datensatz in der Customers-Tabelle mehr gehört. Die referentielle
Integrität in der Datenbank wäre damit zerstört, und manche Abfragen wür-
122
Datenbanken und Tabellen anlegen
jetzt lerne ich
den nicht mehr funktionieren. Damit dies nicht passiert, müssen beim Datenbankentwurf Fremdschlüsseleinschränkungen gesetzt werden.
Die Check-Einschränkung begrenzt den Wert, den eine Spalte annehmen
kann.
Die Not Null-Einschränkung stellt sicher, dass keine Spalte einen Null-Wert
besitzen kann.
Das folgende SQL-Kommando legt eine Tabelle mit dem Namen Buecher
an, in der für das Feld AutorID eine Fremdschlüsselbeziehung mit dem
gleichnamigen Feld in der Tabelle Autoren eingerichtet wird.
=
CREATE TABLE Buecher (BuchID int NOT NULL CONSTRAINT pkBuchID
PRIMARY KEY, AutorID int NOT NULL CONSTRAINT AUTOR_BUCH FOREIGN KEY
(AutorID) REFERENCES Autoren(AutorID), Titel varchar(128) NULL )
Weitere Beispiele für SQL-Kommandos finden Sie in Kapitel 6, in dem über
das CREATE-Kommando eine gespeicherte Prozedur in der Datenbank angelegt wird.
Ab SQL Server 2000 können auf das REFERENCES-Schlüsselwort in einer
Fremdschlüsseleinschränkung ein ON DELETE CASCADE und ein ON DELETE UPDATE folgen, mit der eine Lösch- und Aktualisierungsverfolgung bereits auf
der Ebene der Datenbank implementiert wird. Das erspart die Programmierung eines Triggers, der ansonsten immer dann aktiv werden müsste, wenn
ein Datensatz in einer Tabelle mit einem Primärschlüssel gelöscht oder aktualisiert wird.
3.12.5
1
Eine Referenz zu T-SQL
T-SQL ist ein umfassender SQL-Dialekt mit vielen Kommandos, Funktionen
und Spezialitäten. Hinzu kommen Hunderte von gespeicherten Prozeduren,
die in der Systemdatenbank einer SQL-Server-Installation enthalten sind und
die den Umfang von T-SQL enorm erweitern. Ist das denn irgendwo beschrieben, gibt es eine »Liste aller Befehle«? Die gibt es selbstverständlich.
Zum einen umfasst eine SQL-Server-Installation eine umfangreiche Hilfe
(auch »SQL Server Books Online« genannt), die sämtliche Kommandos,
Funktionen, Operatoren und gespeicherte Prozeduren mit Beispielen enthält.
Sie werden es sich schon denken können, bei der MSDE ist diese Hilfe leider
nicht dabei. Doch das ist kein Grund zu verzagen, denn die komplette Dokumentation zum SQL Server 2000 gibt es (allerdings nur auf Englisch) auch im
Internet unter:
http://msdn.microsoft.com/library/en-us/tsqlref/ts_tsqlcon_6lyk.asp
123
jetzt lerne ich
3 Schnellkurs SQL
Hier können Sie alles zu T-SQL nachschlagen. Sehr viel besser sind natürlich
die SQL Server Books Online, da Sie diese etwas schneller durchsuchen können.
0
Netterweise stellt Microsoft auch die aktuelle Version der SQL Server Books
Online für den SQL Server 2000 (als auch für den Vorgänger 7.0) zum
Download zur Verfügung. Die Adresse lautet:
http://www.microsoft.com/sql/techinfo/productdoc/2000/books.asp
Nach der Installation erhalten Sie eine Chm-Datei, die alle Texte enthält.
Abb. 3.6:
Sehr nett – die
SQL-ServerDokumentation sowohl für
die Version 7.0
als auch 2000
gibt es als
kostenlosen
Download bei
Microsoft.
3.13
Zusammenfassung
SQL-Kenntnisse sind für ADO.NET Pflicht. Das hat aus zwei Gründen seine
Vorteile: 1. SQL ist ein anerkannter und bekannter Standard, so dass viele
Programmierer bereits SQL sprechen, bevor sie sich mit ADO.NET beschäftigen. Außerdem lassen sich SQL-Kenntnisse auf alle anderen Datenbanksysteme übertragen. SQL ist wirklich universell. 2. SQL ist nicht umsonst so populär, da es für die Aufgaben, für die es einst geschaffen wurde, hervorragend
geeignet ist. ADO.NET verlässt sich vollständig auf SQL für das Abfragen und
Aktualisieren von Daten. Dies ist ein angenehmer Kontrast zum Vorgänger
ADO, wo viele Aktionen »im Verborgenen« durchgeführt wurden und die Programmierer entsprechend keinen großen Einfluss auf das hatten, was hinter
124
Fragen
jetzt lerne ich
den Kulissen geschah. Ein »Nachteil« ist, dass die Programmierung dadurch
etwas aufwändiger wird, denn der Programmierer muss sehr viel mehr in Eigenregie erledigen.
3.14
Fragen
Wie lautet das SQL-Kommando, das die Vor- und Nachnamen aller Angestell- Frage 1
ten der Employees-Tabelle zurückgibt, die in Seattle wohnen?
Wie lautet das SQL-Kommando, das die Vor- und Nachnamen aller Angestell- Frage 2
ten der Employees-Tabelle zurückgibt, die seit dem 1.1.1994 zur Firma gehören?
Wie heißt der Angestellte der Northwind Company mit der längsten Betriebs- Frage 3
zugehörigkeit? Können Sie die Anzahl an Tagen, die dieser (bezogen auf den
heutigen Tag) Mitglied der Firma ist, auch per SQL ausgeben?
Wie lautet das SQL-Kommando, das die Anzahl der Tage, die alle Angestell- Frage 4
ten bereits Mitarbeiter der Firma sind, zusammen mit dem Nachnamen der
Angestellten absteigend sortiert nach der Anzahl der Tage ausgibt?
Wie lautet das SQL-Kommando, das den gesamten Umsatz der Northwind Frage 5
Company ausgibt?
Wie lautet das SQL-Kommando, das den Nachnamen des Angestellten aus- Frage 6
gibt, der den meisten Umsatz gemacht hat?
Die Lösungen zu den Fragen finden Sie in Anhang C.
125
Herunterladen