19
Transact-SQL: Eine Einführung
Ein Überblick über Transact-SQL
Auf die Datenbank mit Transact-SQL zugreifen
Platzhalter-Operatoren von Transact-SQL
Berichte mit COMPUTE erstellen
Diagnosewerkzeuge von SQL Server - SET-Befehle
Ziele
Das heutige Material rundet die vorherigen Darstellungen ab, da Transact-SQL eine Ergänzung zum akzeptierten SQL-Standard ist. Die heutige Lektion zeigt ...
Ein Überblick über Transact-SQL
Tag 14 ist kurz auf statisches SQL eingegangen. Die Beispiele in Lektion 14 haben die Verwendung von eingebettetem SQL in Sprachen der dritten Generation wie C herausgestellt. Bei dieser Programmiermethode ändert sich der eingebettete SQL-Code nicht und ist demnach recht eingeschränkt. Mit dynamischem SQL kann man dagegen die gleichen Funktionen in einer prozeduralen Programmiersprache realisieren und innerhalb des SQL-Codes variable Kriterien erlauben.
Wir haben mehrfach darauf hingewiesen, daß die meisten Datenbankhersteller die Standard-SQL-Sprache um zahlreiche Erweiterungen bereichern. Transact-SQL ist das Datenbankprodukt von Sybase und Microsoft SQL Server. Das Pendant von Oracle heißt PL/SQL. Diese Sprachen realisieren in vollem Umfang die bisher im Buch dargestellte Funktionalität. Darüber hinaus enthält jedes Produkt verschiedene Erweiterungen zum ANSI SQL-Standard.
Erweiterungen zu ANSI-SQL
In dieser Lektion demonstrieren wir SQL-Erweiterungen für das Erstellen von Programmen anhand der Sprache Transact-SQL von Sybase und Microsoft SQL Server. Zu dieser Sprache gehören sowohl Konstrukte, die man in Sprachen der dritten Generation findet, als auch einige SQL-Server-spezifische Funktionen, die sich als nützliche Werkzeuge für den Datenbankprogrammierer herausstellen.
Wer verwendet Transact-SQL?
Jeder, der dieses Buch liest, kann mit Transact-SQL arbeiten - sowohl Programmierer, die gelegentlich mit relationalen Datenbanken zu tun haben und hin und wieder Abfragen schreiben, als auch Entwickler, die Anwendungen schreiben und Objekte wie Trigger und gespeicherte Prozeduren erstellen.
Benutzer von Sybase und Microsoft SQL Server, die alle Möglichkeiten bei der Programmierung relationaler Datenbanken ausschöpfen wollen, kommen an den Funktionen von Transact-SQL nicht vorbei. |
Die grundlegenden Komponenten von Transact-SQL
SQL-Erweiterungen überwinden als prozedurale Sprache die Beschränkungen von SQL. Beispielsweise lassen sich mit Transact-SQL die Transaktionen einer Datenbank unmittelbar steuern, und man kann prozedurale Datenbankprogramme schreiben, die den Programmierer von zeitaufwendigen Programmieraufgaben befreien.
Tag 19 behandelt die folgenden Schlüsselmerkmale von Transact-SQL:
Datentypen
Tag 9 ist unter anderem auf Datentypen eingegangen. Beim Erstellen von Tabellen in SQL muß man für jede Spalte einen bestimmten Datentyp angeben.
Datentypen sind in den jeweiligen Implementierungen von SQL unterschiedlich definiert, da jeder Datenbankserver die Daten auf andere Weise speichert. Beispielsweise existieren in Oracle andere Datentypen als in SQL Server von Sybase und Microsoft. |
SQL Server von Sybase und Microsoft unterstützt die folgenden Datentypen.
Zeichenstrings
Numerische Datentypen
Datumswerte
Datentypen für Währungen
Währungstypen fügt man mit Hilfe eines vorangestellten Dollarzeichens ein. Dazu ein Beispiel:
insert payment_tbl (KUNDEN_NR, ZAHL_DATUM, ZAHL_BETRAG)
values (012845, '01.05.1997', $2099.99)
Binäre Strings
bit: ein logischer Datentyp
Die im Datentyp bit gespeicherten Werte können entweder 1 oder 0 sein. Man verwendet diesen Datentyp beispielsweise, um eine Spalte mit einem Kennzeichen - einem sogenannten Flag - zu versehen. Eine 1 kann dann bedeuten, daß eine Bedingung wahr (TRUE) ist, während 0 für eine falsche (FALSE) Bedingung steht. Das folgende Beispiel zeigt mit einer Spalte des Datentyps bit einen Testzustand an.
create table test_flag
( ind_id int not null,
test_ergebnis int not null,
ergebnis_flag bit not null)
Die Spalte ergebnis_flag ist als bit-Spalte definiert, in der ein bestandener Test mit dem Wert TRUE (oder 1) und ein nichtbestandener Test mit dem Wert FALSE (oder 0) gespeichert wird. |
Achten Sie in den restlichen Beispielen dieses Tages auf die Datentypen, die in Tabellen und im Transact-SQL-Code zum Einsatz kommen.
Auf die Datenbank mit Transact-SQL zugreifen
Genug der Vorrede, kommen wir zu praktischen Beispielen. Bauen Sie zunächst die folgenden Tabellen in der Datenbank BASEBALL auf, damit Sie die Beispiele der heutigen Lektion nachvollziehen können.
Die Datenbank BASEBALL
Die Datenbank BASEBALL besteht aus drei Tabellen, in denen typische Angaben von Baseball-Spielen aufgezeichnet werden: die Tabelle BATTERS (Schlagmann), die Tabelle PITCHERS (Werfer) und die Tabelle TEAMS. Diese Datenbank begleitet uns durch alle weiteren Beispiele dieses Tages.
Die Tabelle BATTERS
NAME char(30)
TEAM int
AVERAGE float
HOMERUNS int
RBIS int
Die obige Tabelle kann man mit der folgenden Transact-SQL-Anweisung erstellen:
1> create database BASEBALL on default
2> go
1> use BASEBALL
2> go
1> create table BATTERS (
2> NAME char(30),
3> TEAM int,
4> AVERAGE float,
5> HOMERUNS int,
6> RBIS int)
7> go
Zeile 1 erstellt die Datenbank. Man gibt die Datenbank BASEBALL an und erzeugt dann darunter die Tabelle BATTERS. |
Geben Sie die Daten aus Tabelle 19.1 in die Tabelle BATTERS ein.
Tabelle 19.1: Daten für die Tabelle BATTERS
Name |
Team |
Average |
Homeruns |
RBIs |
Billy Brewster |
1 |
.275 |
14 |
46 |
John Jackson |
1 |
.293 |
2 |
29 |
Phil Hartman |
1 |
.221 |
13 |
21 |
Jim Gehardy |
2 |
.316 |
29 |
84 |
Tom Trawick |
2 |
.258 |
3 |
51 |
Eric Redstone |
2 |
.305 |
0 |
28 |
Die Tabelle PITCHERS
Die Tabelle PITCHERS läßt sich mit der folgenden Transact-SQL-Anweisung erstellen:
1> use BASEBALL
2> go
1> create table PITCHERS (
2> NAME char(30),
3> TEAM int,
4> WON int,
5> LOST int,
6> ERA float)
7> go
Geben Sie die Daten aus Tabelle 19.2 in die Tabelle PITCHERS ein.
Tabelle 19.2: Daten für die Tabelle PITCHERS
Name |
Team |
Won |
Lost |
Era |
Tom Madden |
1 |
7 |
5 |
3.46 |
Bill Witter |
1 |
8 |
2 |
2.75 |
Jeff Knox |
2 |
2 |
8 |
4.82 |
Hank Arnold |
2 |
13 |
1 |
1.93 |
Tim Smythe |
3 |
4 |
2 |
2.76 |
Die Tabelle TEAMS
Die Tabelle TEAMS läßt sich mit der folgenden Transact-SQL-Anweisung erstellen:
1> use BASEBALL
2> go
1> create table TEAMS (
2> TEAM_ID int,
3> CITY char(30),
4> NAME char(30),
5> WON int,
6> LOST int,
7> TOTAL_HOME_ATTENDANCE int,
8> AVG_HOME_ATTENDANCE int)
9> go
Geben Sie die Daten aus Tabelle 19.3 in die Tabelle TEAMS ein.
Tabelle 19.3: Daten für die Tabelle TEAMS
Team_ID |
City |
Name |
Won |
Lost |
Total_Home_-Attendance |
Avg_Home_-Attendance |
1 |
Portland |
Beavers |
72 |
63 |
1,226,843 |
19,473 |
2 |
Washington |
Representatives |
50 |
85 |
941,228 |
14,048 |
3 |
Tampa |
Sharks |
99 |
36 |
2,028,652 |
30,278 |
Lokale Variablen deklarieren
Jede Programmiersprache bietet irgendeine Methode für die Deklaration von lokalen (oder globalen) Variablen, in denen man Daten speichern kann. Transact-SQL bildet hier keine Ausnahme. Die Deklaration einer Variablen in Transact-SQL ist eine recht einfache Prozedur. Man verwendet folgende Syntax mit dem Schlüsselwort DECLARE:
declare @Variablenname Datentyp
Eine Zeichenstringvariable zur Speicherung von Spielernamen deklariert man mit der folgenden Anweisung:
1> declare @name char(30)
2> go
Beachten Sie das Symbol @ vor dem Namen der Variablen. Dieses Symbol ist erforderlich und wird vom Abfrageprozessor zur Identifikation von Variablen verwendet.
Globale Variablen deklarieren
Wenn Sie sich weiter in die Dokumentation von Transact-SQL vertiefen, stoßen Sie auf das Symbol @@. SQL Server kennzeichnet damit globale Systemvariablen.
Die Deklaration eigener globaler Variablen ist vor allem nützlich, wenn man mit gespeicherten Prozeduren arbeitet. SQL Server verwaltet auch mehrere globale Systemvariablen, auf die der Benutzer des Datenbanksystems zurückgreifen kann. Tabelle 19.4 zeigt eine Liste dieser Variablen.
Tabelle 19.4: Globale Variablen von SQL Server
Variablenname |
Zweck |
0 bei aktiver Zeichensatzumwandlung | |
Zeichensatz-ID des Clients | |
Zeichensatzname des Clients | |
Anzahl der Anmeldungen seit Start von SQL Server | |
In Ticks gemessene Zeitspanne, die die CPU seit Start von SQL Server beschäftigt ist | |
Enthält den Fehlerstatus | |
Letzter in eine Identitätsspalte eingefügter Wert | |
In Ticks gemessene Zeitspanne, die SQL Server seit Start im Leerlauf ist | |
In Ticks gemessene Zeitspanne, die SQL Server mit Ein-/Ausgaben verbracht hat | |
Momentane Isolationsebene des Transact-SQL-Programms | |
Definiert ID der lokalen Sprache | |
Definiert den Namen der lokalen Sprache | |
Maximale Länge eines Zeichens | |
Maximale Anzahl von Verbindungen, die mit SQL Server hergestellt werden können | |
Durchschnittliche Länge eines nationalen Zeichens | |
Verschachtelungsebene der aktuellen Programmausführung | |
Anzahl der Eingabepakete, die durch SQL Server seit dem Start eingelesen wurden | |
Anzahl der Ausgabepakete, die durch SQL Server seit dem Start gesendet wurden | |
Anzahl der Fehler, die seit Start von SQL Server aufgetreten sind | |
ID der momentan ausgeführten gespeicherten Prozedur | |
Anzahl der vom letzten Befehl beeinflußten Zeilen | |
Name des lokalen SQL Servers | |
ID des aktuellen Prozesses | |
Enthält Statusinformationen | |
Maximale Länge von Text- oder Bilddaten, die mit der SELECT-Anweisung zurückgegeben werden | |
Änderung im freien Speicher, der für die Aktivierung einer Schwelle erforderlich ist | |
Anzahl der Mikrosekunden pro Tick | |
Anzahl der Fehler, die beim Lesen oder Schreiben aufgetreten sind | |
Anzahl der Lesezugriffe auf den Datenträger seit Start von SQL Server | |
Anzahl der Schreibzugriffe auf den Datenträger seit Start von SQL Server | |
Momentaner Transaktionsmodus des Transact-SQL-Programms | |
Verschachtelungsebene der Transaktionen | |
Momentaner Status einer Transaktion nach Ausführung einer Anweisung | |
Datum der aktuellen Version von SQL Server. |
Variablen verwenden
Mit dem Schlüsselwort DECLARE kann man mehrere Variablen in einer einzigen Anweisung deklarieren (obwohl das Ganze leicht unübersichtlich werden kann, vor allem, wenn man sich den Code später ansieht). Ein Beispiel für diese Art der Anweisung:
1> declare @batter_name char(30), @team int, @average float
2> go
Der nächste Abschnitt erläutert, wie man diese Variablen in Programmoperationen einsetzt.
Daten in Variablen speichern
Variablen sind nur innerhalb des aktuellen Anweisungsblocks verfügbar. In der Sprache Transact-SQL führt man einen Anweisungsblock mit dem Befehl go aus. (In Oracle dient das Semikolon demselben Zweck.) Der Gültigkeitsbereich einer Variablen bezieht sich auf die Verwendung der Variablen innerhalb der aktuellen Transact-SQL-Anweisung.
Variablen lassen sich nicht einfach mit Hilfe des Gleichheitszeichens initialisieren. Probieren Sie die folgende Anweisung aus, und beachten Sie den zurückgegebenen Fehler.
1> declare @name char(30)
2> @name = 'Billy Brewster'
3> go
Sie sollten eine Fehlermeldung erhalten haben, die eine ungeeignete Syntax in Zeile 2 bemängelt. Eine Variable ist nämlich mit einem SELECT-Befehl zu initialisieren. (Jawohl, derselbe Befehl, den Sie bereits beherrschen.) Wiederholen Sie das obige Beispiel mit der korrekten Syntax:
1> declare @name char(30)
2> select @name = 'Billy Brewster'
3> go
Diese Anweisung wird ohne Beanstandung ausgeführt. Hätten Sie weitere Anweisungen vor Ausführung von go eingefügt, könnten Sie hier die Variable @name verwenden.
Daten in lokale Variablen abrufen
Variablen speichern oft Daten, die aus einer Datenbank abgerufen wurden. Man kann diese Variablen dann in gebräuchlichen SQL-Befehlen wie SELECT, INSERT, UPDATE und DELETE verwenden. Beispiel 19.1 zeigt die Verwendung von Variablen in dieser Weise.
Beispiel 19.1
Dieses Beispiel ruft den Namen des Spielers in der Datenbank BASEBALL ab, der den höchsten Schlagdurchschnitt aufweist und für die Portland Beavers spielt.
1> declare @team_id int, @player_name char(30), @max_avg float
2> select @team_id = TEAM_ID from TEAMS where CITY = 'Portland'
3> select @max_avg = max(AVERAGE) from BATTERS where TEAM = @team_id
4> select @player_name = NAME from BATTERS where AVERAGE = @max_avg
5> go
Dieses Beispiel gliedert sich in drei Abfragen, um die Verwendung von Variablen zu demonstrieren. |
Der Befehl PRINT
Ein weiteres nützliches Feature von Transact-SQL ist der Befehl PRINT, mit dem man die Ausgabe auf das Anzeigegerät schreiben kann. Der Befehl hat die folgende Syntax:
PRINT Zeichenstring
Obwohl PRINT nur Zeichenstrings anzeigt, bietet Transact-SQL eine Anzahl von Funktionen, die verschiedene Datentypen in Strings (und umgekehrt) umwandeln können.
Beispiel 19.2
Dieses Beispiel wiederholt Beispiel 19.1, gibt aber am Ende den Namen des Spielers aus.
1> declare @team_id int, @player_name char(30), @max_avg float
2> select @team_id = TEAM_ID from TEAMS where CITY = 'Portland'
3> select @max_avg = max(AVERAGE) from BATTERS where TEAM = @team_id
4> select @player_name = NAME from BATTERS where AVERAGE = @max_avg
5> print @player_name
6> go
Beachten Sie, daß man eine Variable in der WHERE-Klausel (oder irgendeiner anderen Klausel) wie einen konstanten Wert verwenden kann.
Flußsteuerung
Wahrscheinlich die leistungsfähigste Gruppe von Transact-SQL-Funktionen betrifft die Steuerung des Programmablaufs. Wenn Sie bereits mit anderen bekannten Sprachen wie C, Cobol, Pascal oder Visual Basic programmiert haben, sind Sie sicherlich schon mit Befehlen wie IF...THEN und Schleifenanweisungen vertraut. Dieser Abschnitt beschreibt die wichtigsten Befehle zur Steuerung des Programmablaufs.
Die Anweisungen BEGIN und END
Transact-SQL kennzeichnet mit den Anweisungen BEGIN und END die Anfangs- und Endpunkte von Codeblöcken. (Andere Sprachen verwenden für diesen Zweck unter anderem geschweifte Klammern oder andere Operatoren.) Häufig findet man die BEGIN/END-Anweisungen in Verbindung mit IF...ELSE-Anweisungen und WHILE-Schleifen. Das folgende Beispiel zeigt einen einfachen Block mit BEGIN und END:
BEGIN
Anweisung1
Anweisung2
Anweisung3
END
Die Anweisung IF...ELSE
Eine der grundlegendsten Programmkonstruktionen ist die Anweisung IF...ELSE. Nahezu jede Programmiersprache unterstützt diese Konstruktion. Beispielsweise lassen sich damit die aus einer Datenbank abgerufenen Werte testen. Die Transact-SQL-Syntax für die IF...ELSE-Anweisung sieht folgendermaßen aus:
if (Bedingung)
begin
(Anweisungsblock)
end
else if (Bedingung)
begin
(Anweisungsblock)
end
...
...
...
else
begin
(Anweisungsblock)
end
Für jeden Zweig der Bedingungskonstruktion existiert ein eigener BEGIN/END-Block mit entsprechenden Anweisungen. Es gehört zum guten Programmierstil, die Anweisungsblöcke um eine bestimmte Anzahl von Leerzeichen einzurücken und diese Konvention in der gesamten Anwendung beizubehalten. Dadurch verbessert sich die Lesbarkeit des Programms, und man verringert die Anzahl der Fehler, die sich allein aufgrund einer unübersichtlichen Darstellung einschleichen.
Beispiel 19.3
Dieses Beispiel erweitert Beispiel 19.2 durch eine Prüfung auf den Schlagdurchschnitt eines Spielers. Wenn der Durchschnitt des Spielers über .300 liegt, soll er eine Gehaltserhöhung erhalten. Andernfalls könnte der Spieler schnell im Abseits verschwinden!
Beispiel 19.3 setzt die IF...ELSE-Anweisung ein, um Bedingungen innerhalb der Anweisung auszuwerten. Wenn die erste Bedingung gleich TRUE ist, erscheint der angegebene Text auf dem Bildschirm. Der alternative Text wird bei jeder anderen Bedingung (ELSE) ausgegeben.
1> declare @team_id int, @player_name char(30), @max_avg float
2> select @team_id = TEAM_ID from TEAMS where CITY = 'Portland'
3> select @max_avg = max(AVERAGE) from BATTERS where TEAM = @team_id
4> select @player_name = NAME from BATTERS where AVERAGE = @max_avg
5> if (@max_avg > .300)
6> begin
7> print @player_name
8> print 'Bekommt eine Gehaltserhöhung!'
9> end
10> else
11> begin
12> print @player_name
13> print 'Komm'' wieder, wenn du besser triffst!'
14> end
15> go
Beispiel 19.4
Mit dieser neuen IF-Anweisung lassen sich die einfachen BASEBALL-Datenbankabfragen etwas interessanter gestalten. Beispiel 19.4 fügt einen IF...ELSE IF...ELSE-Zweig in den Code von Beispiel 19.3 ein.
1> declare @team_id int, @player_name char(30), @max_avg float
2> select @team_id = TEAM_ID from TEAMS where CITY = 'Portland'
3> select @max_avg = max(AVERAGE) from BATTERS where TEAM = @team_id
4> select @player_name = NAME from BATTERS where AVERAGE = @max_avg
5> if (@max_avg > .300)
6> begin
7> print @player_name
8> print 'Bekommt eine Gehaltserhöhung!'
9> end
10> else if (@max_avg > .275)
11> begin
12> print @player_name
13> print 'Nicht schlecht. Hier ist eine Anerkennung!'
14> end
15> else
16> begin
17> print @player_name
18> print 'Komm'' wieder, wenn du besser triffst!'
19> end
20> go
In Transact-SQL lassen sich auch Bedingungsfunktionen in einer IF-Anweisung einsetzen. Entsprechende Funktionen können auf bestimmte Bedingungen oder Werte testen. Wenn die Funktion TRUE zurückgibt, wird der IF-Zweig abgearbeitet. Andernfalls durchläuft das Programm den ELSE-Zweig (falls dieser vorhanden ist), wie es das vorhergehende Beispiel gezeigt hat.
Die Bedingung EXISTS
Mit dem Schlüsselwort EXISTS läßt sich prüfen, ob eine SELECT-Anweisung einen Wert zurückgegeben hat. In diesem Fall durchläuft das Programm den IF-Zweig. Beispiel 19.5 demonstriert diese Logik.
Beispiel 19.5
In diesem Beispiel wertet das Schlüsselwort EXISTS eine Bedingung in IF aus. Die Bedingung ist in Form einer SELECT-Anweisung formuliert.
1> if exists (select * from TEAMS where TEAM_ID > 5)
2> begin
3> print 'Es existiert!!'
4> end
5> else
6> begin
7> print 'Nichts zu finden!'
8> end
Das Ergebnis einer Abfrage testen
Mit der IF-Anweisung läßt sich auch das Ergebnis testen, das eine SELECT-Abfrage zurückgibt. Beispiel 19.6 implementiert diese Möglichkeit, um auf den maximalen Schlagdurchschnitt unter den Spielern zu prüfen.
Beispiel 19.6
Dieses Beispiel ist ähnlich zu Beispiel 19.5. Es verwendet die SELECT-Anweisung, um eine Bedingung zu testen. Dieses Mal testen wir aber die Bedingung mit dem Zeichen größer als (>).
1> if (select max(AVG) from BATTERS) > .400
2> begin
3> print 'UNGLAUBLICH!!'
4> end
5> else
6> print 'TED WILLIAMS IST ABGESCHLAGEN!'
7> end
Informieren Sie sich über die IF-Anweisung in Ihrer konkreten SQL-Implementierung. Denken Sie sich verschiedene Bedingungen aus, die Sie in der Datenbank BASEBALL (oder irgendeiner anderen) überprüfen möchten. Starten Sie einige Abfragen, um sich mit dem Einsatz der IF-Anweisung vertraut zu machen.
Die WHILE-Schleife
Mit der WHILE-Schleife unterstützt Transact-SQL eine weitere bekannte Programmkonstruktion. Die Syntax lautet:
WHILE (logischer_Ausdruck)
begin
Anweisung(en)
end
Beispiel 19.7
Die WHILE-Schleife arbeitet die enthaltenen Anweisungen wiederholt ab, bis der logische Ausdruck FALSE liefert. Das nächste Beispiel inkrementiert eine lokale Variable (namens COUNT) in einer einfachen WHILE-Schleife.
1> declare @COUNT int
2> select @COUNT = 1
3> while (@COUNT < 10)
4> begin
5> select @COUNT = @COUNT + 1
6> print 'Erneuter Schleifendurchlauf!'
7> end
8> print 'Schleife beendet!'
Der Befehl BREAK
Mit dem Befehl BREAK läßt sich der sofortige Austritt aus einer WHILE-Schleife erzwingen. Den Befehl BREAK setzt man häufig in Verbindung mit einem IF-Test ein, um bei einem bestimmten Ergebnis einer Bedingung die WHILE-Schleife zu verlassen. Damit setzt die Programmausführung mit den Befehlen fort, die unmittelbar auf die END-Anweisung folgen. Beispiel 19.8 zeigt den Einsatz des BREAK-Befehls. Hier wird auf eine willkürlich gewählte Zahl (sagen wir @COUNT = 8) geprüft. Wenn die Bedingung erfüllt ist, verläßt das Programm die WHILE-Schleife.
Beispiel 19.8
Beachten Sie die Anordnung des BREAK-Befehls nach der Auswertung der ersten Bedingung in IF.
1> declare @COUNT int
2> select @COUNT = 1
3> while (@COUNT < 10)
4> begin
5> select @COUNT = @COUNT + 1
6> if (@COUNT = 8)
7> begin
8> break
9> end
10> else
11> begin
12> print 'Erneuter Schleifendurchlauf!'
13> end
14> end
15> print 'Schleife beendet!'
Der BREAK-Befehl bewirkt das Verlassen der Schleife, wenn die Variable @COUNT den Wert 8 erreicht. |
Der Befehl CONTINUE
Der Befehl CONTINUE ist ein weiterer Spezialbefehl, der sich innerhalb einer WHILE-Schleife einsetzen läßt. Dieser Befehl bewirkt, daß die Schleifenausführung sofort an den Beginn der Schleife springt, statt den Rest der Schleife abzuarbeiten und dann erst wieder an den Beginn zurückzugehen. Wie beim BREAK-Befehl verwendet man den Befehl CONTINUE häufig in einer IF-Anweisung, um auf eine Bedingung zu testen und dann eine Aktion auszulösen. Beispiel 19.9 zeigt einen Einsatzfall.
Beispiel 19.9
Beachten Sie die Anordnung der CONTINUE-Anweisung nach der Auswertung der ersten Bedingung in IF.
1> declare @COUNT int
2> select @COUNT = 1
3> while (@COUNT < 10)
4> begin
5> select @COUNT = @COUNT + 1
6> if (@COUNT = 8)
7> begin
8> continue
9> end
10> else
11> begin
12> print 'Erneuter Schleifendurchlauf!'
13> end
14> end
15> print 'Schleife beendet!'
Beispiel 19.9 ist Beispiel 19.8 ähnlich, arbeitet aber mit dem CONTINUE-Befehl statt mit BREAK. Bei @COUNT = 8 verläßt das Programm nunmehr nicht die Schleife, sondern geht an den Anfang der WHILE-Schleife zurück und arbeitet die Anweisungen in der Schleife weiter ab. |
Mit der WHILE-Schleife durch eine Tabelle scrollen
SQL Server und viele andere Datenbanksysteme verfügen über den speziellen Objekttyp Cursor, mit dem man datensatzweise durch die Datensätze einer Tabelle scrollen kann. (Siehe dazu Tag 13.) Allerdings unterstützen manche Datenbanksysteme keine scrollbaren Cursor. Beispiel 19.10 zeigt einen Ansatz, wie man mit einer WHILE-Schleife arbeitet, um etwa die Funktionalität eines Cursors zu implementieren, wenn diese Funktionalität nicht automatisch zur Verfügung steht.
Beispiel 19.10
Mit der WHILE-Schleife kann man durch Tabellen datensatzweise blättern. Transact-SQL verwaltet die Variable rowcount, mit der man SQL Server anweisen kann, nur eine Zeile bei einer Abfrage zurückzugeben. Wenn man mit einem anderen Datenbankprodukt arbeitet, sollte man sich über ähnliche Einstellungen informieren. Durch Setzen von rowcount auf 1 (der Standardwert 0 bedeutet unbegrenzt) gibt SQL Server nur einen Datensatz bei einer SELECT-Abfrage zurück. Mit diesem einen Datensatz können Sie dann alle gewünschten Operationen anstellen. Indem Sie den Inhalt einer Tabelle in eine temporäre Tabelle selektieren, die am Ende der Operation gelöscht wird, können Sie eine Zeile pro Abfrage auswählen und diese Zeile nach getaner Arbeit löschen. Wenn alle Zeilen aus der Tabelle ausgewählt würden, müßte man jede Zeile in der Tabelle durcharbeiten! (Wie gesagt, diese Funktionalität entspricht nur in etwa der eines Cursors.) Führen wir nun das Beispiel aus.
1> set rowcount 1
2> declare @PLAYER char(30)
3> create table temp_BATTERS (
4> NAME char(30),
5> TEAM int,
6> AVERAGE float,
7> HOMERUNS int,
8> RBIS int)
9> insert temp_BATTERS
10> select * from BATTERS
11> while exists (select * from temp_BATTERS)
12> begin
13> select @PLAYER = NAME from temp_BATTERS
14> print @PLAYER
15> delete from temp_BATTERS where NAME = @PLAYER
16> end
17> print 'Schleife beendet!'
Platzhalter-Operatoren von Transact-SQL
Der Einsatz von Platzhalterbedingungen (Wildcards) in SQL wurde in Lektion 3 eingeführt. Der Operator LIKE erlaubt die Verwendung von Platzhalterbedingungen in SQL-Anweisungen. Transact-SQL erweitert die Flexibilität von Platzhalterbedingungen. Die folgende Übersicht faßt die Wildcard-Operationen von Transact-SQL zusammen.
Berichte mit COMPUTE erstellen
In Transact-SQL lassen sich auch zusammengefaßte Datenbankberichte erstellen. Die Syntax des Befehls COMPUTE ist eng mit dem Pendant in SQL*Plus verwandt. (Siehe dazu Tag 20.)
Die folgende Abfrage liefert einen Bericht, der alle Schläger, die Anzahl der Heimspiele jedes Schlagmanns und die Gesamtzahl der Heimspiele aller Schlagmänner zeigt:
select name, homeruns
from batters
compute sum(homeruns)
Im obigen Beispiel führt COMPUTE allein Berechnungen auf dem Bericht als Ganzes aus, während COMPUTE BY die Berechnungen auf angegebenen Gruppen und dem gesamten Bericht ausführt, wie es das folgende Beispiel zeigt: |
COMPUTE FUNCTION(Ausdruck) [BY Ausdruck]
Für FUNCTION können die Aggregatfunktionen SUM, MAX, MIN etc. stehen. Ausdruck ist gewöhnlich ein Spaltenname oder ein Alias.
Datumsformate
Sybase und Microsoft SQL Server kann Datumswerte in eine Tabelle in verschiedenen Formaten einfügen. Außerdem lassen sich Datumswerte in verschiedenen Formaten abrufen. Dieser Abschnitt zeigt, wie man mit dem Befehl CONVERT von SQL Server das Anzeigeformat eines Datums beeinflussen kann.
CONVERT (Datentyp [(Laenge)], Ausdruck, Format)
Die folgenden Datumsformate sind in SQL Server verfügbar, wenn man mit der Funktion CONVERT arbeitet:
Tabelle 19.5: Datumsformate in SQL Server
Formatcode |
Darstellung |
100 |
mon dd yyyy hh:miAM (oder PM) |
101 |
mm/dd/yy |
102 |
yy.mm.dd |
103 |
dd/mm/yy |
104 |
dd.mm.yy |
105 |
dd-mm-yy |
106 |
dd mon yy |
107 |
mon dd, yy |
108 |
hh:mi:ss |
109 |
mon dd, yyyy hh:mi:ss:mmmAM (oder PM) |
110 |
mm-dd-yy |
111 |
yy/mm/dd |
112 |
yymmdd |
113 |
dd mon yyyy hh:mm:ss:mmm (24h) |
114 |
hh:mi:ss:mmm (24h) |
select 'ZAHL_DATUM' = convert(char(15), ZAHL_DATUM, 104)
from RECHNUNGEN
where KUNDEN_NR = 012845
ZAHL_DATUM
---------------
01.05.1997
Das obige Beispiel verwendet den Formatcode 104 in der CONVERT-Funktion. Entsprechend der Tabelle der Datumsformate zeigt Code 104 das Datum im deutschen Format dd.mm.yy an. |
Diagnosewerkzeuge von SQL Server - SET-Befehle
In Transact-SQL lassen sich mit SET-Befehlen verschiedene Optionen aktivieren, um Transact-SQL-Anweisungen zu analysieren. Einige der gebräuchlichsten SET-Befehle zeigt die folgende Übersicht:
Mit den folgenden Befehlen kann man steuern, was als Teil der Ausgabe von Abfragen anzuzeigen ist:
Die Optimierung von SQL-Anweisungen ist Thema von Tag 15. |
Zusammenfassung
Tag 19 führt eine Reihe von Themen ein, die etwas Biß in Ihre SQL-Programmierpraxis bringen. Die bisher in diesem Buch behandelten SQL-Themen sind äußerst wichtig und liefern die Grundlage für Ihre gesamte Datenbankprogrammierung. Allerdings bilden diese Themen erst den Anfang. Die gestern und heute erläuterten prozeduralen Sprachkonzepte von SQL bauen auf Ihren SQL-Grundkenntnissen auf. Es handelt sich um leistungsfähige Konstruktionen, mit denen Sie auf die Daten in Ihrer relationalen Datenbank zugreifen können.
Die Sprache Transact-SQL gehört zu den Produkten SQL Server von Sybase und Microsoft und stellt viele Programmkonstrukte bereit, die man in bekannten Sprachen der dritten und vierten Generation findet. Dazu gehört die IF-Anweisung, die WHILE-Schleife und die Möglichkeit, lokale und globale Variablen zu deklarieren.
Denken Sie daran, daß Tag 19 nur eine kurze Einführung in die Funktionen und Verfahren des Transact-SQL-Codes bietet. Vertiefen Sie sich ruhig in Ihre Dokumentation und probieren Sie alle Werkzeuge aus, die Ihnen zur Verfügung stehen. Eine detaillierte Behandlung von Transact-SQL finden Sie in den entsprechenden Dokumentationen zu Microsoft SQL Server.
Fragen & Antworten
Frage:
Stellt SQL eine FOR-Schleife bereit?
Antwort:
Programmierkonstrukte wie FOR-Schleifen, WHILE-Schleifen und CASE-Anweisungen sind Erweiterungen zu ANSI-SQL. Demzufolge variiert die Verwendung dieser Elemente von einem Datenbanksystem zum anderen. Beispielsweise bietet Oracle die FOR-Schleife, während Transact-SQL (SQL Server) diese Konstruktion nicht kennt. Man kann natürlich in einer WHILE-Schleife eine Variable inkrementieren und auf diese Weise die FOR-Schleife nachbilden.
Frage:
Ich entwickle eine Windows- (oder Macintosh-) Anwendung, in der die Benutzeroberfläche aus Elementen wie Fenstern und Dialogfeldern besteht. Kann ich mit der PRINT-Anweisung Meldungen an den Benutzer ausgeben?
Antwort:
SQL ist vollständig plattformunabhängig. Demzufolge öffnet die PRINT-Anweisung kein eigenes Meldungsfenster. Um Meldungen an den Benutzer auszugeben, können Ihre SQL-Prozeduren vordefinierte Werte zurückgeben, die Erfolg oder Scheitern anzeigen. Dann kann der Benutzer vom Status der Abfragen unterrichtet werden. (Der PRINT-Befehl ist vor allem bei der Fehlersuche hilfreich, da eine innerhalb einer gespeicherten Prozedur ausgeführte PRINT-Anweisung überhaupt nicht auf dem Bildschirm ausgegeben wird.)
Workshop
Kontrollfragen
1. Richtig oder falsch: Die Bezeichnung SQL in PL/SQL von Oracle und Transact-SQL von Microsoft/Sybase impliziert, daß diese Produkte vollständig kompatibel zum ANSI-Standard sind.
2. Richtig oder falsch: Statisches SQL ist nicht so flexibel wie dynamisches SQL, obwohl die Leistungsbilanz von statischem SQL besser sein kann.
Übungen
1. Wenn Sie nicht mit SQL Server von Microsoft/Sybase arbeiten, sollten Sie die Erweiterungen Ihres Produkts zu ANSI-SQL mit den heute erwähnten Erweiterungen vergleichen.
2. Schreiben Sie eine Anweisungsgruppe, die das Vorhandensein einer bestimmten Bedingung überprüft. Wenn diese Bedingung TRUE ist, führen Sie eine bestimmte Operation aus. Andernfalls führen Sie eine andere Operation aus.
Ein Imprint des Markt&Technik Buch- und Software-Verlag GmbH.
Elektronische Fassung des Titels: SQL in 21 Tagen, ISBN: 3-8272-2020-3