Content-Type: multipart/related; start=; boundary=----------hCIO5lKGmo8K5cqvFf690d Content-Location: http://www.sql-und-xml.de/temp/sql-tutorial.print.html Subject: =?utf-8?Q?Sql=20lernen=20-=20ein=20Tutorial=20zum=20Selbststudium=20mit=20einer=20Beispiel-Datenbank?= MIME-Version: 1.0 ------------hCIO5lKGmo8K5cqvFf690d Content-Disposition: inline; filename=sql-tutorial.print.html Content-Type: text/html; charset=utf-8; name=sql-tutorial.print.html Content-ID: Content-Location: http://www.sql-und-xml.de/temp/sql-tutorial.print.html Content-Transfer-Encoding: Quoted-Printable =EF=BB=BFSql lernen - ein Tutorial zum Selbststudium mit eine= r Beispiel-Datenbank

Sql-Tutorial: Lernen Sie= Sql und =C3=BCben Sie die entsprechenden Befehle interaktiv anhand des S= ql-interaktiv-lernen

Auf den folgenden Seiten finden Sie ein Sql-Tutorial, das anhand einer e= infachen Datenbank die zentralen Prinzipien der beiden Teile von SQL, der Data Manipulation Language (DML) und der Data Definit= ion Language (DDL) verdeutlicht. Die Beispieldatenbank, bestehend aus drei kleinen Tabellen (Artike= l.txt, Vertreter.txt, Umsatz.txt) k=C3=B6nnen Sie sich entweder direkt herunterladen und in ein eigenes Da= tenbank-System einspielen oder Sie nutzen das Sql-interaktiv-lernen aus den Freeware-Tools. In diesem ist eine Access-Datenbank mit den drei Beispie= ltabellen bereits enthalten. Eine Access-Installation ist zur Nutzung nicht notwendig. Es gen=C3=BCgt die = .NET1.1-Laufzeitumgebung, der Zugriff auf die Datenbank erfolgt =C3=BCber das Programm.

Falls Sie das Beispiel auf einem Ms-SqlServer oder einem anderen verglei= chbaren Datenbank-System verwenden m=C3=B6chten, k=C3=B6nnen Sie das Script create-sql-interaktiv.sql verwenden. Mit dem OSQL.exe k=C3= =B6nnen Sie dieses Script ausf=C3=BChren, ein Beispiel finden Sie in der Datei.<= p>

Neu= e L=C3=B6sungen f=C3=BCr Ihre Daten

Server-Daten: Di= e Web - Datenbank als CRM - L=C3=B6sung ist:

  • die Single-Data-Solution: Alles i= n einer Datenbank, ein Login.
  • Sie entscheiden, was Ihre Datenban= k macht. Diese funktioniert.
  • Einfach f=C3=BCr alle Generationen = - Internetzugang gen=C3=BCgt.
  • Erste Formulare nach ein bis zwei = Tagen.
  • Kontakt per Telefon (+49(0)30 420 20= 0 60) oder per Mail
  • Zah= lungsm=C3=B6glichkeiten: Einmalige Einrichtung plus Miete (Preis= liste) oder Einrichtung+Miete verteilt auf 1 bis 2 Jahre monatlich
  • Jetzt anmelden!

Ein Hinweis zum Aufbau dieses Tutorials: Bevor Sie sich zu viel mit der = Theorie besch=C3=A4ftigen - erarbeiten Sie sich zun=C3=A4chst die praktischen Beispiele zum SELECT-Befehl (DML-I). = Sql arbeitet mit Mengen. Sind Ihnen Auswertungen anhand eines =C3=BCberschaubaren, absichtlich kleinen Beisp= iels gel=C3=A4ufig, so lernen Sie die zugrundeliegende relationale Theorie beil=C3=A4ufig.

Auswahl= und Aggregation vorhandener Daten (Data Manipulation Language - DML-I)<= /h2>
  • SELECT - der Grundbegriff zur Auswahl = von Daten: Sobald Sie Daten ausw=C3=A4hlen, sei es, um diese direkt anzeigen zu lassen oder sie weiterzuverarbeite= n, verwenden Sie den SELECT-Befehl. In der einfachsten Version werden aus einer Tabelle= alle oder einige Spalten ausgew=C3=A4hlt.
  • Mit WHERE wenige Zeilen ausw=C3=A4hlen: Sol= len von einer Tabelle nicht s=C3=A4mtliche, sondern nur wenige Zeilen zur=C3=BCckgegeben werden, so reduzieren Sie die Zah= l der ausgegebenen Zeilen mit einer WHERE-Klausel.
  • Mit= JOIN Tabellen kombinieren: Wurden di= e Regeln f=C3=BCr die Normalisierung der Daten eingehalten, so sind die zu einem Datensatz geh=C3=B6renden Zeilen oft= mals =C3=BCber mehrere Tabellen verteilt. Mit einer JOIN - Klausel lassen sich zwei Tabellen zu einer = neuen, virtuellen Tabelle zusammenf=C3=BCgen, so da=C3=9F bsp. Zellen aus verschiedenen Tabellen= miteinander multipliziert oder nach fehlenden Eintr=C3=A4gen in einer der Tabellen gesucht werden kann.
  • Mit GROUP BY Daten aggregieren und auswerten: A= lle bisherigen Techniken w=C3=A4hlen aus, ver=C3=A4ndern die Ausgabezeilen jedoch nicht. M=C3=B6chten Sie Werte = einer Spalte aus mehreren Zeilen addieren, das Maximum in einer Spalte bestimmen oder Ums=C3=A4tze pro Tag und pro Ar= tikel erhalten, so verwenden Sie Aggregatfunktionen und die GROUP-BY - Klausel.
  • Subqueries / Unterabfragen: Unterabfragen, meist Subqueries genannt, we= rden verwendet, um das Ergebnis einer Abfrage sofort als zus=C3=A4tzlichen Input f=C3=BC= r eine weitere Abfrage heranzuziehen. Damit lassen sich tieferliegende Strukturen ermitteln, etwa die Frage,= welche Artikel oder Vertreter =C3=BCberdurchschnittlich viel zum Umsatz beigetragen haben.
=

Grundlagen f=C3=BCr relationale Datenbank-Systeme= und Entwurf der Speicherstruktur

Eintragen, =C3=84ndern und L=C3=B6schen von Daten (Data Manipulat= ion Language - DML-II)

Weitere Seiten zum Erstellen von Datenbank-Objekten (DDL) werden folgen.= DLL-Befehle k=C3=B6nnen allerdings nicht von Nutzern beim Hauptprojekt verwendet werden, insofern sind diese Themen derzeit n= achrangig. Die aktuellen Texte stehen bereits zur Verf=C3=BCgung, damit Beispiele f= =C3=BCr das Sql-interaktiv-lernen aus den Freeware-Tools existieren und genutzt werden k=C3=B6nnen.

Falls Sie diesen Text interessant finden, k=C3=B6nnen Sie gerne einen Ve= rweis auf Ihrer Site einf=C3=BCgen. Verlinken Sie bitte ausschlie=C3=9Flich das Html-Angebot, die Xml-Version ist nur f=C3= =BCr Leser mit dem IE6 verwendbar. Kopieren Sie die folgende Html-Zeile in den Quellcode Ihrer Datei oder p= assen Sie die Darstellung Ihren eigenen Bed=C3=BCrfnissen an:
<a href=3D"http://www.sql-und-xml.de/sql-tutorial/">Sql-Tutor=
ial</a>

TOP

Daten ausw=C3=A4hlen mit dem SELECT-Befehl

Die SELECT-Anweisung ist fundamental f=C3=BCr jedes Ausw=C3=A4hlen von D= aten und stellt diese in Form einer virtuellen Tabelle zur Verf=C3=BCgung. Diese virtuelle Tabelle, auch Recordset genannt, also eine Menge (=3D Set) von Records (=3D Datenzeilen, Da= tens=C3=A4tzen), existiert zun=C3=A4chst nur tempor=C3=A4r im Arbeitsspeicher und wird na= ch dem Ende der Befehlsausf=C3=BChrung verworfen. Wird SELECT ohne weitere Erg=C3=A4nzungen verwendet, so werden die Daten= angezeigt. Die Ausgabe kann auch mit SELECT ... INTO ... FROM in eine neue Tabelle kopiert oder mit INSERT INTO ... SELECT ... zu einer b= estehenden Tabelle hinzugef=C3=BCgt werden.

Syntax

  • SELECT	[DISTINCT]
    	<Name einer Spalte>
    	<Konstante>
    	<Berechnung>
    	<einer der obigen Ausdr=C3=BCcke> As Spaltenalias
    	[, weitere der obigen Ausdr=C3=BCcke]
    
    FROM <Ausdruck, der eine Tabelle zur=C3=BCckgibt> As Tabellenalias=
    
    
    [WHERE ...]
    
    [GROUP BY ...]
    
    [HAVING ...]
    
    [UNION [ALL]]
    
    [Weitere SELECT-Anweisung, welche dieselbe Zahl von
    	Spalten und Datentypen liefert]
    
    [ORDER BY [Order-By-Ausdruck] ASC | DESC]]
    	[, weitere Sortierungen]
    Dies ist die grundlegende Syntax des SELECT-Befehls. Details zu den Ausd= r=C3=BCcken nach FROM, WHERE, GROUP BY und HAVING finden Sie in den Abschnitten =C3=BCber JOIN, WHERE = und GROUP BY. Die hiesigen Beispiele behandeln nur den Abschnitt zwischen SELECT und FROM.
  • SELECT <Name einer Spalte - wie oben >
    
    INTO <neue Tabelle>
    
    FROM <Ausdruck, der eine Tabelle zur=C3=BCckgibt> As Tabellenalias=
    

Beispiele

  1. SELECT A_NR,
    	A_NAME,
    	A_PREIS
    FROM ARTIKEL
    Einfache, kommagetrennte Auflistung der gew=C3=BCnschten Spalten, die im= Tabellen-Ausdruck vorkommen. Ohne Alias f=C3=BCr die Tabelle.
  2. SELECT A.A_NR,
    	A.A_NAME,
    	A.A_PREIS
    FROM ARTIKEL As A
    ORDER BY A.A_PREIS
    Dasselbe wie im ersten Beispiel, aber mit Aliasname A f=C3=BCr die Tabel= le und aufsteigender Sortierung nach der Spalte A_PREIS.
  3. SELECT A_NR,
    	A_PREIS  As Netto,
    	0.19 As MwSt,
    	A_PREIS * 1.19 As Brutto,
    FROM ARTIKEL
    ORDER BY A_PREIS DESC
    Hier werden Alias-Ausdr=C3=BCcke f=C3=BCr die Spalten verwendet - das Er= gebnis kennt die drei Spalten Netto, MwSt und Brutto. MwSt ist ein konstanter Wert, in der Spalte Brut= to wird der Inhalt von A_PREIS multipliziert mit einer Konsta= nten. Da ein solches Ergebnis keinen Spaltennamen hat, sollte dieser anschlie=C3=9Fen= d festgelegt werden. Das Ergebnis wird nach A_PREIS absteigend sortiert.
  4. SELECT A.* FROM ARTIKEL As A
    ORDER BY A.A_NAME ASC,
    	A.A_PREIS DESC
    Hier wird f=C3=BCr die Tabelle ein Alias A verwendet und mit * s=C3=A4mt= liche Spalten ausgew=C3=A4hlt. Das Ergebnis wird aufsteigend nach den Artikel-Namen, absteigend nach den Artikel-Pre= isen sortiert.
  5. SELECT DISTINCT A.A_NAME
    FROM ARTIKEL As A
    Das Schl=C3=BCsselwort DISTINCT entfernt alle mehrfach vorkommenden Zeil= en mit Ausnahme einer. Diese Abfrage liefert deshalb nicht vier Zeilen mit doppeltem 'Oberhemd', sondern nur = drei Zeilen zur=C3=BCck, eine Zelle mit dem Wert 'Oberhemd' wurde entfernt.
  6. SELECT A.A_NAME
    FROM ARTIKEL As A
    UNION
    SELECT B.V_NAME
    FROM VERTRETER As B
    Diese inhaltlich merkw=C3=BCrdige Abfrage liefert alle Artikel- und alle= Vertreter-Namen in einer einzigen Liste aus. Da ALL fehlt, werden sechs Zeilen ausgegeben, das do= ppelte 'Oberhemd' wird nur einfach in das Resultset =C3=BCbernommen. Beachten Sie, da=C3=9F die Dat= entypen =C3=BCbereinstimmen m=C3=BCssen und da=C3=9F jede einzelne SELECT-Abfrage dieselbe Zahl von Spalten zur=C3=BCckliefer= n mu=C3=9F. Die Spaltennamen m=C3=BCssen allerdings nicht =C3=BCbereinstimmen, bei den SELECT-Anweisungen ab der = zweiten Abfrage kann auf ALIAS-Namen verzichtet werden.
  7. SELECT V.*
    	INTO [Kopie-von-Vertreter]
    FROM VERTRETER As V
    Dies transferiert die virtuelle Tabelle in ein reales neues Tabellenobje= kt. Zun=C3=A4chst wird die neue Tabelle 'Kopie-von-Vertreter' erstellt und anschlie=C3=9Fend mit den Zeilen gef=C3=BCllt, die von der = SELECT-Anweisung zur=C3=BCckgegeben wurden. Erg=C3=A4nzt man diese Abfrage um eine WHERE-Klausel 0 =3D 1, so werden keine Zeilen kopiert, e= s wird jedoch eine neue leere Tabelle erstellt.

Bemerkungen

  • Machen Sie es dem Sql-Parser m=C3=B6glichst einfach. Verwenden Sie A= lias-Namen f=C3=BCr Tabellen, dann k=C3=B6nnen die Spalten rascher identifiziert werden, es mu=C3=9F n= icht erst ermittelt werden, von welcher Tabelle diese Spalte stammt.
  • Wenn der Spalten-, Alias- oder Tabellenname Sonderzeichen, etwa ein = Leerzeichen oder Minus (-) enth=C3=A4lt, so schlie=C3=9Fen Sie den Ausdruck in eckige Klammern ein. Beispiel:
    Select A.A_PREIS * 1.19 As [Aktueller=
     Bruttopreis]
    FROM ARTIKEL
  • Soll ein konstanter Text angegeben werden, so setzen Sie diesen in e= infache Hochkommata. Beispiel
    SELECT A.A_NAME, 'aktuell' As Info
    FROM ARTIKEL As A
    Dies liefert zwei Spalten, die erste Spalte hei=C3=9Ft 'A_NAME', die zwe= ite 'Info'. Das Ergebnis enth=C3=A4lt vier Zeilen, in der ersten Spalte stehen die Werte aus der Tabelle, die = zweite Spalte enth=C3=A4lt viermal den Text 'aktuell'.
  • Ben=C3=B6tigen Sie eine zus=C3=A4tzliche Zahl, etwa beim Vereinigen = zweier Tabellen mit UNION, so k=C3=B6nnen Sie diese einfach notieren:
    SELECT A.A_NAME, 1 As [Index]
    FROM ARTIKEL As A
    UNION
    SELECT B.V_NAME, 2
    FROM VERTRETER As B
    Eine solche Techn= ik kann n=C3=BCtzlich sein, wenn mit UNION die Ausgaben mehrerer SELECT-Anweisungen zusammengef=C3=BCgt werde= n und eine Information ben=C3=B6tigt wird, aus welchem SELECT-Abschnitt die einzelne Zeile stammt.
  • Hinter FROM folgt ein Ausdruck, der eine Tabelle zur=C3=BCckgibt. Di= es kann, wie in den obigen Beispielen, eine einfache Tabelle sein, das Ergebnis einer JOIN-Verkn=C3=BCpfung ode= r einer Unterabfrage. Ferner lassen es manche Datenbanksysteme zu, da=C3=9F der FROM-Abschnitt fehlt. In diesem= Fall wird genau eine Zeile ausgegeben.
  • Beim Sortieren auf dem MS-SQLServer kann der Aliasname in der ORDER-= BY-Klausel angegeben werden. Access dagegen versteht diesen Namen nicht, so da=C3=9F bei der Sortieru= ng nach dem Ergebnis einer Rechenoperation diese erneut notiert werden mu=C3=9F.
  • Verwendet man die Technik 'SELECT ... INTO ... FROM ...', um eine ne= ue Tabelle zu erzeugen und enth=C3=A4lt die urspr=C3=BCngliche Tabelle eine automatisch hochz=C3=A4hlende ID (Identi= ty(1,1)), so wird dieser spezielle Spaltentyp auch in der Zieltabelle erzeugt. Soll dies vermieden werden, kann zur Identit=C3=A4t= sspalte 0 hinzugef=C3=BCgt und der Spaltenname als Alias notiert werden:
    SELECT U.Umsatz_Nr + 0 As [Umsatz_Nr]=
    , U.A_Nr
    	Into [Umsatz-Kopie]
    FROM UMSATZ As U
    Nun wird die Spalte = Umsatz_Nr der neuen Tabelle als Integer definiert.

TOP

Mit WHERE wenige Zeilen ausw=C3=A4hlen

Die SELECT-Anweisung liefert eine virtuelle Tabelle, bestehend aus Zeile= n und Spalten zur=C3=BCck. Der nach FROM folgende WHERE-Abschnitt kann Spaltennamen verwenden, um Bedingungen festzulegen.= F=C3=BCr jede Zeile wird gepr=C3=BCft, ob die durch den Spaltennamen festgelegte Zelle die Bedingung erf=C3=BCllt. Falls dies der Fall ist, w= ird die Zeile zur Ausgabe hinzugef=C3=BCgt, ansonsten wird diese Zeile nicht zum Resultset erg=C3=A4nzt.

Syntax

  • SELECT ...
    FROM ...
    WHERE <Bedingung 1> [<logischer Operator> <Bedingung 2>=
    ;]
    Es kann entweder nur eine Bedingung geben. Oder es werden mehrere Beding= ungen angegeben, welche mit logischen Operatoren (NOT, AND, OR) miteinander verkn=C3=BCpft sind.
  • Zul=C3=A4ssige Vergleichsoperatoren zwischen Spaltennamen und Ausdr=C3= =BCcken, Konstanten und weiteren Spaltennamen:
    =3D
    Gleichheit
    <>
    verschieden
    <
    kleiner
    >
    gr=C3=B6=C3=9Fer
    <=3D
    kleiner oder gleich
    >=3D
    gr=C3=B6=C3=9Fer oder gleich
    IS NULL
    pr=C3=BCft, ob die Zelle leer ist
    IS NOT NULL
    pr=C3=BCft, ob die Zelle einen We= rt enth=C3=A4lt
    Between
    Zwischen zwei Werten liegend
    In
    pr=C3=BCft, ob der linke Ausdruck in einem= der rechten vorkommt
    Like
    Vergleich auf Textmuster
    Exists
    pr=C3=BCft, ob die folgende Unterabfra= ge mindestens eine Zeile zur=C3=BCckliefert
  • Zul=C3=A4ssige logische Operatoren, die Ausdr=C3=BCcke mit Vergleich= soperatoren verkn=C3=BCpfen:
    NOT
    der folgende Ausdruck darf nicht erf=C3=BC= llt sein
    AND
    beide Bedingungen m=C3=BCssen erf=C3=BCll= t sein
    OR
    mindestens eine Bedingung mu=C3=9F erf=C3=BC= llt sein

Beispiele:

  1. Select A.*
    FROM ARTIKEL As A
    WHERE A.A_NR =3D 11
    W=C3=A4hlt die Zeile aus, bei welcher die Zelle A_NR den Wert 11 hat. Hi= er ist eine Bedingung und kein logischer Operator angegeben.
  2. WHERE NOT A.A_NR =3D 11
    WHERE A.A_NR <> 11
    W=C3=A4hlt alle Zeilen aus, deren A_NR verschieden von 11 und nicht leer= (Not Null) ist.
  3. WHERE A_PREIS IS NULL
    W=C3=A4hlt jene Zeilen aus, bei welchen derzeit kein Preis definiert ist= , bei denen die Zelle A_PREIS also leer ist. Beachten Sie, da=C3=9F eine Zelle mit dem Wert 0 nicht leer is= t, sondern den Wert 0 enth=C3=A4lt. Ebenso ist bei Zellen mit Text die Belegung mit einer leeren Zeichenfolg= e (A_NAME =3D "" bzw. '') verschieden von der Zuweisung A_NAME =3D NULL bzw. der Abfrage A_NAME IS NULL.
  4. WHERE A.A_NAME =3D 'Oberhemd' And=
     A.A_PREIS < 40.00
    Dies w=C3=A4hlt nur jene Zeilen aus, bei denen sowohl der Wert in A_NAME= gleich 'Oberhemd' und der Wert in A_PREIS kleiner als 40.00 ist. Es wird nur die Zeile mit A_NR =3D 12 = ausgew=C3=A4hlt.
  5. WHERE A.A_NAME =3D 'Oberhemd' Or =
    A.A_PREIS > 40.00
    Dies w=C3=A4hlt jene Zeilen aus, bei denen der Wert in A_NAME gleich 'Ob= erhemd' oder der Wert in A_PREIS gr=C3=B6=C3=9Fer als 40.00 ist. Die einzigste Zeile, die eine= n Preis < 40.00 hat, beschreibt ein 'Oberhemd', so da=C3=9F von dieser Abfrage alle vier Zeilen zur=C3=BCckg= egeben werden.
  6. WHERE A.A_PREIS BETWEEN 39.8 AND =
    100.00
    Listet die beiden Zeilen auf, deren Preis zwischen 39.8 und 100.00 liegt= . Die Randwerte werden mitgez=C3=A4hlt, deshalb ist die Zeile A_NR =3D 12 im Ergebnis enthalten. Beachten Sie, d= a=C3=9F das AND zum BETWEEN geh=C3=B6rt und hier keine logische Bedeutung hat.
  7. WHERE 39.8 <=3D A.A_PREIS And =
    A.A_PREIS <=3D 100
    Diese Version ist gleichwertig zur vorherigen Version.
  8. WHERE A.A_NAME IN ('Hose', 'Mante=
    l', 'Str=C3=BCmpfe')
    Vergleicht den Wert von A_NAME mit jedem der in der Klammer angegebenen = Werten. Stimmt er mit einem dieser =C3=BCberein, so wird die betreffende Zeile ausgegeben. Der Ausdruck ist= gleichwertig zu
    WHERE A.A_NAME =3D 'Hose' OR
    	A.A_NAME =3D 'Mantel' OR
    	A.A_NAME =3D 'Str=C3=BCmpfe'
    Rechts = kann, wie hier, eine Liste von Konstanten, berechneten Werten oder eine Unterabfrage notiert werden. Die Unterabfr= age mu=C3=9F eine Spalte zur=C3=BCckliefern.
  9. WHERE 0 =3D 1
    oder
    WHERE FALSE
    Dieser Ausdruck liefert immer False zur=C3=BCck, es werden also keine Ze= ilen ausgew=C3=A4hlt. Dies kann verwendet werden, falls nur die Spaltennamen gew=C3=BCnscht sind. Analog liefert 0= =3D 0 oder TRUE alle Zeilen zur=C3=BCck, so da=C3=9F eine solche WHERE-Klausel redundant ist.
  10. Textvergleiche mit LIKE
    SELECT V.* FROM VERTRETER
    WHERE V.V_NAME LIKE 'Me_er, Franz'
    Mit LIKE k=C3=B6nnen Zellen gegen Textmuster gepr=C3=BCft werden, ohne d= a=C3=9F eine vollst=C3=A4ndige =C3=9Cbereinstimmung notwendig ist. Der Unterstrich (_) fungiert als Platzhalter f=C3=BCr ein= Zeichen, so da=C3=9F der obige Ausdruck sowohl 'Meyer, Franz' als auch 'Meier, Franz' findet.
    WHERE A.V_NAME LIKE 'Me%'
    Das Prozentzeichen (%) schlie=C3=9Ft 0 bis mehrere Zeichen ein, so da=C3= =9F aus der Beispieldatenbank sowohl 'Meier, Franz' als auch 'Meyer, Emil' gefunden wird.
  11. Suche nach den Sonderzeichen '_' und '%': Wenn Sie nach diesen Sonde= rzeichen selbst suchen m=C3=B6chten, dann setzen Sie diese in eckige Klammern ([]). Damit wird die eckige Kla= mmer selbst zum Sonderzeichen, so da=C3=9F auch eine Suche nach einer eckigen Klammer den Einschlu=C3=9F erfordert. Ansonsten erlau= ben eckige Klammern das Angeben eines Bereiches. Beispiel:
    WHERE <Spaltenname> LIKE '%Tulpen[_]und[_]Zwiebeln%'
    findet 'Hier gibt es Tulpen_und_Zwiebeln', nicht jedoch 'Hier gibt es Tu= lpen-und-Zwiebeln'. Entfernt man die Eckklammern, werden beide Eintr=C3=A4ge ausgegeben.
    WHERE <Spaltenname> LIKE 'Mayer [5-7]'
    WHERE <Spaltenname> LIKE 'Mayer [567]'
    findet 'Mayer 5', 'May= er 6', 'Mayer 7', nicht jedoch 'Mayer 8'
    WHERE <Spaltenname> LIKE 'Mayer [[]5]'
    findet 'Mayer [5]= '
  12. Mit Exists pr=C3=BCfen, ob eine Unterabfrage Werte enth=C3=A4lt:
    SELECT A.A_NR
    FROM ARTIKEL As A
    WHERE EXISTS
    	(SELECT B.UMSATZ_NR
    	FROM UMSATZ As B
    	WHERE B.A_NR =3D A.A_NR)
    
    Diese Abfrage liefert jene Artikel einmal (!) zur=C3=BCck, f=C3=BC= r die es Eintr=C3=A4ge in der Tabelle 'Umsatz' gibt. Diese Abfrage erzeugt dasselbe Ergebnis wie:
    SELECT DISTINCT A.A_NR
    FROM ARTIKEL As A INNER JOIN UMSATZ As U
    ON A.A_NR =3D U.A_N=
    R
    Nur wird die letztere Abfrage in der Regel teurer sein, da zun=C3=A4chst= alle passenden Zeilen gesucht und mehrfache Eintr=C3=A4ge anschlie=C3=9F= end mit DISTINCT entfernt werden. EXISTS bricht dagegen ab, falls bereits ei= ne einzige Zeile gefunden wurde.

Bemerkungen

  • Zur Suche nach ganzen Zahlen werden diese direkt notiert. F=C3=BCr Z= ahlen mit Nachkommastellen ist der Punkt das g=C3=BCltige Trennzeichen (A_Preis > 99.99). Textkonstanten werd= en in einfache Hochkommata (') gesetzt. Soll nach einem einfachen Hochkomma gesucht werden, so gen=C3=BCgt es, = dieses zu verdoppeln:
    WHERE V.V_Name =3D 'O''Neil'
    findet
    O'Neil
  • Grunds=C3=A4tzlich gilt, da=C3=9F jeder Vergleich mit einem Operator= (NOT, =3D, <, >, IN) auf NULL ausgewertet wird, falls einer der beiden Ausdr=C3=BCcke NULL ist. Damit= liefert auch die Verneinung eines solchen Ausdrucks NULL. Damit wird eine gesamte Menge von Zeilen = mit NULL-Zellen nicht vollst=C3=A4ndig durch einen Vergleich und dessen Verneinung ausgesch=C3= =B6pft.
  • WHERE A.A_PREIS =3D 10.00
    ...
    UNION
    ...
    WHERE A.A_PREIS <> 10.00
    liefer= t alle Zeilen mit Preis, jedoch nicht jene Artikel, f=C3=BCr die kein Preis definiert ist, bei welchen die A_PREIS-Zelle lee= r ist. Denn bei einer leeren Zelle kann keine der obigen Bedingungen positiv gepr=C3=BCft werden.
  • Ein Beispiel mit einem logischen Operator:
    SELECT A.* FROM ARTIKEL AS A
    WHERE A.A_NAME =3D 'Hose'
    
    UNION
    
    SELECT A.* FROM ARTIKEL AS A
    WHERE NOT A.A_NAME =3D 'Hose'
    Im Rahmen von jedem Logik-Kurs wird Ihnen mitgeteilt, da=C3=9F diese Abf= rage s=C3=A4mtliche Zeilen liefert, hier also 4 Zeilen ausgibt. L=C3=B6schen Sie anschlie=C3=9Fend testweise= eine Zelle der Spalte A_NAME, etwa eine Zelle mit dem Wert 'Oberhemd'. L=C3=B6schen Sie nur die Zelle,= nicht die Zeile. F=C3=BChren Sie anschlie=C3=9Fend die Abfrage erneut aus, so werden Sie = nur drei Ergebniszeilen erhalten.
  • Operatorreihenfolge: Ein Vergleich mit =3D bindet am st=C3=A4rksten,= so da=C3=9F ein Ausdruck
    A_NAME =3D 11 Or A_PREIS > 100
    wie gew=C3=BCnscht interpretiert wird:
    (A_NAME =3D 11) Or (A_PREIS > 100)
    Verwenden Sie verschiedene logische Operatoren in einem WHERE-Ausdruck, = so nutzen Sie am besten Klammern. Dies ist f=C3=BCr jeden, der den Code sp=C3=A4ter bearbeitet und die gen= aue Operator-Reihenfolge nicht wei=C3=9F, die sicherste L=C3=B6sung, damit sich nicht unbeabsichtigte Fehler einschlei= chen.

    Betrachten Sie den folgenden Ausdruck:
    WHERE A.A_NR BETWEEN 11 AND 10 OR 15<=
    /pre>
    Der erste Ausdruck ist f=C3=BCr A_NR =3D 11 zumindest f=C3=BCr Access in=
     Sql-Interaktiv-lernen erf=C3=BCllt, so da=C3=9F mit
    einem Datensatz zu rechnen w=C3=A4re. Da AND st=C3=A4rker bindet als OR =
    und AND zu BETWEEN geh=C3=B6rt, wird der Ausdruck
    tats=C3=A4chlich jedoch so ausgewertet:
    
    WHERE (A.A_NR BETWEEN 11 AND 10) OR (=
    15)
    Der Ausdruck (15) ist verschieden von 0, damit in den meisten Datenbank-= Systemen wahr. Also handelt es sich um eine Konstante, so da=C3=9F alle Zeilen ausgegeben werden.
  • Platzhaltersuche bei Access: Werden in Access =C3=BCber die gew=C3=B6= hnliche Programmierumgebung Abfragen erstellt, so m=C3=BCssen entgegen den oben genannten Konventionen f=C3=BCr die Suche nach einem e= inzelnen Zeichen das '?', f=C3=BCr die Suche nach mehreren Zeichen '*' verwendet werden. In diesem Fall wird das DAO-Modell (Data Access Ob= jects) genutzt, welches einen Non-Standard - Sql-Dialekt implementiert. Wird dagegen auf eine Access-Datenbank =C3=BCber eine der Programmiersch= nittstellen ADO oder .NET zugegriffen, so sind die Standard-Zeichen '_' und '%' zu verwenden. Das Sql-Interaktiv-lernen verwendet .NET-Zugri= ffstechniken, so da=C3=9F hier der Standard einzusetzen ist.
  • Anstatt eines Ausdrucks der Form
    <Spaltenname> =3D <Wert>
    kann rechts auch entweder ein anderer Spaltenname oder eine eigenst=C3=A4= ndige in Klammern stehende Select-Abfrage angegeben werden. Diese mu=C3=9F genau eine Zelle zur=C3=BC= ckliefern. Ebenso kann bei einem Ausdruck der Form
    <Spaltenname> IN (<Unterabfrage mit einer Spalte>)
    eine Unterabfrage eingesetzt werden, die genau eine Spalte zur=C3=BCckli=
    efert. Beispiele hierzu finden
    Sie im Abschnitt zu Unterabfragen.
  • EXISTS kann beim Sql-Server ressourcenschonend bsp. am Anfang eines = Scripts dazu verwendet werden, um zu pr=C3=BCfen, ob ein Objekt existiert, um es gegebenenfalls zu l=C3=B6schen:
    If (Exists
    	(Select A.Table_Name
    	From Information_Schema.Tables As A
    	Where A.Table_Name =3D 'Artikel')
        )
        Drop Table Artikel
    Diese Technik ist jedem Group By bzw. Count(*) vorzuziehen, etwa dem fol= genden Code:
    If ((Select Count(*) From Information_Schema.Tables As A
    	Where A.Table_Name =3D 'Artikel') > 0)
        Drop Table Artikel

TOP

JOIN - Normalisierte Tabellen f=C3=BCr eine Abfra= ge wieder zusammenfassen

Vorbemerkung

Aufgabe der JOIN-Verkn=C3=BCpfung: Die Daten wurden normalisiert, also a= uf verschiedene Tabellen aufgeteilt. So sind die Daten zu einer Bestellung (Artikel, Datum, Menge, Vertreter)= in der Beispiel-Datenbank nicht in einer Tabelle abgelegt, sondern wurden auf drei Tabellen verteilt: Ar= tikel und Vertreter umfassen die Stammdaten, die Tabelle Umsatz enth=C3=A4lt die eigentlichen Bewegungsda= ten. Pro Zeile wird lediglich ein Verweis auf die zur einzelnen Bestellung geh=C3=B6renden Datens=C3=A4tze= abgelegt. Sollen alle Daten einer Bestellung als ein Datensatz ausgegeben werden, so m=C3=BCssen die Eintr= =C3=A4ge aus den verschiedenen Tabellen einander zugeordnet werden. Dies leistet die JOIN-Verkn=C3=BCpfung. Ein = JOIN f=C3=BCgt zwei Tabellen zu einer neuen, virtuellen Tabelle zusammen, die anschlie=C3=9Fend mit einem weit= eren JOIN sowie der n=C3=A4chsten Tabelle verkn=C3=BCpft werden kann.
Folglich gen=C3=BCgt es, einen JOIN zwischen zwei Tabellen zu behandeln.=

Syntax

  • Komma-Version:
    FROM <Tabelle oder Abfrage>, <Tabelle oder Abfrage>
  • Einfachste Form des INNER JOIN
    FROM <Tabelle oder Abfrage> INNER JOIN <Tabelle oder Abfra=
    ge>
    ON <Spalte1> OPERATOR <Spalte2>
  • Mehrfache Verkn=C3=BCpfung:
    FROM <Tabelle oder Abfrage> INNER JOIN <Tabelle oder Abfra=
    ge>
    ON <Spalte1> OPERATOR <Spalte2>
    	AND
    <Spalte3> OPERATOR <Spalte4>
  • Statt INNER kann auch eines der folgenden Schl=C3=BCsselw=C3=B6rter verw= endet werden:
    LEFT, RIGHT, OUTER
  • Statt dem AND-Operator kann auch OR verwendet werden, ferner k=C3=B6nnen= mehr als zwei Vergleichsausdr=C3=BCcke angegeben sowie AND und OR kombiniert werden.
  • Eine Tabelle kann auch zweimal angegeben werden, man spricht von ein= er Selbstverkn=C3=BCpfung, da Zeilen der Tabelle zu anderen Zeilen der Tabelle in Beziehung gesetzt= werden. Abgesehen von der Komma-Version ist mindestens ein Alias-Name f=C3=BCr eine Tabelle Pflicht, um die Spalten eindeutig z= u beschreiben.

Beispiele

  1. SELECT A.*, U.*
    FROM ARTIKEL As A, =
    UMSATZ As U
    Diese Komma-Version kombiniert jede Zeile der Tabelle ARTIKEL mit jeder = Zeile der Tabelle UMSATZ und gibt das Ergebnis aus 4 * 9 =3D 36 Zeilen vollst=C3=A4ndig aus. Vergleic= ht man die beiden Spalten A.A_NR und U.A_NR, so f=C3=A4llt auf, da=C3=9F den Ums=C3=A4tzen in den = meisten F=C3=A4llen Artikel zugeordnet sind, welche von dem im Umsatz erw=C3=A4hnten Artikel verschieden sind. Diese (36 - 9= ) =3D 27 Ergebnisse sind also sinnlos, Durch die in der ON-Klausel festgelegte Filterbedingung in der folgenden= JOIN-Klausel werden diese Datens=C3=A4tze entfernt.
  2. SELECT A.A_NR,
    	A.A_NAME,
    	A.A_PREIS,
    	U.DATUM,
    	U.A_STUECK,
    	A.A_PREIS * U.A_ST=
    UECK AS Preis
    
    FROM UMSATZ AS U INNER JOIN ARTIKEL AS A
    ON U.A_NR =3D A.A_N=
    R
    Dies ist die einfachste und am h=C3=A4ufigsten genutzte Form des JOIN. D= ie Spalte A.A_NR ist gleichzeitig der Prim=C3=A4rschl=C3=BCssel der Tabelle ARTIKEL, zu einem Artikel kann es mehrere Bestellungen, also Zeilen in der Tabelle UMSATZ geben. Aus der oben angegebenen Komma-Version werden all jene Zeilen ent= fernt, bei welchen die beiden Spalten A.A_NR und U.A_NR nicht =C3=BCbereinstimmen.

    Ersetzt man in diesem Ausdruck den INNER JOIN durch die Komma-Version, s= o wird deutlich: Hier ist die Komma-Version unsinnig. Denn eine Mengenangabe, die sich auf einen Artik= el bezieht, wird kombiniert mit dem Preis eines anderen Artikels.
  3. SELECT A.A_NR,
    	A.A_NAME,
    	A.A_PREIS,
    	V.V_NR,
    	V.V_NAME,
    	U.DATUM,
    	A.A_PREIS * U.A_ST=
    UECK AS Preis
    
    FROM (ARTIKEL AS A INNER JOIN UMSATZ AS U
    ON A.A_NR =3D U.A_N=
    R) INNER JOIN VERTRETER AS V
    ON U.V_NR =3D V.V_N=
    R
    Dies ist die Version f=C3=BCr die Verkn=C3=BCpfung von drei Tabellen. In= der ersten Klammer werden zun=C3=A4chst jene neun Ergebniszeilen gefiltert, bei denen der Umsatz zum Artikel geh=C3=B6rt. = Zu dieser neuen Tabelle werden jene Zeilen hinzugenommen, bei denen die Vertreter-Id =C3=BCbereinstimmt. Die= Komma-Version w=C3=BCrde (4 * 9) * 3 =3D 108 Zeilen liefern, der doppelte Join liefert korrekt die neun Zeilen aus de= r Tabelle UMSATZ, erg=C3=A4nzt um die Informationen aus den beiden anderen Tabellen.
    Manche Datenbank-Systeme, etwa Access, fordern, da=C3=9F bei einem solch= en Ausdruck ein Join geklammert wird. Beim MS-SqlServer kann auf die Klammern verzichtet werden.
  4. Ausdr=C3=BCcke mit Operatoren werden beim INNER JOIN nur dann ausgewerte= t, wenn die einzelnen Ausdr=C3=BCcke nicht Null sind. Ist ein Ausdruck ein Spaltenname, so werden bsp. bei einer Pr= =C3=BCfung auf Gleichheit alle Zeilen ignoriert, in welchen die zugeh=C3=B6rige Zelle leer ist. Damit liefert = der INNER JOIN immer nur Informationen =C3=BCber tats=C3=A4chliche Vorg=C3=A4nge, etwa =C3=BCber Verk=C3=A4ufe = von Artikeln. Es sind damit jedoch zun=C3=A4chst keine Informationen =C3=BCber nicht verkaufte Artikel ermittelbar, der normale JOIN e= rzeugt keine Informationen zu einem Nicht-Ereignis. Sollen hier=C3=BCber Aussagen getroffen= werden, gelingt dies mit LEFT bzw. RIGHT JOIN:
    SELECT A.A_NR,
    	U.DATUM
    FROM ARTIKEL AS A LEFT JOIN UMSATZ AS U
    ON A.A_NR =3D U.A_NR
    F=C3=BCgen Sie Ihrer Tabelle ARTIKEL einen neuen Artikel hinzu. Als Befe= hl:
    INSERT INTO ARTIKEL(A_NR, A_NAME, A_PREIS)
    	VALUES (25, 'Mantel', 149.00)
    Da es f=C3=BCr diesen Artikel keine passende Zeile in der Tabelle UMSATZ= gibt, wird dieser Artikel bei einer INNER-JOIN-Verkn=C3=BCpfung ignoriert. Der obige LEFT JOIN gibt zun=C3=A4= chst dasselbe wie ein INNER JOIN aus. Zus=C3=A4tzlich f=C3=BCgt er alle Datens=C3=A4tze aus der links (left) s= tehenden Tabelle hinzu, die im Ergebnis bislang noch fehlen. Werden Spalten aus der rechts stehenden Tabelle mit ausgege= ben, so werden deren Werte als NULL-Werte ausgegeben. In Kombination mit einer WHERE-Abfrage lassen sic= h die niemals verkauften Artikel ermitteln:
    SELECT A.A_NR,
    	A.A_NAME
    FROM ARTIKEL AS A LEFT JOIN UMSATZ AS U
    ON A.A_NR =3D U.A_NR
    WHERE U.UMSATZ_NR IS NULL
    Beachten Sie, da=C3=9F Sie mit dieser Abfrage nicht ermitteln, welcher A= rtikel blo=C3=9F an bestimmten Tagen nicht verkauft wurde. Wurde ein Artikel ein einziges Mal verkauft, so erschein= t er nicht mehr in dieser Liste.
  5. Ermittlung der an einzelnen Tagen nicht verkauften Artikel. Betracht= en Sie zun=C3=A4chst die folgende Abfrage:
    SELECT C.DATUM, D.A_NR
    FROM
    	(SELECT Distinct A.DATUM
    	FROM UMSATZ As A
    	Where A.DATUM Is Not Null) As C,
    
    	(SELECT B.A_NR
    	FROM ARTIKEL As B) As D
    Die beiden inneren Abfragen liefern Ihnen eine Liste aller Datumsangaben= , an welchen etwas verkauft wurde sowie eine Liste aller Artikel-Nummern. Beide Tabellen werden durch die = Komma-Version kombiniert, so da=C3=9F die Ergebnistabelle jede Kombination aus Datum und Artikel umfa= =C3=9Ft. Kombinieren Sie diese neue, nur tempor=C3=A4r existierende Tabelle per LEFT JOIN mit den tats=C3=A4chlic= hen Ums=C3=A4tzen:
    SELECT E.DATUM, E.A_NR,
    	F.DATUM, F.A_NR
    
    FROM
    
    	(SELECT C.DATUM, D.A_NR
    	FROM
    		(SELECT Distinct A.DATUM
    		FROM UMSATZ As A
    		Where A.DATUM Is Not Null) As C,
    
    		(SELECT B.A_NR
    		FROM ARTIKEL As B) As D) As E
    
    LEFT JOIN UMSATZ AS F
    
    ON E.DATUM =3D F.DATUM AND E.A_NR =3D F.A_NR
    Die Ausgabe ergibt, da=C3=9F am 25.6 bei den Artikeln 12 und 13 die Spal= ten F.DATUM und F.A_NR leer sind, da f=C3=BCr beide Artikel an diesem Tag kein Umsatz vorliegt. Entfernen Sie= F.DATUM und F.A_NR in der Liste der Ausgabespalten und erg=C3=A4nzen Sie die Abfrage um die folgende Bedingu= ng:
    WHERE F.DATUM IS NULL
    Dann liefert Ihnen diese Abfrage s=C3=A4mtliche Kombinationen von Tagen = mit den an diesen Tagen nicht verkauften Artikeln.
  6. Selbstverkn=C3=BCpfung einer Tabelle:
    SELECT DISTINCT U1.DATUM, U1.A_NR
    FROM UMSATZ As U1 INNER JOIN UMSATZ As U2
    On (U1.DATUM =3D U2.DATUM) And
    	(U1.A_NR =3D U2.A_=
    NR) And
    	(U1.A_STUECK <> U2.A_STUECK)
    
    DatumA_NR
    24.06.199912
    24.06.199913

    Diese Abfrage ordnet zun=C3=A4chst all jene Zeilen paarweise einander zu= , die sich auf dasselbe Datum und denselben Artikel beziehen. Da als dritte Bedingung die Verschiedenartigkeit der A= _STUECK-Spalte gepr=C3=BCft wird, werden zun=C3=A4chst alle Kombinationen aus Datum und Artikel entfernt, die sich auf dieselbe Zeil= e beziehen. Dasselbe w=C3=BCrde jedoch die Pr=C3=BCfung U1.UMSATZ_NR <> U1.UMSATZ_NR erf=C3=BCllen. Die tats=C3=A4chlich v= erwendete Pr=C3=BCfung entfernt jedoch zus=C3=A4tzlich alle Kombinatione= n aus Datum und Artikel, bei welchen der Artikel mehrfach mit derselben St=C3=BC= ckzahl verkauft worden ist, nur jene Kombinationen werden ausgegeben, bei welchen der Artikel an einem Tag zu mindestens zw= ei verschiedenen St=C3=BCckzahlen verkauft worden ist. Da jede diese Bedingungen erf=C3=BCllende Kombination von Zeilen auch erf=C3= =BCllt ist, wenn die beiden Zeilen vertauscht sind, kann man die Bedingung <> auch ersetzen durch < und mit DISTINCT alle weiter= en Zeilen dieser Kombination entfernen.

    Sollen dagegen jene Kombinationen aus Tagen und Artikeln bestimmt werden= , f=C3=BCr die an einem Tag nur eine St=C3=BCckzahl, jedoch mehrere Verk=C3=A4ufe durchgef=C3=BChrt wurden, so gen=C3=BCgt es nicht, nur den= Unterschieds-Operator durch den Gleichheits-Operator zu ersetzen. Denn in diesem Fall werden auch jene Tage/Artikel ausgegeben, die genau einma= l verkauft worden sind. Wird diese Abfrage erg=C3=A4nzt um die Bedingung U1.Umsatz_Nr <> U2.Umsatz_Nr, so wird nur der Artike= l 11 am 25.06.1999 ausgegeben, der zweimal zwanzigmal verkauft wurde. Insgesamt:
    SELECT DISTINCT U1.DATUM, U1.A_NR
    FROM UMSATZ As U1 INNER JOIN UMSATZ As U2
    On (U1.DATUM =3D U2.DATUM) And
    	(U1.A_NR =3D U2.A_=
    NR) And
    	(U1.A_STUECK =3D U2.A_STUECK) And
    	(U1.UMSATZ_NR <> U2.UMSATZ_NR)
    

Bemerkungen

  1. Falls Sie Tabellen verkn=C3=BCpfen, so sollten Sie im Regelfall eine= der JOIN-Methoden verwenden. Insbesondere ist die 'alte' Technik, welche die Klammerversion nutzt und die ON-Klausel in d= ie WHERE-Bedingung verschiebt, zu vermeiden. Vergleichen Sie die beiden folgenden Darstellungen:
    SELECT A.*, U.*
    FROM ARTIKEL As A, =
    UMSATZ As U
    WHERE A.A_NR =3D U.=
    A_NR
    	AND A.A_NR < 13
    mit
    SELECT A.*, U.*
    FROM ARTIKEL As A INNER JOIN UMSATZ As U
    On A.A_NR =3D U.A_N=
    R
    WHERE A.A_NR < 13
    Bei der ersten, nicht zu verwendenden Version ist die Bedingung zur Verk= n=C3=BCpfung der beiden Tabellen gemischt mit der Bedingung, welche wenige Zeilen ausw=C3=A4hlt. Die zweite Version trennt dagegen di= e Verkn=C3=BCpfung der Tabellen von der Reduktion der Spalten. In der Regel werden zun=C3=A4chst alle WHERE-Bedingungen ausgef=C3=BChrt= , welche die Zahl der Zeilen reduzieren, erst =C3=BCber die verbleibende= Restmenge der Zeilen wird der JOIN gebildet.
  2. LEFT und RIGHT Join sind zueinander symmetrisch. Die beiden folgende= n Anweisungen zur Ermittlung der niemals verkauften Artikel sollten deshalb denselben Ablaufplan erzeugen (f=C3=BC= gen Sie wie oben einen niemals verkauften Artikel hinzu):
    SELECT A.*
    FROM ARTIKEL As A LEFT JOIN UMSATZ As U
    ON A.A_NR =3D U.A_N=
    R
    WHERE U.A_NR Is null
    sowie
    SELECT A.*
    FROM UMSATZ As U RIGHT JOIN ARTIKEL As A
    ON U.A_NR =3D A.A_N=
    R
    WHERE U.A_NR Is null
    OUTER JOIN kombiniert LEFT/RIGHT und akzeptiert sowohl =C3=BCbereinstimm= ende Zeilen als auch Nullwerte beider Tabellen.
  3. Left- bzw. Right-Join-Konstrukte sind zwingend, falls eine Tabelle e= ine Verkn=C3=BCpfung zu einer optionalen Randtabelle enth=C3=A4lt. Ein klassisches Beispiel ordnet Personen Titel zu, die Titel (Dr., Dr.me= d, Prof.Dr.) sind in einer Randtabelle gespeichert, die Personentabelle enth=C3=A4lt eine Spalte mit der ID der Titel-Tabelle. G= ibt es Personen ohne Titel, so kann entweder in der Randtabelle ein Eintrag ohne Text erzeugt und ein INNER JOIN zur Verkn=C3=BCpfung ge= nutzt werden oder es fehlt ein solcher Eintrag. Damit ist die entsprechende Zelle in der Personentabelle leer, so da=C3=9F ein Lef= t/Right-Join von der Haupt- auf die Randtabelle gebildet werden mu=C3=9F, falls alle Personen gefunden werden sollen.

    Ein Beispiel f=C3=BCr den MS-SqlServer:
    SELECT A.Nachname + ', ' +
    	A.Vorname + CoalEsce(' ' + B.Titel, '')
    	As Name
    From Personen As A Left Join PersonenTitel As B
    On A.TitelId =3D B.TitelId
    CoalEsce liefert den ersten Ausdruck in = der Liste, der von Null verschieden ist. Existiert ein Titel, so wird dieser mit einem Leerzeichen als Trenner ausgegeben, = ansonsten wird ein Leerstring zur bisherigen Ausgabe aus Nachname, Komma und Vorname hinzugef=C3=BCgt.

TOP

Mit Aggregat-Funktionen und GROUP BY Daten auswer= ten und aggregieren

Vorbemerkung

  • Mit SELECT, FROM und WHERE erhalten Sie einzelne Zellen der gew=C3=A4hlt= en Tabellen zur=C3=BCck. Es wird jedoch keine Aggregation des Ergebnisses durchgef=C3=BChrt, die Daten werden ni= cht zusammengefa=C3=9Ft. Liefert Ihre JOIN-Anweisung 50.000 Zeilen und entfernt die WHERE-Klausel hiervon 30.0= 00, so enth=C3=A4lt Ihre Ergebnistabelle 20.000 Zeilen. Alle Techniken mit Aggregatfunktionen fassen dagegen mehr= ere Zeilen zu einer Ergebniszeile zusammen und geben nur noch diese aus.
  • Eine solche Aggregation / Zusammenfassung / Ermittlung von Kennziffe= rn / Konsolidierung kann sich =C3=BCber die gesamte Tabelle erstrecken. In diesem Fall werden nur= Aggregatfunktionen, jedoch keine GROUP BY - Klausel ben=C3=B6tigt. Oder die Kennziffern sollen aufg= esplittet nach Artikeln, Verk=C3=A4ufern, Datum, Regionen oder anderen Kriterien bestimmt werden. In diesem Fall w= ird die Tabelle zun=C3=A4chst gem=C3=A4=C3=9F dieser Kriterien mit der GROUP BY - Klausel in Teiltabellen zerlegt und = f=C3=BCr jede Teiltabelle die Kennziffern berechnet. Damit liegt pro Teiltabelle eine Ergebniszeile vor, eventuell sind die konkreten Wer= te, die =C3=BCber die Zugeh=C3=B6rigkeit zu dieser Teiltabelle entscheiden, ebenfalls mit ausgegeben. Aus all die= sen Einzelzeilen wird das Gesamtergebnis zusammengef=C3=BCgt.
  • Bildlich gesprochen: Die bisherigen Techniken liefern Ihnen einen St= apel von Zeilen zur=C3=BCck. Verwenden Sie eine Aggregat-Funktion, so wird der Zeilenstapel auf eine = Zelle, einen einzigen Wert gestaucht. Verwenden Sie mehrere Aggregat-Funktionen, so wird der Zeilen= stapel auf mehrere Zellen komprimiert, diese werden als eine Zeile ausgegeben. Gruppieren Sie das Ergebnis zus=C3= =A4tzlich mit GROUP BY, so wird der Gesamtstapel zun=C3=A4chst gem=C3=A4= =C3=9F der GROUP BY - Kriterien in Teilstapel zerlegt, =C3=BCber jeden dieser T= eilstapel wird aggregiert, dieser also in einer Zeile zusammengefa=C3=9Ft, so da=C3=9F am Ende alle Teilstapel-= Ergebniszeilen zum Gesamtergebnis vereinigt werden.
  • Sollen Ergebnisse, die mittels der Aggregatfunktionen ermittelt wurd= en, als zus=C3=A4tzliches Filterkriterium herangezogen werden, so k=C3=B6nnen solche Ausdr=C3=BCck= e in der HAVING-Klausel angegeben werden.

Syntax

  • R=C3=BCckgabe einer einzelnen Zelle - einfache Aggregation
    SELECT <Aggregatfunktion(Spaltenname) As [Spaltenname]>
    FROM ...
    [WHERE ...]
  • R=C3=BCckgabe einer Zeile mit mehreren Zellen - mehrere Kennziffern = gleichzeitig ermitteln
    SELECT <Aggregatfunktion-1(Spaltenname-A1) As Ausgabename-1,>=
    
    	<Aggregatfunktion-2(Spaltenname-A2) As Ausgabename-2,>
    	...
    	<Aggregatfunktion-n(Spaltenname-An) As Ausgabename-n>
    FROM ...
    [WHERE ...]
    [HAVING ...]
  • Gruppierung in Teilgruppen, Aggregation =C3=BCber die Teilgruppen un= d Zusammenfassen der Einzelergebnisse
    SELECT <Aggregatfunktion-1(Spaltenname-A1) As Ausgabename-1,>=
    
    	<Aggregatfunktion-2(Spaltenname-A2) As Ausgabename-2,>
    	...
    	<Aggregatfunktion-n(Spaltenname-An) As Ausgabename-n>,
    	Spaltenname-1,
    	Spaltenname-2,
    	...
    	Spaltenname-m
    
    FROM ...
    [WHERE ...]
    GROUP BY Spaltenname-1,
    	Spaltenname-2,
    	...
    	Spaltenname-m
    [HAVING ...]
    

Beispiele

  1. SELECT COUNT(A.DATUM) As [Zahl-der-Um=
    s=C3=A4tze]
    FROM UMSATZ As A
    Beachten Sie, da=C3=9F Ihnen diese Abfrage 9 als Ergebnis zur=C3=BCcklie= fert, also die Zahl der nichtleeren Zellen. F=C3=BCgen Sie einen weiteren Datensatz ein und lassen bei diese= m das Feld DATUM leer, so erhalten Sie mit der obigen Abfrage weiterhin das Ergebnis 9. Es wird nicht 2 (die Zahl der verschiedenen Datumsangaben) ausgegeben. S= ind alle Zellen einer Tabelle belegt, so ist es f=C3=BCr diese Abfrage mit COUNT unerheblich, = welche Zelle Sie verwenden.
  2. SELECT A.DATUM, COUNT(A.DATUM) As [Zahl-der-Ums=C3=A4tze-pro-Tag]
    FROM UMSATZ As A
    GROUP BY A.DATUM
    Sie erhalten als Ergebnis zwei Zeilen, f=C3=BCr jede der unterschiedlich= en Datumsangaben eine Zeile. Jede Zeile enth=C3=A4lt die zus=C3=A4tzliche Zelle 'Zahl-der-Ums=C3=A4tze-pro-Tag' = mit den Werten 6 f=C3=BCr den 24.06 und 3 f=C3=BCr den 25.06.99. Verzichten Sie auf die Ausgabespalte A.DATUM, so k=C3=B6nnen Sie die bei= den Zellen mit den Werten 6 und 3 nicht mehr interpretieren.
  3. SELECT MAX(A.A_PREIS) As [teuerst=
    er-Artikel]
    FROM ARTIKEL As A
    Dies liefert Ihnen den Preis des teuersten Artikels (360.00). Beachten S= ie, da=C3=9F Sie mit dieser Abfrage noch nicht den Namen oder die Details dieses Artikels erfahren. Dies gelingt nur, wenn Sie da= s obige Ergebnis selbst als Kriterium in einer Where-Abfrage verwenden. N=C3=A4heres finden Sie im A= bschnitt =C3=BCber Unterabfragen. Hier eine M=C3=B6glichkeit:
    SELECT B.*
    FROM ARTIKEL As B
    WHERE B.A_PREIS =3D (SELECT MAX(A.A_PREIS)=
     As [teuerster-Artikel]
    	FROM ARTIKEL As A)
    Ergebnis:
    A_NRA_NAMEA_PREIS
    22Mantel360.00
  4. SELECT SUM(A.A_PREIS * B.A_STUECK) As [Gesamtumsatz]
    FROM ARTIKEL As A INNER JOIN UMSATZ As B
    ON A.A_NR =3D B.A_N=
    R
    
    Diese Abfrage kombiniert jede Umsatz-Zeile mit der zu ihr geh=C3=B6= renden Artikel-Zeile. Damit sind die Spalten A_PREIS und A_STUECK bekannt und k=C3=B6nnen miteinander mul= tipliziert werden. Ohne die Aggregatfunktion SUM w=C3=BCrden neun Zeilen mit dem tats=C3=A4chlichen Umsatz dieser ein= zelnen Verkaufshandlung ausgegeben. So wird =C3=BCber all diese Einzelergebnisse summiert und der Gesamtumsatz von 2= 7.472,00 ermittelt.
  5. SELECT A.A_NR, SUM(A.A_PREIS * B.A_STUECK) As [Um=
    satz-dieses-Artikels]
    FROM ARTIKEL As A INNER JOIN UMSATZ As B
    ON A.A_NR =3D B.A_N=
    R
    GROUP BY A.A_NR
    Ergebnis:
    A_NRUmsatz-dieses-Artikels
    114.862,00
    121.990,00
    134.420,00
    2216.200,00

    Diese Aggregation zerlegt den Gesamtstapel der neun Ums=C3=A4tze zun=C3=A4= chst in Teilstapel anhand der Artikelnummern. F=C3=BCr jeden Teilstapel wird multipliziert und die Sum= me ermittelt. Das Ergebnis wird, erg=C3=A4nzt um die Information, zu welchem Artikel die Summation geh=C3= =B6rt, ausgegeben.
  6. SELECT B.DATUM,
    	MAX(A.A_PREIS * B.=
    A_STUECK) As [Max-Tages-Einzelumsatz]
    FROM ARTIKEL As A INNER JOIN UMSATZ As B
    ON A.A_NR =3D B.A_N=
    R
    GROUP BY B.DATUM
    Ergebnis:
    DATUMMax-Tages-Einzelumsatz
    24.06.19993.867,50
    25.06.199912.600,00

    Anstelle der obigen Summation wird das Maximum =C3=BCber alle Einzelums=C3= =A4tze f=C3=BCr jeden Tag ermittelt. Beachten Sie, da=C3=9F Sie auch mit dieser Abfrage nicht ermitteln k=C3=B6nnen, welche= r Artikel f=C3=BCr diesen h=C3=B6chsten Umsatz verantwortlich ist. Denn sobald Sie zur Gruppierung die Artikel-Nummer h= inzunehmen, erhalten Sie f=C3=BCr jede Kombination aus Artikel und Tag eine Zeile, so da=C3=9F das Maximum =C3=BC= ber solche einzeiligen Teilmengen gleich dem Wert in dieser Zelle ist. M=C3=B6chten Sie zus=C3=A4tzlich wissen, w= elcher Artikel f=C3=BCr diesen h=C3=B6chsten Einzelumsatz zust=C3=A4ndig ist, so kombinieren Sie diese Abfrage als JOIN mit einer = direkten Multiplikation:
    SELECT A.DATUM, A.A_NR, A.Einzelumsatz
    
    FROM
    	(SELECT C.DATUM, B.A_NR,
    		B.A_PREIS * C.A_S=
    TUECK As [Einzelumsatz]
    	FROM ARTIKEL As B INNER JOIN UMSATZ As C
    	ON B.A_NR =3D C.A_=
    NR) AS A
    
    INNER JOIN (
    	SELECT Y.DATUM,
    		MAX(X.A_PREIS * Y.A_STUECK) As [Max-Tages-Einzelumsatz]
    	FROM ARTIKEL As X INNER JOIN UMSATZ As Y
    	ON X.A_NR =3D Y.A_=
    NR
    	GROUP BY Y.DATUM) As D
    
    ON (A.DATUM =3D D.D=
    ATUM) AND
    	(A.Einzelumsatz =3D D.[Max-Tages-Einzelumsatz])
    Ergebnis: =
    DATUMA_NREinzelumsatz
    24.06.1999133.867,50
    25.06.19992212.600,00

    Unterst=C3=BCtzt das Datenbanksystem - im Gegensatz zu Access - eine dir= ekte Multiplikation im JOIN-Ausdruck, so k=C3=B6nnen Sie den ersten geklammerten JOIN-Ausdruck herausziehen un= d die Multiplikation direkt in der JOIN-Klausel durchf=C3=BChren.
  7. SELECT B.DATUM, B.A_NR,
    	SUM(A.A_PREIS * B.=
    A_STUECK) As Tagesumsatz
    FROM ARTIKEL As A INNER JOIN UMSATZ As B
    ON A.A_NR =3D B.A_N=
    R
    GROUP BY B.DATUM, B.A_NR
    
    Ergebnis: <= /tr>
    DATUMA_NRTagesumsatz
    24.06.1999113.094,00
    24.06.1999121.990,00
    24.06.1999134.420,00
    24.06.1999223.600,00
    25.06.1999111.768,00
    25.06.19992212.600,00

    Das ist nun die klassische ausdifferenzierte Version: Die tats=C3=A4chli= chen Einzelums=C3=A4tze werden pro Tag und pro Artikel aggregiert, das Ergebnis wird mit den beiden gruppierenden S= palten ausgegeben.
  8. SELECT A.DATUM, A.A_NR, COUNT(*) As [Umsatz-Anzahl]
    FROM UMSATZ As A
    GROUP BY A.DATUM, A.A_NR
    HAVING COUNT(*) > 1
    Ergebnis:
    DATUMA_NRUmsatz-Anzahl
    24.06.1999122
    24.06.1999132
    25.06.1999112

    Ohne HAVING-Klausel w=C3=BCrde diese Abfrage sechs Zeilen zur=C3=BCcklie= fern - vier f=C3=BCr den 24.06, an dem vier Artikel verkauft wurden, 2 f=C3=BCr den 25.06. Die HAVING-Klausel definiert eine= zus=C3=A4tzliche Einschr=C3=A4nkung und beschr=C3=A4nkt die Ausgabe auf jene Artikel, die mindestens zwei Mal verkauft worden si= nd.
  9. SELECT A.A_NR, SUM(A.A_PREIS * B.A_STUECK) As [Um=
    satz-dieses-Artikels]
    FROM ARTIKEL As A INNER JOIN UMSATZ As B
    ON A.A_NR =3D B.A_N=
    R
    GROUP BY A.A_NR
    HAVING SUM(A.A_PREIS * B.A_STUECK) > 10000
    
    Dies ermittelt jene Artikel, mit welchen ein Umsatz von =C3=BCber = 10.000 gemacht wurde. Die SQL-Abfrage ist dieselbe wie unter Beispiel 5, es wurde nur die HAVING-Klausel hinzu= gef=C3=BCgt. Artikel 22 wird ausgegeben.

Aggregatfunktionen

  1. COUNT: Ermittlung der Zeilen bzw. Zellen. Diese Funktion kann in zwe= i verschiedenen Versionen genutzt werden: COUNT(*) gibt die Anzahl aller Zeilen gem=C3=A4=C3=9F de= m GROUP-BY-Abschnitt zur=C3=BCck. COUNT(<Spaltenname>) liefert die Zahl der nichtleeren Zellen in de= r angegebenen Spalte.
  2. MIN(<Spaltenname>) / MAX(<Spaltenname>): Ermittelt das M= inimum / Maximum der angegebenen Spalte.
  3. SUM(<Spaltenname>): Summation =C3=BCber alle Zellwerte
  4. AVG(<Spaltenname>): Mittelwert aller Zellwerte, NULL-Werte wer= den ignoriert.
Dies sind die Funktionen, die jedes Datenbanksystem mit Sql-Schnittstell= e anbieten d=C3=BCrfte. Hinweise f=C3=BCr weitere Funktionen Ihres Systems finden Sie in der zugeh=C3=B6r= igen Dokumentation. Die Aggregatfunktionen mit numerischem Bezug (SUM, AVG) k=C3=B6nnen nur f=C3=BCr Spalten verwendet = werden, welche numerische Datentypen enthalten.

Bemerkungen

  • Wenn Sie eine Spalte ausgeben, =C3=BCber diese jedoch weder aggregie= ren noch sie in der GROUP-BY-Klausel erw=C3=A4hnen, so erhalten Sie eine typische Fehlermeldung: 'Sie wollten= eine Abfrage ausf=C3=BChren, die den angegebenen Ausdruck 'A_NR' nicht als Teil der Aggregatfunktion einschli= e=C3=9Ft' (Beispiel Access). Diese Fehlermeldung ist insofern irref=C3=BChrend, da es drei M=C3=B6glichkeit= en gibt: Sie entfernen die Spalte aus der Liste der Ausgabespalten, Sie f=C3=BCgen die Spalte zum GROUP-BY-Abschni= tt hinzu oder Sie aggregieren =C3=BCber diese Spalte. Beim MS-SQLServer hei=C3=9Ft die analoge Fehlermeldung: '= Die U.A_NR-Spalte ist in der Auswahlliste ung=C3=BCltig, da sie nicht in einer Aggregatfunktion enthalten und kein= e GROUP BY-Klausel vorhanden ist'. Wurde eine GROUP-BY-Klausel angegeben, so wird Ihnen mitgeteilt: 'und ni= cht in der GROUP BY-Klausel enthalten ist'. Beim MS-SqlServer ist die Fehlermeldung also weitaus spe= zifischer als bei Access.
  • Ist zus=C3=A4tzlich ein WHERE-Abschnitt angegeben, so wird dieser zu= erst kosteng=C3=BCnstig ausgewertet. Die Aggregation mit eventueller vorheriger Gruppierung wird erst anschlie=C3=9Fend ausge= f=C3=BChrt. In den HAVING-Abschnitt geh=C3=B6ren deshalb nur jene Ausdr=C3=BCcke, welche sich auf Aggregationen beziehen.
  • Access neigt bei der visuellen Codegenerierung dazu, bei vorhandenen= Aggregationen alle Kriterien von der WHERE-Bedingung in die HAVING-Klausel zu verschieben. Dies ist jedoc= h unn=C3=B6tig teuer und sollte gegebenenfalls per Hand bzw. durch den Verzicht auf die visuelle Codierung vermieden we= rden.
  • Wenn Sie nur wissen m=C3=B6chten, welche verschiedenen Zeilen existi= eren, so liefern die beiden Alternativen DISTINCT sowie das Gruppieren nach allen Ausgabespalten die= selben Ergebnisse. DISTINCT ist jedoch immer ressourcenschonender als GROUP BY und deshalb in solchen F=C3= =A4llen erste Wahl.
  • In PHP-Foren findet sich wiederholt Code, mit welchem die Zahl der Z= eilen in einer Tabelle ermittelt werden soll. Dieser Code ist wie folgt aufgebaut:
    $select =3D mysql_query("Select * From Artikel");
    $reihen =3D mysql_num_rows($select);
    Eine solche Verarbeitung wider= spricht s=C3=A4mtlichen Prinzipien ressourcenschonender Programmierung. Akzeptabel ist eine L=C3=B6sung der Form:
    $select =3D mysql_query("Select Count(*) From Artikel");
    $zahl_der_zeilen =3D mysql_fetch_row($select);
    echo $zahl_der_zeilen[0];
    
    Ein DBMS sollte nur jene Zeilen zur=C3=BCckgeben, die tats=C3=A4ch= lich ben=C3=B6tigt werden. Das Z=C3=A4hlen von Datens=C3=A4tzen wird von= jedem DBMS rascher erledigt als im Rahmen eines externen Aufrufs von der umgeb= enden Wirtssprache. Ferner wird nur eine einzige Zelle, also ein Gebilde aus einer Spalte und einer Zeile, zur=C3=BCckgegeben. Bei ge= speicherten Prozeduren l=C3=A4=C3=9Ft sich der Code weiter optimieren:
    Create Procedure _up_count_Artikel
    	@num_rows int Output
    As
    
    Select @num_rows =3D Count(*)
    From Artikel
    In diesem Fall mu=C3=9F keine DataTable oder ein Recor= dSet mit Informationen =C3=BCber die zur=C3=BCckgegebenen Datentypen erstellt werden, da der R=C3=BCckgabewert von vornherein bekannt ist. De= r Aufruf kann nun (VB.NET) so erfolgen:
    Dim oCmd As New SqlCommand("_up_count_Artikel", oConn), _
    	i_num_rows As Integer
    
    oCmd.Parameters.Add("@num_rows", SqlDbType.Int).Direction =3D _
    	ParameterDirection.Output
    Try
    	oCmd.ExecuteNonQuery()
    	i_num_rows =3D CType(oCmd.Parameters("@num_rows").value, Integer)
    
    Catch _e As Exception
    	'Fehlerbehandlung
    End Try

TOP

Unterabfragen bzw. Subqueries - einfach, korrelie= rt, anstelle einer Tabelle

Vorbemerkung

Die folgenden Techniken verwenden kein neues Schl=C3=BCsselwort, sondern= ausschlie=C3=9Flich die bisher bekannten grundlegenden Techniken mit SELECT, JOIN, WHERE und GROUP BY. Unterabfra= gen, f=C3=BCr die meistens das Wort Subqueries genutzt wird, werden dann verwendet, falls das Ergebnis einer Abfrage / = Query herangezogen wird, um eine neue Abfrage zu erstellen, mit welcher ein genauerer Einblick in die Dat= enstruktur gewonnen werden kann. Unterabfragen werden deshalb in WHERE-Klauseln und als Tabellen-Ersatz i= n JOIN-Klauseln genutzt.

Die einfachste Form - eine zur=C3=BCckgegebene Ze= lle

In der elementarsten Version einer Unterabfrage liefert diese eine Zelle= zur=C3=BCck und ist unabh=C3=A4ngig von der sie aufrufenden Abfrage. Sie wird verwendet, um Details zu einem= Datensatz zu ermitteln.
Beispiel:
SELECT A.*
FROM ARTIKEL As A
WHERE A.A_PREIS =3D
	(SELECT MAX(A.A_PREIS)
	FROM ARTIKEL As A)
Die Unterabfrage ermittelt durch Maximumsbildung den teuersten Artikel. = Dieser Wert wird zur=C3=BCckgegeben, die =C3=BCbergeordnete Abfrage sucht nach diesem Wert, den es mindestens ein= mal geben mu=C3=9F und gibt die zugeh=C3=B6rigen Zeilen aus.
Die ganze Konstruktion mag f=C3=BCr jemanden, der dies zum ersten Mal ma= cht, verdoppelt aussehen: 'Suche die Zeilen, deren Wert in A_PREIS gleich dem Maximum aller Preise ist'. Erst= mu=C3=9F dieses Maximum einmal ermittelt werden, dann ist ein zweiter Durchlauf notwendig, um die zu diesem Preis= geh=C3=B6renden Zeilen zu bestimmen.
Wird die Abfrage allerdings auf dem MS-Sql-Server durchgef=C3=BChrt und = zuvor mit SET SHOWPLAN_TEXT ON die Analyseoption eingeschaltet, so wird sichtbar, da=C3=9F der Optimierer e= inen ver=C3=A4nderten Abfragetext vorgeschlagen hat:
Top(1)
  Filter(WHERE:(Artikel.A_Preis <> NULL)
    Sort(Order By:(Artikel.A_Preis DESC)
      Clustered Index Scan(Object:Artikel.pk_Artikel)
Es wird also eine Abfrage ausgef=C3=BChrt, die in etwa dem folgenden Sql= -Befehl entspricht:
SELECT TOP 1 A.*
FROM ARTIKEL As A
ORDER BY A.A_PREIS DESC
Das hei=C3=9Ft, da=C3=9F der Optimierer eine Unterabfrage gegebenenfalls= in eine andere Sql-Befehlsfolge aufl=C3=B6st und diese ausf=C3=BChrt. Verwenden Sie die obige, umgeschri= ebene Abfrage jedoch nicht. Denn setzen Sie alle Artikel auf denselben Preis, so wird Ihnen die Version mit der Unte= rabfrage korrekt alle vier Datens=C3=A4tze ausgeben, die umgeschriebene Version liefert jedoch nur einen Datensatz.=

Eine solche Unterabfrage wird also in Klammern gesetzt, mu=C3=9F genau e= ine Zelle zur=C3=BCckliefern und darf =C3=BCberall dort verwendet werden, wo Konstanten, etwa Zahlen, oder Spalten eingeset= zt werden d=C3=BCrfen.

Unterabfragen, die eine Spalte zur=C3=BCckliefern=

Jede Zeile in der Tabelle Umsatz stellt einen einzelnen Gesch=C3=A4ftsvo= rfall dar, an dem ein Artikel und ein Verk=C3=A4ufer beteiligt ist, jeder Gesch=C3=A4ftsvorfall liefert einen = gewissen Brutto-Umsatz. Der durchschnittlichen Brutto-Umsatz kann mit der AVG-Funktion ermittelt werden. Dieses Kriteri= um l=C3=A4=C3=9Ft sich verwenden, um jene Gesch=C3=A4ftsvorf=C3=A4lle zu ermitteln, welche hieran beteiligt waren.= Interessant ist nun: Welche Artikel und welche Verk=C3=A4ufer sorgen f=C3=BCr diese =C3=BCberdurchschnittlic= hen Gesch=C3=A4ftsvorf=C3=A4lle? Offenbar ist nicht bekannt, wieviele Artikel und wieviele Verk=C3=A4ufer dies sind, also wird eine L= iste zur=C3=BCckgegeben, wobei sich der Auswertende f=C3=BCr die Klartext-Namen, nicht f=C3=BCr die internen= Prim=C3=A4rschl=C3=BCssel interessiert. Betrachten Sie zun=C3=A4chst die folgende Abfrage:
SELECT U.A_NR, U.DA=
TUM, U.V_NR
FROM ARTIKEL As A INNER JOIN UMSATZ As U
ON A.A_NR =3D U.A_N=
R
WHERE A.A_PREIS * U.A_STUECK >
	(SELECT AVG(A.A_PREIS * U.A_STUECK)
	FROM ARTIKEL As A INNER JOIN UMSATZ As U
	ON A.A_NR =3D U.A_=
NR)
Ergebnis:
A_NRDATUMV_NR
2224.06.19995016
1124.06.19998413
2225.06.19995016
1324.06.19998413

An den =C3=BCberdurchschnittlichen Ums=C3=A4tzen sind drei von vier Arti= keln sowie zwei von drei Verk=C3=A4ufern beteiligt. Werden deren Klartext-Informationen ben=C3=B6tigt, so reduziert man die = Ausgabespalten auf A_Nr bzw. V_Nr und verwendet den ganzen Ausdruck als Unterabfrage f=C3=BCr die Tabelle mit = den zugeordneten Stammdaten. Am Beispiel der Artikel:
SELECT A.*

FROM ARTIKEL As A

WHERE A.A_NR IN

	(SELECT U.A_NR

	FROM ARTIKEL As A INNER JOIN UMSATZ As U
		ON A.A_NR =3D U.A=
_NR

	WHERE A.A_PREIS * U.A_STUECK >

		(SELECT AVG(A.A_PREIS * U.A_STUECK)
		FROM ARTIKEL As A INNER JOIN UMSATZ As U
			ON A.A_NR =3D U.=
A_NR)
	)

Korrelierte Unterabfragen

Bislang waren die Unterabfragen immer unabh=C3=A4ngig von der =C3=BCberg= eordneten Abfrage. Man k=C3=B6nnte sie eigenst=C3=A4ndig ausf=C3=BChren, ihr Ergebnis in eine neue Tabelle eintragen (Select ... = Into) und die =C3=BCbergeordnete Abfrage mit dieser verkn=C3=BCpfen. Nun soll der Fall betrachtet werden, bei dem zu jeder Z= eile der =C3=BCbergeordneten Tabelle eine Anweisung ausgef=C3=BChrt werden soll: Es soll ermittelt werden, mit wel= chem Artikel und an welchem Tag jeder Vertreter seinen h=C3=B6chsten Einzelumsatz gemacht hat. Bei wenig= en Vertretern und vielen Einzelums=C3=A4tzen liegt es nahe, diesen Befehl f=C3=BCr jeden Vertreter getrennt auszuf=C3= =BChren, also V_NR als Parameter @V_NR zu =C3=BCbergeben:
SELECT U.DATUM, U.A_NR, MAX(A.A_PREIS * U.A_STUECK) As Maximum
FROM UMSATZ As U INNER JOIN ARTIKEL As A
ON U.A_NR =3D A.A_N=
R
WHERE U.V_NR =3D @V_NR
Diese Abfrage funktioniert auch dann nicht, wenn man @V_NR durch eine Ko= nstante, etwa 1215 ersetzt. Da eine Aggregatfunktion verwendet wird, mu=C3=9F nach den anderen Spalten grupp= iert werden, dann erh=C3=A4lt man jedoch zu jedem Vertreter so viele Zeilen, wie dieser verschiedene Artikel verk= auft hat, anstatt da=C3=9F man nur eine Zeile f=C3=BCr einen Vertreter erh=C3=A4lt.

Ein Umschreiben ergibt zun=C3=A4chst soviele Zeilen aus, wie dieser Vert= reter Ums=C3=A4tze gemacht hat:
SELECT U.DATUM, U.A_NR, A.A_PREIS * U.A_STUECK As Maximum
FROM UMSATZ As U INNER JOIN ARTIKEL As A
ON U.A_NR =3D A.A_N=
R
WHERE U.V_NR =3D @V_NR
Also mu=C3=9F dieser Ausdruck noch erg=C3=A4nzt werden um eine filternde= Unterabfrage, welche das Maximum f=C3=BCr diesen Vertreter ermittelt:
SELECT U.DATUM, U.A_NR, A.A_PREIS * U.A_STUECK As Maximum

FROM UMSATZ As U INNER JOIN ARTIKEL As A
	ON U.A_NR =3D A.A_=
NR

WHERE (U.V_NR =3D @V_NR) AND

(A.A_PREIS * U.A_ST=
UECK) =3D

	(SELECT MAX(A.A_PREIS * U.A_STUECK)
	FROM ARTIKEL As X INNER JOIN UMSATZ As Y
	ON X.A_NR =3D Y.A_=
NR
	WHERE Y.V_NR =3D @V_NR)
Diesen Ausdruck m=C3=BC=C3=9Fte man f=C3=BCr jeden Vertreter aufrufen un= d die Ergebnisse anschlie=C3=9Fend vereinigen. Tats=C3=A4chlich kann man stattdessen auch eine einzige Anweisung verwen= den. Denn sowohl die =C3=A4u=C3=9Fere als auch die innere Abfrage verwenden denselben Parameter @V_NR, dieser entspricht ei= ner Zelle in der =C3=A4u=C3=9Feren Abfrage und kann von dieser auf die innere Abfrage 'durchgereicht' werden. Die Unter= abfrage erh=C3=A4lt von der =C3=BCbergeordneten Abfrage die V_NR und ermittelt nur f=C3=BCr diese den maximalen Umsatz.
SELECT V.V_NR, V.V_NAME, U.DATUM,
	A.A_NR, A.A_PREIS<=
/span> * U.A_STUECK As [H=C3=B6chster Umsa=
tz]

FROM (VERTRETER AS V INNER JOIN UMSATZ AS U
	ON V.V_NR =3D U.V_=
NR) INNER JOIN ARTIKEL As A
	ON U.A_NR =3D A.A_=
NR

WHERE (A.A_PREIS * U.A_STUECK) =3D

	(SELECT MAX(X.A_PREIS * Y.A_STUECK)
	FROM ARTIKEL As X INNER JOIN UMSATZ As Y
	ON X.A_NR =3D Y.A_=
NR
	WHERE Y.V_NR =3D V.V_NR)
Die =C3=A4u=C3=9Fere Abfrage ruft f=C3=BCr jede V_NR einmal die Unterabf= rage auf und belegt den Wert von V_NR mit dem aktuellen Wert. Das Ergebnis wird genutzt, um von den Zeilen, welche die =C3=A4u=C3= =9Fere Abfrage liefert und welche diesen Vertreter betreffen, die Zeilen zu entfernen, deren Produkt aus A_PREIS und A_STUE= CK nicht dem Maximum entspricht.

Das Interessante an dieser Anweisung ist, da=C3=9F sie auch dann die kor= rekten Ergebnisse liefert, falls man einen Artikel im Wert von 12.600,00, einen neuen Vertreter und einen Ums= atz dieses Vertreters mit diesem Artikel (A_STUECK =3D 1) hinzuf=C3=BCgt. Obwohl es bei dieser Datenstruk= tur zwei maximale Ums=C3=A4tze mit demselben Betrag gibt, die Abfrage auf die Gleichheit von Produkt und Maximum also zwei W= erte zur=C3=BCckliefern m=C3=BC=C3=9Fte, wird pro Vertreter nur eine Zeile mit den ansonsten korrekten Daten ausgegeben. D= ie =C3=A4u=C3=9Fere Abfrage wird also, wie bei einer mit GROUP BY gruppierten Abfrage, nach V_NR gruppiert, f=C3=BC= r jede Gruppe wird einmal die Unterabfrage aufgerufen. Und nur auf diese Teilmenge der =C3=A4u=C3=9Feren Abfrage wi= rd das zus=C3=A4tzliche, durch die Unterabfrage bestimmte Kriterium angewandt.

Beim Entwickeln solcher Abfragen ist zu beachten, da=C3=9F die Alias-Nam= en f=C3=BCr die Tabelle in der untergeordneten Abfrage anders gew=C3=A4hlt werden m=C3=BCssen als in der =C3=BCbergeord= neten Abfrage. Enth=C3=A4lt die Unterabfrage Ausdr=C3=BCcke, die nicht aufgel=C3=B6st werden k=C3=B6nnen, so wird in der =C3=BCbergeo= rdneten Abfrage nach einem entsprechenden Ausdruck gesucht. Wird ein solcher gefunden, handelt es sich um eine korrelierend= e Unterabfrage.

Unterabfragen anstelle von Tabellen in einer JOIN= -Klausel

M=C3=B6chte man zu jedem Vertreter mit seinem Klarnamen den maximalen Um= satz ermitteln, so wurde dies bislang mit einer Doppelberechnung erledigt. Zun=C3=A4chst wurde f=C3=BCr diesen= Vertreter der Maximalumsatz ermittelt, anschlie=C3=9Fend wurden die Produkte A_PREIS * A_STUECK f=C3=BCr diesen= Vertreter mit dem errechneten Maximum verglichen, um die anderen Daten DATUM und A_NR zu bestimmen. Ist man nu= r an dem Maximalwert interessiert, erh=C3=A4lt man diesen f=C3=BCr alle Vertreter gemeinsam mit einer Abfra= ge, die mit MAX aggregiert und nach V_NR gruppiert. Diese kann in einem JOIN verwendet werden, um die Daten direk= t auszugeben.
SELECT V.V_NR, V.V_NAME, X.MAXIMUM

FROM VERTRETER AS V INNER JOIN

	(SELECT U.V_NR, MAX(A.A_PREIS * U.A_STUECK) As MAXIMU=
M
	FROM ARTIKEL As A INNER JOIN UMSATZ As U
	ON A.A_NR =3D U.A_=
NR
	GROUP BY U.V_NR) AS X

ON V.V_NR =3D X.V_N=
R
Anstelle einer Tabelle wird eine eigenst=C3=A4ndige Abfrage notiert, gek= lammert und mit einem Alias identifiziert. Beachten Sie, da=C3=9F in diesem Fall ein Alias f=C3=BCr die Tabelle, di= e aus der Unterabfrage gebildet wird, Pflicht ist.

= TOP

Grundbegriffe und Konzepte von Datenbank-Systemen=

In diesem Abschnitt werden die folgenden Konzepte thematisiert: Der Unte= rschied zwischen einer Datenbank und einem Datenbank-Management-System, zwei fundamentale= Anforderungen, die jedes computerbasierte Datenbanksystem erf=C3=BCllen sollte, der Unterschied zwischen desktop- = und serverbasierten Systemen sowie eine kurze Erl=C3=A4uterung zu drei Typen von Datenbanken.

Datenbank versus Datenbank-Management-System

=
  • Eine Datenbank ist eine logische Einheit zusammenge= h=C3=B6render Daten, ihrer Meta-Beschreibungen sowie zus=C3=A4tzlicher Informationen, die zur Verar= beitung und Bereitstellung dieser Daten ben=C3=B6tigt werden. Physikalisch kann eine Datenbank in mehrere Einzel= teile zerfallen, die getrennt werden k=C3=B6nnen, jedoch nur gemeinsam eine Datenbank bilden.
  • Datenbank-Beispiele in diesem logischen Sinne sind:

    • Eine Access-MDB-Datei
    • Eine mySql-Datenbank, zerfallend in viele Dateien, die in einem ge= meinsamen Ordner liegen
    • Eine MS-SqlServer-Datenbank, verteilt auf diverse Dateien, die auf= verschiedenen Festplatten mit unterschiedlicher RAID-Stufe untergebracht sind
    • Ein Archiv mit tausenden von Regalmetern voller Aktenordnern sowie= einem zus=C3=A4tzlichen Klassifikationssystem in Form weiterer Ordner
    • Ein Zettelkasten mit Personennamen und zugeordneten Telefonnummern=
    • Eine Sql-Datenbank zum Mieten, deren konkrete Implementierung nach= au=C3=9Fen hin unsichtbar ist
  • Eine Datenbank kann in den wenigsten F=C3=A4llen direkt verwendet we= rden. Zwar m=C3=B6gen die Daten in Form von Dateien vorliegen, ein direktes Lesen mit einem Editor liefert jedoch ke= ine verwertbaren Informationen. Oder es bestehen Zugriffsbeschr=C3=A4nkungen verschiedenster Art, so da=C3=9F ei= n gew=C3=B6hnlicher Benutzer keine Informationen dar=C3=BCber hat, in welcher Form und an welchem Ort die Dateien abgelegt sind.
  • Ein Datenbank-Management-System (DBMS) stellt unterschiedliche Werkzeuge bereit, mit welchen eine oder mehrere Datenba= nken erstellt, mit Daten gef=C3=BCllt und verwaltet werden k=C3=B6nnen. Ein DBMS verf=C3=BCgt in der Regel =C3=BCb= er mindestens eine Benutzerschnittstelle und kann eine oder mehrere Datenbanken nur aufeinanderfolgend oder parallel verwa= lten. Ferner gibt es - explizit oder implizit - Regeln, wer zu welchem Zeitpunkt Zugriff auf und =C3=84nderun= gsrecht an den Daten hat. Schlie=C3=9Flich k=C3=B6nnen Sicherungsstrategien / Backup-Verfahren definiert und regelm=C3=A4=C3=9F= ig ausgef=C3=BChrt werden.
  • Jede Benutzerschnittstelle besteht entweder aus verschiedenen Masken= (Sql-Enterprise-Manager) oder bietet dem Nutzer eine M=C3=B6glichkeit, direkt Befehle entgegenzunehme= n. Diese werden an das DBMS gesandt und von diesem gegen die aktuelle Datenbank ausgef=C3=BChrt. Die hierf=C3=BC= r verwendete Sprache k=C3=B6nnte vom Hersteller des DBMS frei entwickelt worden sein. Tats=C3=A4chlich wird von den meisten= relationalen DBMS Structured Query Language (S= QL) mit eventuellen eigenen Erweiterungen unterst=C3=BCtzt.
  • Datenbank-Management-Systeme in diesem Sinne sind:

    • Die Installation einer geeigneten Ms-Access-Version zur Verwaltung= von jeweils einer Datenbank.
      Oder: Die Installation der NET-Laufzeitumgebung sowie des Sql-Interakt= iv-lernen. Mit diesem k=C3=B6nnen Datenbank-Befehle direkt auf der Access-Datenbank ausgef=C3=BChrt werd= en.
    • Eine mySql-Installation, die vielleicht eine Datenbank verwaltet, = deren Ordner auf einem anderen Rechner liegt.
    • Eine MS-SqlServer-Standard-Installation, die einige Werkzeuge (Ent= erprise-Manager, OSQL) bereitstellt.
      Oder: Ein installiertes MS-Access, in dem ein Access-Projekt erstellt = wird, das auf eine Datenbank auf einem MS-SqlServer zugreift.
    • Regeln f=C3=BCr den Zutritt zum Archiv (Ausweispflicht, zeitliche = Einschr=C3=A4nkungen, nicht in der Urlaubszeit). Gespr=C3=A4ch mit den Archivverwaltern, um bestimmte Informationen zu = finden bzw. um das Klassifikationssystem erst einmal zu verstehen, Verbot der Archivbenutzung bei zu vielen Anf= ragen oder bei ungeb=C3=BChrlichem Benehmen. Implizite oder explizite Verhaltensregeln innerhalb des Archivs (kein = Essen / Trinken / Rauchen), da das Archiv einmalig ist und keine Sicherung zur Verf=C3=BCgung steh= t.
    • Der Zettelkasten: Diese Datenbank ist einmalig und kann nicht mit = einem vertretbaren Aufwand kopiert / gesichert werden. Sie k=C3=B6nnte h=C3=B6chstens, Karte f=C3=BCr Karte, kopiert = bzw. abgeschrieben werden. F=C3=BCr neue Datens=C3=A4tze gen=C3=BCgt einfaches kartoniertes Papier. Spezielle Kenntnisse zur Erstellung neu= er Datens=C3=A4tze sind zun=C3=A4chst nicht notwendig. Jeder mit Zutritt zum Zimmer kann auf diese Daten zugreifen= und die Sortierung zerst=C3=B6ren. Es kann jedoch einen zweiten Zettelkasten geben, der nach vergleichbar= en Prinzipien aufgebaut und von derselben Person verwaltet wird.
    • Zu einer Sql-Datenbank zum Mieten wird ein Web-Interface mit =C3=BC= blichen Masken angeboten, wie sie bsp. von Access her bekannt sind. Im Hintergrund werden aus den Nutzer= eingaben Sql-Befehle generiert und diese auf der Kunden-Datenbank ausgef=C3=BChrt. Verschiedene Nutzer ve= rwenden zwar dasselbe Interface, haben jedoch keinen Zugriff auf die Datenbanken der anderen Nutzer.
  • Zusammengefa=C3=9Ft: Eine Datenbank als logische Einheit umfa=C3=9Ft= alle Daten mit den notwendigen Meta-Informationen, diese sind ohne das zugeh=C3=B6rige Datenbank-Management-System unverst=C3= =A4ndlich und nicht verwendbar. Letzteres stellt die eigentliche Rahmenarchitektur zur Erstellung von Datenbanken dieses Typs mit ihren s= peziellen Inhalten dar und bietet datenbank=C3=BCbergreifend zus=C3=A4tzliche Service-Leistungen an.

Grundlegende Anforderungen an computergest=C3=BCt= zte Datenbank-Systeme

An Datenbank-Systeme, die edv-basiert sind, werden =C3=BCblicherweise zw= ei fundamentale Forderungen gestellt: Vermeiden von Redundanz sowie die Sicherstellung einer = maximalen Integrit=C3=A4t der Daten.
  • Redundanzfreiheit: Informat= ionen sollten nicht mehrfach abgelegt werden. Wurden Daten zu einer Einheit, einem Objekt, einem Vorgang abgelegt, so= sollen diese Daten nur einmalig in der Datenbank vorhanden sein, so da=C3=9F beim lesenden Zugriff immer n= ur diese eine Position abgefragt, beim schreibenden Zugriff nur diese Position ge=C3=A4ndert wird. Enth=C3=A4l= t die Datenbank bsp. Informationen zur Person 'Max Mustermann, Tel. 773355', so sollen die Eigenschaften 'Vorname', '= Nachname' und 'Telefon' nur einmalig existieren. =C3=84ndert sich etwa die Telefonnummer, so mu=C3=9F sie nu= r an einer einzigen Stelle ge=C3=A4ndert werden. Alle anderen Stellen, welche diese Information ben=C3=B6tigen, lesen sie von= dort aus und erhalten ab der =C3=84nderung unverz=C3=BCglich den neuen Wert.
    Papierversionen von Datenbanken sind oft redundant, so werden Personenn= amen ausgeschrieben, anstatt da=C3=9F nur eine Nummer eingesetzt wird. Damit steht bsp. auf Karteikarten der Name= des Erstellers, gleichzeitig ist es nur mit einem unvertretbar hohen Aufwand m=C3=B6glich, alle von diesem = erstellten Karten herauszufinden.
  • Datenintegrit=C3=A4t erzwingen: Alle abzulegenden = Informationen zerfallen in kleinste Einheiten, die vielfachen Einschr=C3=A4nkungen unterliegen = k=C3=B6nnen. Ein Geburtsdatum darf nur g=C3=BCltige Datumswerte enthalten, bei Gewichts- oder Mengenangaben sollen nur ganz= e Zahlen gr=C3=B6=C3=9Fer Null zul=C3=A4ssig sein. Bei Namen sind vielleicht Sonderzeichen verboten, bei Benutzernamen f=C3= =BCr ein Forum m=C3=B6gen keine Leerzeichen (... van der ...) gew=C3=BCnscht und die L=C3=A4nge beschr=C3=A4nkt sei= n. Telefonnummern erlauben lediglich die Eingabe von Zahlen und Leerzeichen einschlie=C3=9Flich f=C3=BChrender Nullen, die nicht ab= geschnitten werden sollen. Oder ein Feld erfordert die Auswahl aus einer Reihe von Werten, etwa W=C3=A4hrungen, = Personen oder Kategorien. Hier sollte eine Pulldown-Liste versehentliche oder absichtliche Fehleingaben aussc= hlie=C3=9Fen. Schlie=C3=9Flich gibt es Pflichtfelder, die zwingend zu belegen sind, Werte m=C3=BCssen eindeuti= g sein - etwa Personalnummern - oder sollen zus=C3=A4tzliche Bedingungen erf=C3=BCllen (10 < Wert < 10= 0). Ferner kann es w=C3=BCnschenswert sein, Lese- und Schreibrechte fein granuliert zu verteilen, so da=C3=9F nur berechtigte Personen Zugr= iff auf den jeweiligen Ausschnitt der Daten erhalten.
    Zur Forderung der Datenintegrit=C3=A4t z=C3=A4hlt ferner, da=C3=9F das = DBMS parallele Benutzerzugriffe gestattet, so da=C3=9F parallele Lese- und Schreibzugriffe sich nicht gegenseitig behindern. Bei schwerw= iegenden St=C3=B6rungen wie einem Verbindungsabbruch innerhalb der Netzkommunikation oder einem Stromausfall mu=C3=9F es das= DBMS gew=C3=A4hrleisten, da=C3=9F die Daten konsistent bleiben bzw. da=C3=9F das System auf einen Zustand kurz vor dem Abbruch zur=C3=BC= ckgesetzt werden kann.
Beachten Sie, da=C3=9F das vielleicht erwartete, =C3=BCblicherweise edv-= typische Kriterium des 'raschen Zugriffs' hier ausdr=C3=BCcklich nicht thematisiert worden ist. Dieses Kriterium stellt= zwar einen der entscheidenden Unterschiede zu jeder Form eines papiergebundenen Archivs dar, f=C3=BCr das m=C3=BChs= am vielleicht einzelne Schlagworte mit Seitenangaben katalogisiert wurden. Es wird jedoch im Laufe der weiteren Ausf=C3=BChru= ngen deutlich werden, da=C3=9F der rasche Suchzugriff h=C3=B6chstens eine Folge der obigen Anforderungen darstellt. Sind die D= aten nicht redundanzfrei abgelegt oder ist die Datenintegrit=C3=A4t nicht bei jeder Verarbeitung sichergestellt, so= liefert jede nachfolgende Auswertung ebenfalls ungen=C3=BCgende oder falsche Ergebnisse.

Desktop- versus serverbasierte Datenbank-Manageme= nt-Systeme

  • Ein desktop-basiertes DBMS ist dadurch gekennzeichn= et, da=C3=9F der Betriebssystem-Proze=C3=9F, der auf die Datenbank zugreift, nur in der Zeit aktiv sein mu=C3=9F, in = welcher die Datenbank tats=C3=A4chlich benutzt wird. Damit k=C3=B6nnen verschiedene Instanzen desselben DBMS auf verschiedene= n Rechnern gestartet werden und versuchen, auf dieselbe logische Datenbank zuzugreifen, deren Datei auf einem Netzlaufw= erk freigegeben worden ist. Jede dieser Instanzen mu=C3=9F freiwillig Zugriffe anderer Instanzen respektieren un= d eventuell gesetzte Schreibsperren beachten. Ein b=C3=B6swillig geschriebenes oder einfach fehlerhaftes Pro= gramm kann ebenfalls auf die Datenbank zugreifen und deren Inhalt beliebig ver=C3=A4ndern, so da=C3=9F die Datenbank zers= t=C3=B6rt wird. Der Rechner, auf dem die Datenbank-Datei liegt, wird nur als Fileserver verwendet. Alle Filter- und Sortiervorg=C3=A4nge= werden ausschlie=C3=9Flich von den Benutzerprozessen erledigt, so da=C3=9F sich eine solche Instanz alle Daten =C3=BCber das = Netzwerk holt, erst lokal wenige Zeilen aussondert und diese dem Nutzer anzeigt. Fordert ein anderer Nutzer dieselbe Teilmenge = von Daten an, f=C3=BChrt der Betriebssystem-Proze=C3=9F dieses Nutzers dieselbe Aktivit=C3=A4t durch. Sollen Sicherungen erstell= t werden, so gelingt dies nur durch ein physikalisches Kopieren der Datei. Wird die Datei so besch=C3=A4digt, da=C3=9F sie nich= t mehr verwendbar ist, kann nur auf die eventuell mehrere Stunden alte Sicherung zur=C3=BCckgegriffen werden, so da=C3=9F = alle in der Zwischenzeit erfolgten =C3=84nderungen verloren sind.

    Beispiel: Eine Access-Datenbank auf einem freigegebenen Laufwerk. Mehrer= e Benutzer starten auf ihrem Rechner Access und =C3=B6ffnen die Datenbank. Zus=C3=A4tzlich schreibt jemand ei= n Programm, welches direkt, unter Umgehung der =C3=BCblichen Treiber, auf die Datenbank zugreift und diese als Textdate= i anspricht.
  • Ein serverbasiertes DBMS ist durch mindestens einen= kontinuierlich laufenden Betriebssystem-Proze=C3=9F charakterisiert, welcher vom Server-Betriebss= ystem verwaltet und gesch=C3=BCtzt wird. Nur dieser wei=C3=9F, wo die physikalischen Dateien tats=C3=A4chlich liegen und ver= bietet jedem anderen Proze=C3=9F den Zugriff auf diese. Dieser Proze=C3=9F stellt verschiedene Kommunikations-Schnittstellen zur Verf=C3= =BCgung, die von Nutzern angesprochen werden k=C3=B6nnen. Alle =C3=BCber die Schnittstellen mitgeteilten W=C3=BCnsche werden zun=C3= =A4chst vom Server-Proze=C3=9F analysiert. Nur wenn die Befehle syntakti= sch korrekt sind und die Berechtigung f=C3=BCr diesen Zugriff vorliegt, wird= die Befehlsfolge ausgef=C3=BChrt und gegebenenfalls Daten zur=C3=BCckge= sandt. Fordert ein Nutzer nur wenige Datens=C3=A4tze an, so wird die Filterung = sofort auf dem Server durchgef=C3=BChrt, f=C3=BCr das Senden der Daten sind nur geringe Netzwerk-Ressourcen notwendig. Fordern mehrer= e Nutzer dieselben Informationen ab, k=C3=B6nnen sp=C3=A4tere Anfragen direkt aus dem Arbeitsspeicher heraus beantwortet = werden, so da=C3=9F die Antwortzeit entsprechend verk=C3=BCrzt wird. Sicherungen k=C3=B6nnen w=C3=A4hrend des laufenden Betriebs vom Se= rverproze=C3=9F erstellt werden.
  • Vergleicht man diese beiden Typen mit einem klassischen Archiv, so e= ntspricht einem Desktop-System ein Archiv, das frei zug=C3=A4nglich ist, bei dem jeder Archiv-Nutzer selbst= zu den Regalen geht, in den Akten bl=C3=A4ttert oder einen Ordner aus dem Regal nimmt und an einer anderen Stelle wieder= einstellt. Die Integrit=C3=A4t und Konsistenz des Archivs ist also vollst=C3=A4ndig vom Verhalten der Nutzer abh=C3=A4= ngig, die Logik der Archivierung mu=C3=9F jedem Nutzer neu erl=C3=A4utert werden.

    Eine serverbasierte Datenbank-L=C3=B6sung l=C3=A4=C3=9Ft sich dagegen be= schreiben als eine Art Hochsicherheitstrakt mit frei zug=C3=A4nglichem Eingangsbereich. Die Nutzer haben keinen Zutritt zu den Stockwerken und = Regalen, sie d=C3=BCrfen im Erdgescho=C3=9F ihre W=C3=BCnsche interaktiv oder telefonisch mitteilen. Nur, wenn die W=C3=BCnsche syntak= tisch korrekt formuliert und die notwendige Berechtigung vorliegt, wird ausschlie=C3=9Flich das erlaubte Datenpaket = zugesandt.

Drei Typen von Datenbank-Systemen

Bei Datenbank-Management-Systemen werden drei verschiedene Typen untersc= hieden:
  • Hierarchische Datenbank: Dies ist der historisch f= r=C3=BCheste Typ. Die Daten werden in Form einer Baumstruktur abgebildet, so da=C3=9F Pa= rent-Child-Beziehungen ma=C3=9Fgeblich sind.
  • Relationale Datenbank: 1970 ver=C3=B6ffentlichte <= strong>Edgar Frank Codd den Text A Relational Model of Data for Large Shared Data Banks= (fr=C3=BCher zug=C3=A4nglich unter http://www.acm.org/classics/nov95/toc.html), mit dem er die Grundlage f=C3=BCr relationale Datenbank-Systeme legte. = Die Daten werden in flache Tabellen (=3D Relationen) abgelegt, die durch Fremdschl=C3=BCssel-Beziehungen beliebig miteinande= r verkn=C3=BCpft werden k=C3=B6nnen. Die f=C3=BCnf Normalformen<= /strong> stellen Regeln dar, entlang derer ein Tabellenschema so entworfen wird,= da=C3=9F die Daten ohne Informationsverlust und redundanzfrei gespeichert werden. Charakteristisch f=C3=BCr das rel= ationale Modell ist, da=C3=9F die Informationen zu einem Gesch=C3=A4ftsvorfall auf viele Tabellen verteil= t und bei Bedarf zusammengesetzt werden. Das relationale Modell ist bis heute das vorherrschende Modell f=C3=BCr= Datenbanken.
  • Objektorientierte Datenbank: Ein objektorientierte= s DBMS erlaubt es, zusammengeh=C3=B6rende Einheiten auch zusammen abzuspeichern. Dabei leh= nt es sich an die objektorientierte Programmierung an und vermeidet damit das wiederholte Zusammensuchen zu= sammengeh=C3=B6render Daten.

TOP

Daten verwalten - die denormalisierte Tabelle als= Ausgangspunkt f=C3=BCr die Definition der Relationen / des Tabellenschemas

  • Aufgabe einer Datenbank ist es, alle Informationen zu einer Thematik= zusammenzutragen. Hierbei kann es sich um s=C3=A4mtliche Gesch=C3=A4ftsvorf=C3=A4lle einer Firma oder u= m ein privates Werkzeug-Archiv handeln. Bei der Firma sollen alle Mitarbeiter-, Lieferanten- und Kundendaten sowie jede einzel= ne Bestellung erfa=C3=9Ft werden. Das private Werkzeug-Archiv bestehe aus tausenden von Gegenst=C3=A4nden, gegliedert = in diverse Kategorien, verteilt auf verschiedene K=C3=A4sten und Regale.
  • Sollen all diese Informationen erfa=C3=9Ft werden, so kann dies nach= einem einfachen Schema realisiert werden: Zu jedem Detail gibt es eine Spalte. Findet irgendeine Aktivit=C3=A4t st= att, so wird eine Zeile hinzugef=C3=BCgt und die bei dieser Aktivit=C3=A4t ermittelten Informationen in die zur Zeile= geh=C3=B6renden Zellen eingetragen. Alle bei diesem Gesch=C3=A4ftsvorfall nicht ben=C3=B6tigten Zellen bleiben leer. Eine so= lche Tabelle kann auch als vollst=C3=A4ndig denormalisierte Tabelle bezeichnet wer= den.
  • Beispiel 1:

    = <= td>Schulze, Fritz
    U_NRA_NAMEA_PREISA_STUECKDATUMV_NAMEV_ANSC= H
    1Oberhemd39,804024.06.1999Meyer, EmilWendeweg 10, 2800 Bremen
    2Mantel360,001024.06.1999Meier, FranzKohlstr. 1, 2800 Bremen
    3Oberhemd44,207024.06.1999Meyer, EmilWendeweg 10, 2800 Bremen
    4Oberhemd44,202025.06.1999Schulze, FritzGem=C3=BCseweg 3, 2800 Bremen
    5Mantel360,003525.06.1999Meier, FranzKohlstr. 1, 2800 Bremen
    6Hose110,503524.06.1999Meyer, EmilWendeweg 10, 2800 Bremen
    7Hose110,50524.06.1999Gem=C3=BCseweg 3, 2800 Bremen
    8Oberhemd39,801024.06.1999Schulze, FritzGem=C3=BCseweg 3, 2800 Bremen
    9Oberhemd44,202025.06.1999Meyer, EmilWendeweg 10, 2800 Bremen

    Dieses Beispiel scheint relativ klar strukturiert zu sein, so da=C3=9F m= an eine solche denormalisierte Tabelle rasch in drei Tabellen zerlegen k=C3=B6nnte. Werden allerdings tagesaktu= elle Preise ber=C3=BCcksichtigt, so stellt sich die Frage, ob der Preis in die Artikel- oder in die Umsatztabelle eingetrage= n wird.
  • Beispiel 2:

    30 40 =
    lfNrLiefer-NrDatum Artikel (E)LieferantEPZahl Artikel (V)Empf=C3=A4ngerEPZahl
    12415.2.2003 Hosen, blauFA Muster-Liefer GbR, N=C3=BCrnberg39.9= 050
    22415.2.2003 Hose, braunFA Muster-Liefer GbR, N=C3=BCrnberg39.9= 050
    32716.2.2003 HosenMax M=C3=BCller, Berlin49.9010
    42817.2.2003 HemdenFA Gro=C3=9F-Handel AG, Hamburg18.40
    52817.2.2003 HemdenFA Gro=C3=9F-Handel AG, Hamburg18.40
    63518.2.2003 HemdenLisa Mayer, M=C3=BCnchen23.905

Merkmale und Nachteile einer vollst=C3=A4ndig den= ormalisierten Tabelle

  • Einerseits l=C3=A4=C3=9Ft sich offenkundig jede Information in eine = solcherart strukturierte, sehr viele Spalten umfassende Tabelle einsortieren. Wird die Archivierung zus=C3=A4tzlicher= Informationen gew=C3=BCnscht, so gen=C3=BCgt es, weitere Zeilen hinzuzuf=C3=BCgen und diese gegebenenfalls leer zu lassen. Jede D= atenbank k=C3=B6nnte sich theoretisch damit begn=C3=BCgen, eine einzige, nach diesem Muster strukturierte Tabelle zu enthalten. Im = extremsten Fall w=C3=BCrde die Tabelle eine einzige gro=C3=9Fe Textspalte enthalten, in welcher s=C3=A4mtliche Infor= mationen der Reihe nach aufgef=C3=BChrt w=C3=A4ren. Andererseits weist diese Form der internen Darstellung offensichtliche Nachteile auf,= die im folgenden zu diskutieren sind.
  • Die Redundanz dieser Beispiele ist offenkundig. So werden im ersten = Beispiel dieselben Adressdaten mehrfach aufgef=C3=BChrt, so da=C3=9F bei einer =C3=84nderung einer Adress= e mehrere gleichlautende Zellen gesucht und umgeschrieben werden m=C3=BCssten. In solch einem Fall spricht man von einer U= pdate-Anomalie. Dann k=C3=B6nnte es zwei verschiedene Personen mit demselben Vor- und Na= chnamen geben, so da=C3=9F bei der dem Update vorgeschalteten Suche mehrere Adressen gefunden und anschlie=C3=9Fend ge=C3=A4ndert werd= en. Eindeutige Personen sollten eindeutig charakterisierbar sein.
  • Werden im Beispiel 2 alle Hosen gesucht, so mu=C3=9F mit einer Platz= haltersuche gearbeitet werden, die nach 'Hose*' oder '*Hose*' sucht und den '*' als Platzhalter nutzt. Denn die Zelle 'Einkau= f: Artikel' enth=C3=A4lt mehrere Informationen gleichzeitig. Interessiert nur eine Teilinformation, so ist unbekannt, w= o diese steht (am Anfang oder in der Zellenmitte), so da=C3=9F der zu suchende Ausdruck von beiden Seiten her= durch einen Platzhalter erg=C3=A4nzt werden mu=C3=9F. Ein vergleichbares Problem existiert bei der Suche nach Ortschaften. Ein= e Person, die als Nachname ein Wort hat, das gleichzeitig als Ort eingetragen ist, w=C3=BCrde bei der Suche nach = dem Ort gefunden werden.
  • Eine solche Tabelle scheint nur Text zu enthalten. Damit k=C3=B6nnte= in die Datumszelle auch Text eingetragen oder bei den Preisangaben anstelle des Punktes ein Komma als Trennzeiche= n verwendet werden, so da=C3=9F der Wert nicht mehr korrekt f=C3=BCr Rechenoperationen verwendet werden kann.
  • Das Beispiel 2 umfa=C3=9Ft derzeit nur Bestellungen und Lieferungen.= W=C3=BCrde die Lieferung an 'Lisa Mayer' gel=C3=B6scht oder storniert werden, so w=C3=BCrden auch die Adressangaben verschwinden, ob= wohl diese vielleicht noch notwendig sind. Dies wird als Delete-Anomalie benannt. Eine Alternative= best=C3=BCnde darin, 'Lisa Mayer' ohne eine Lieferung einzutragen. Damit d=C3=BCrfen die f=C3=BCr eine Lieferun= g zwingend notwendigen Felder nicht mit NOT NULL deklariert sein, das DBMS kann nicht die Konsistenz der Eingabe sicherst= ellen. W=C3=A4re dagegen eine Bestellung zwingend, so w=C3=A4re dies ein= Beispiel f=C3=BCr eine Insert-Anomalie. Selbst bei der Zul=C3=A4ssigkeit einer Person ohne Bestellung ist unklar= , ob die Daten in die Spalte 'Lieferant' oder 'Empf=C3=A4nger' einzutragen sind. Schlie=C3=9Flich ist der Fall denkbar, da=C3=9F eine F= irma sowohl Lieferant als auch Empf=C3=A4nger ist oder an eine als Mitarbeiter eingetragene Person Waren gesandt werden.
  • Liefert die Firma 'Muster-Liefer' verschiedenfarbige Hosen, so kann = diese Information ignoriert werden. Damit ist es sp=C3=A4ter unm=C3=B6glich, die Einkaufs- und Verkaufszahle= n nach den Farben der Hosen aufzuschl=C3=BCsseln. Wird diese Information zus=C3=A4tzlich abgelegt, so m=C3=BCssen auch s=C3=A4m= tliche Adressdaten erneut eingegeben werden, so da=C3=9F die Wahrscheinlichkeit von Eingabefehlern steigt. Ein Verschrei= ber 'FI Muster-Liefer' w=C3=BCrde bei einer Textsuche nach 'FA Muster-Liefer*' zum Verschwinden dieses Datensatzes f=C3=BChren= .
  • Die beiden Lieferungen am 15.02.2003 betreffen verschiedene Artikel.= Die zwei Lieferungen vom 17.02.2003 dagegen k=C3=B6nnten zu einer Lieferung mit 70 St=C3=BCck zusammengefa=C3= =9Ft werden, da die Zellwerte, mit Ausnahme der Spalte 'St=C3=BCckzahl', identisch sind und bei der St=C3=BCckzahl die Addition= zweier Einzelinformationen sinnvoll ist.
Offenkundig produziert ein solches Design diverse Probleme und fehlerhaf= te Auswertungen. Zwar w=C3=A4re im Gegensatz zu jedem Archiv in Papierform eine reine Tex= tsuche m=C3=B6glich. Jedoch m=C3=BC=C3=9Ften die Ergebnisse erneut per Hand gepr=C3=BCft werden, jede fehlerhafte Eingabe l=C3=A4=C3= =9Ft sich nur durch die Kontrolle der Originalzelle ermitteln. Deshalb w=C3=BCrde ein solches, denormalisiertes Design all j= ene Vorz=C3=BCge einer edv-gest=C3=BCtzten Datenarchivierung zunichte machen.

Die folgenden Seiten besch=C3=A4ftigen sich deshalb mit den datenbank-ty= pischen Techniken, eine solche denormalisierte Tabelle in mehrere kleinere Tabellen zu zerlegen.

TOP

Tabellen als Relationen mit Attributen

Eine denormalisierte Tabelle enth=C3=A4lt pro Gesch=C3=A4ftsvorfall eine= Zeile und ist insofern mit einer freien schriftlichen Aufzeichnung vergleichbar. Wird diese Zeile auf einzelne Zellen aufgetei= lt und werden den Spalten Namen zugewiesen, so spricht man davon, da=C3=9F der Tabelle Attribute zu= geordnet sind. Stimmen zwei Zeilen in allen Attributen =C3=BCberein, so kann eine Zeile entfernt werden, da= in der Menge der Zeilen kein Element (=3D Zeile) doppelt vorkommen kann:= Entweder handelt es sich um einen Eingabefehler oder es gibt bsp. tats=C3=A4chlich zwei verschiedene Perso= nen mit demselben Vor- und Nachnamen, dann mu=C3=9F ein zus=C3=A4tzliches Attribut eingef=C3=BChrt werden, welches die Einde= utigkeit jeder Zeile sicherstellt. Statt Tabelle wird in der eher mathematisch orientierten Literatur auch von Re= lation gesprochen: Ein Gesch=C3=A4ftsvorfall stellt eine individuelle Relation zwischen verschi= edenen Attribut-Werten dar.

Ein Schl=C3=BCssel ist eine Menge von Attributen, mit d= em eine Datenzeile eindeutig identifiziert werden kann. Ein Schl=C3=BCssel-Kandidat ist ein Schl=C3= =BCssel mit minimaler Attribut-Anzahl. Eine Tabelle / Relation kann mehrere Schl=C3=BCssel-Kandidaten haben. Ei= n Prim=C3=A4r-Schl=C3=BCssel ist ein beliebig ausgew=C3=A4hlter Schl=C3=BCsselkandidat. Besteht dieser au= s mehreren Attributen, so wird er als zusammengesetzter Prim=C3=A4rschl=C3=BCssel bezeichnet.= Ein Schl=C3=BCssel-Attribut ist schlie=C3=9Flich ein Attribut, das zu mindestens einem Schl=C3=BCsse= l geh=C3=B6rt, ansonsten handelt es sich um ein Nicht-Schl=C3=BCssel-Attribut.

Ein Attribut B hei=C3=9Ft funktional abh=C3=A4ngig vom = Attribut A, falls zu einem Wert von Attribut A h=C3=B6chstens ein Wert von B geh=C3=B6rt. So sind Name (B) und Vornam= e (C) einer Person funktional abh=C3=A4ngig von der Personalnummer dieser Person. Ein Attribut B hei=C3=9Ft voll funktional abh=C3=A4= ngig vom Schl=C3=BCssel A, falls B funktional abh=C3=A4ngig ist von A, jedoch nicht schon funktional abh=C3= =A4ngig von einer Teilmenge von A ist. Besteht der Schl=C3=BCssel A nur aus einem Attribut und ist B funktional abh=C3=A4= ngig von A, so ist B bereits voll funktional abh=C3=A4ngig. Das Attribut C hei=C3=9Ft transitiv abh=C3=A4ngig von A= , falls es ein Nicht-Schl=C3=BCssel-Attribut B gibt, das funktional abh=C3=A4ngig ist von A und von dem C funktional abh=C3=A4= ngt. Ein Attribut B kann, im Gegensatz zur funktionalen Abh=C3=A4ngigkeit von A, auch mehrwertig abh=C3=A4n= gig von A sein. In diesem Fall gibt es mehrere Attribut-Werte B, die A zugeordnet sein k=C3=B6nnen= (Bsp.: mehrere Mailadressen einer Person).

Ziel der Normalisierung =C3=BCber die f=C3=BCnf Normalformen
ist es, zun=C3=A4chst atomare Attribute einzuf=C3=BChren und anschlie=C3=9Fend die Mengen von Schl=C3=BCsseln und Nichtschl=C3=BCssel-Attributen so der Rei= he nach zu identifizieren, da=C3=9F alle redundanten Beziehungen herausgezogen und in einzelne Tabellen ausgelagert werden. Die oben defi= nierten Begriffe der 'vollen funktionalen Abh=C3=A4ngigkeit' sowie der Transitivit=C3=A4t dienen dazu, Abh=C3=A4ng= igkeiten zwischen den Attributen aufzusp=C3=BCren und solche Wiederholungen zwischen verschiedenen Attributen in neue Tabellen auszul= agern. Das Ergebnis ist nicht mehr eine gro=C3=9Fe, redundante Tabelle, sondern viele kleine und schmale Tabellen, die durch verschiedenste Bezi= ehungen miteinander verkn=C3=BCpft sind. F=C3=BCr diese Beziehungen wird - leider - oftmals ebenfalls der Begriff = Relation verwendet, so da=C3=9F dieser Begriff sowohl f=C3=BCr Tabellen als auch f=C3=BCr Be= ziehungen zwischen Tabellen genutzt wird. Jede dieser Einzel-Tabellen kann um einen eigenen zus=C3=A4tzlichen Prim=C3=A4rschl=C3=BCssel erg=C3= =A4nzt werden, der als ganze Zahl implementiert, dessen Wert vom Datenbanksystem festgelegt und beim Einf=C3=BCgen neuer Datens=C3=A4= tze automatisch hochgez=C3=A4hlt wird. Wird in einer anderen Tabelle auf diese Tabelle bezug genommen, so gen=C3=BCgt es, eine zus=C3= =A4tzliche Spalte einzuf=C3=BCgen und diese als Fremdschl=C3=BCssel (foreign key) zu d= eklarieren.

Einschr=C3=A4nkungen auf der Ebene von Spalten F=C3=BCr eine einzelne Spalte k=C3=B6nnen - unabh=C3=A4ngig voneinander = - zwei Einschr=C3=A4nkungen deklariert werden:
  • Nicht Null / Not Null: Ein solche= s Feld darf nicht leer sein, es mu=C3=9F auf jeden Fall einen Wert erhalten.
  • Eindeutigkeit / UNIQUE: Jeder Wer= t in dieser Spalte mu=C3=9F innerhalb der Spalte eindeutig sein.
In beiden F=C3=A4llen gen=C3=BCgt es, das Feld bei der Erstellung mit di= esen Eigenschaften zu deklarieren bzw. bei einer bereits definierten Tabelle die Felddefinition zu =C3=A4ndern. Ab dann =C3= =BCberpr=C3=BCft das DBMS bei jedem Einf=C3=BCgungs- und Aktualisierungsversuch, ob die gesetzten Bedingungen durch den neu einzu= f=C3=BCgenden oder zu =C3=A4ndernden Datensatz mi=C3=9Fachtet werden und verhindert die ausl=C3=B6sende Operation gegeb= enenfalls.

Ist die Spalte als Prim=C3=A4rschl=C3=BCssel deklariert, so sind implizi= t beide Sondereigenschaften gesetzt: Ein Prim=C3=A4rschl=C3=BCssel darf nicht leer sein und er mu=C3=9F eindeutig= sein. Denn der Wert einer Prim=C3=A4rschl=C3=BCssel-Zelle ist f=C3=BCr diese Zeile eindeutig, damit sind mehrere leere oder doppelte W= erte ausgeschlossen.

Beziehungen zwischen Tabellen

Stehen mehrere Tabellen zueinander in Beziehung, so sind verschiedene Sz= enarien denkbar:
  • Basis- und Detail-Tabelle in eine= r 1:n-Beziehung: Zu einem Datensatz in der Basistabelle kann es keinen, einen oder mehre= re Datens=C3=A4tze in der Detailtabelle geben. Die Detailtabelle enth=C3=A4lt mehrwertige Attribute zur Basistabelle.<= p>

    So sollen zu Mitarbeitern Mailadressen hinzugef=C3=BCgt werden. Die Tab= elle der Mitarbeiter verwendet einen eigenen, zahlbasierten Prim=C3=A4rschl=C3=BCssel, da weder Nachname noch Nachnam= e + Vorname eindeutig sind. Es soll jedoch m=C3=B6glich sein, einem Mitarbeiter keine, eine oder mehrere Mailadressen zuzuweise= n. W=C3=BCrde f=C3=BCr jeden Mitarbeiter h=C3=B6chstens eine Mailadresse erfa=C3=9Ft, so w=C3=BCrde es gen=C3=BCgen, der Tabell= e 'Mitarbeiter' eine weitere Spalte hinzuzuf=C3=BCgen. Da jedoch beliebig viele Adressen zul=C3=A4ssig sein sollen, wird eine = Detailtabelle ben=C3=B6tigt.

    Basistabelle tbl_Mitarbeiter:

    Mitarbeiter-IDNameVorname=
    15MaierHorst
    16SchmidtSusanne
    18SchmidtFrank

    Detailtabelle tbl_MailAdressen mit Fremdschl=C3=BCssel von Mitarbeiter-= Id auf die gleichnamige Prim=C3=A4rschl=C3=BCsselspalte in tbl_Mitarbeiter:

    IDMitarbeiter-IdeMail
    215horst.maier@mustermann-ag.de
    315abt-1@mustermann-ag.de
    415maier@privatadressen-erdbewohner.de
    518frank.schmidt@mustermann-ag.de

    Damit wurden Horst Maier drei und Frank Schmidt eine Mailadresse zugewi= esen, f=C3=BCr Susanne Schmidt wurde keine Mailadresse aufgenommen.
  • Zwei Basis-Tabellen werden in einer Detail= -Tabelle durch eine n:m-Beziehung verkn=C3=BCp= ft: Es gibt zwei voneinander unabh=C3=A4ngige Basis-Tabellen und es gibt Ge= sch=C3=A4ftsvorf=C3=A4lle, bei welchen genau einem Datensatz der ersten Tabelle genau ein Datensatz der zweiten Tabelle zugewiesen wird. Jeder = Datensatz aus jeder Basistabelle kann beliebig oft an Gesch=C3=A4ftsvorf=C3=A4llen teilnehmen. Die n:m - Bezi= ehung wird also aufgel=C3=B6st in eine 1:m sowie in eine n:1 - Beziehung.

    Die Mitarbeiter der obigen Tabelle pflegen Kundenkontakte, jeder Kunden= kontakt soll mit Datum und Notiz aufgezeichnet werden. Ein Mitarbeiter kann viele Kunden beraten, ein Kunde kann mit v= ielen Mitarbeitern Kontakt haben.

    Basistabelle tbl_Kunden:

    =
    Kunden-IDNameVorname
    30M=C3=BCllerSilvia
    35BeckerKarl

    Detailtabelle tbl_Kundenkontakte mit Fremdschl=C3=BCssel-Einschr=C3=A4n= kungen von Mitarbeiter-Id auf tbl_Mitarbeiter sowie von Kunden-Id auf tbl_Kunden:

    IDMitarbeiter-IdKunden-Id= DatumNotiz
    2163520.04.2004Erstgespr=C3= =A4ch
    3153522.04.2004Tel. Verschi= ebung
    4163025.04.2004Besichtigung=
    5163528.04.2004Vertragsunte= rzeichnung

    Hier hat der Kunde Karl Becker drei Kontakte, zwei mit der Mitarbeiteri= n Susanne Schmidt sowie ein Telefonat mit Horst Mayer. Mitarbeiterin Susanne Schmidt f=C3=BChrt ferner eine Besic= htigung mit Kundin Silvia M=C3=BCller durch.
  • Eine Basis-Tabelle mu=C3=9F um diverse Spalten erg=C3=A4nzt werden,= die Zellen bleiben jedoch f=C3=BCr viele Zeilen leer. In diesem Fall ist es besser, eine zweite Tabelle zu definieren und die= se durch eine 1:1-Beziehung mit der ersten Tabelle zu verkn=C3=BCpfen. Nun werden in der Randtabell= e nur zu jenen Zeilen der Basis-Tabelle neue Zeilen eingef=C3=BCgt, falls zu dem Basis-Datensatz jene speziellen Inf= ormationen aufzuzeichnen sind:

    Es gibt die Tabelle tbl_Mitarbeiter mit s=C3=A4mtlichen Mitarbeitern (f= estangestellte und freie) und ihren Grunddaten. Zu den festangestellten Mitarbeitern sollen zus=C3=A4tzlich das Eintrittsdatum sowie Gehaltsinf= ormationen abgelegt werden.

    Randtabelle tbl_MitarbeiterInfos:

    Mitarbeiter-IDEintrittStu= fe
    1501.01.2000XI-2
    1601.05.2001X-3

    Hier wird die Spalte Mitarbeiter-Id zus=C3=A4tzlich (1) als Prim=C3=A4r= schl=C3=BCssel sowie (2) als Fremdschl=C3=BCssel auf die Tabelle tbl_Mitarbeiter deklariert, es existiert keine Spalte vom Typ A= uto-Wert. Durch die Auszeichnung als Prim=C3=A4rschl=C3=BCssel ist gew=C3=A4hrleistet, da=C3=9F zu jedem Mit= arbeiter h=C3=B6chstens ein Eintrag in tbl_MitarbeiterInfos existiert. Die Definition als Fremdschl=C3=BCssel stellt sicher, da=C3=9F= nur g=C3=BCltige Mitarbeiter-Id's verwendet werden.

    Mitarbeiter Nr. 18 / Frank Schmidt ist freier Mitarbeiter, f=C3=BCr ihn= existiert kein Eintrag in tbl_MitarbeiterInfos.

Konsequenzen bei der Nutzung von Fremdschl=C3=BCs= sel-Einschr=C3=A4nkungen

Werden bei der Definition einer Tabelle Fremdschl=C3=BCssel-Einschr=C3=A4= nkungen verwendet, so gelten zus=C3=A4tzlich die folgenden Regeln:
  • Das Ziel der Fremdschl=C3=BCsseleinschr=C3=A4nkung mu=C3=9F eine Sp= alte sein, die in der Basis-Tabelle Prim=C3=A4rschl=C3=BCssel ist. Denn ein Fremdschl=C3=BCssel bedeutet, da=C3=9F zur aktuellen Zeil= e genau eine Zeile der Basistabelle zugeordnet wird, folglich mu=C3=9F diese eindeutig identifizierbar sein.
  • Das DBMS stellt sicher, da=C3=9F in die mit einem Fremdschl=C3=BCss= el definierte Spalte der Detailtabelle nur Werte eingetragen werden k=C3=B6nnen, welche bereits in der Basistabell= e existieren.
  • Ein Datensatz in der Basistabelle, dessen ID bereits in der Detailt= abelle genutzt wird, kann nicht mehr gel=C3=B6scht werden. Um ein L=C3=B6schen zu erm=C3=B6glichen, m=C3= =BCssen zun=C3=A4chst alle auf dieser ID basierenden Detail-Datens=C3=A4= tze gel=C3=B6scht werden. Ausnahme: Das DBMS unterst=C3=BCtzt kaskadierende= s L=C3=B6schen und diese Option wurde beim Erstellen des Fremdschl=C3=BCssels aktiviert. In diesem Fall f=C3=BChrt ein L=C3=B6= schen einer Zeile in der Basistabelle zum automatischen L=C3=B6schen aller Detail-Zeilen.
  • Im Regelfall k=C3=B6nnen Spalten, die zu Fremdschl=C3=BCssel-Bez=C3= =BCgen geh=C3=B6ren, nicht umbenannt oder gel=C3=B6scht werden. Zun=C3=A4chst mu=C3=9F der Fremdschl=C3=BCssel gel=C3=B6scht und nach d= er Umbenennung wieder neu deklariert werden.
  • Da =C3=BCber Fremdschl=C3=BCssel-Spalten bei sp=C3=A4teren Abfragen= Tabellen wieder mit dem JOIN-Operator verkn=C3=BCpft werden, sind Fremdschl=C3=BCssel-Spalten gute Kandidaten f=C3=BCr Indiz= es zur Verbesserung der Leistung.

TOP

Erste Normalform: Attribute sollen atomar sein, w= iederholende Gruppen sind auszulagern

Die erste Normalform (NF1) ist durch z= wei Forderungen charakterisiert:
  1. Attribute m=C3=BCssen atomar sein. Das meint: Einem Attribut d=C3=BC= rfen nicht mehrere Werte aus dem definierten G=C3=BCltigkeitsbereich zug= eordnet sein.
  2. Wiederholende Gruppen, also mehrwertige Relationen, sind in eine ei= gene Tabelle auszulagern und zu verkn=C3=BCpfen.
Beispiele:
  • Trennen von Nachname, Vorname, eventuell Namenszusatz (... van der = ...) in ein eigenes Feld, also Vergr=C3=B6=C3=9Ferung der Zahl der Spalten. Wird beim Namenszusatz auf eine eigene Spalte ver= zichtet, so kann es sp=C3=A4ter zu inkonsistenten Eintr=C3=A4gen kommen. Einmal wird der Vorname um den Namenszusatz erg=C3= =A4nzt {Schmidt, Sybille van der}, andere Varianten sind {van der Schmidt, Sybille} oder {Schmidt van der, Sybille}. In s=C3= =A4mtlichen F=C3=A4llen k=C3=B6nnen bei Suchabfragen nach 'Schmidt' oder 'Sybille' Zeilen ignoriert werden, so da=C3=9F der = Datensatz nicht gefunden und ein zweites Mal eingetragen wird.
  • Schauspieler zu einem Film, an einem Projekt beteiligte Mitarbeiter= , Etagen in einem Haus, Zimmer einer Etage: Eine handschriftliche Aufzeichnung w=C3=BCrde die beteiligten Personen / Etagen / Zimmer der Reihe nach au= ff=C3=BChren, sie damit alle in eine Zelle schreiben. Die L=C3=B6sung, mehrere Spalten f=C3=BCr mehrere Teilnehmer usw. anzuf=C3=BCgen, ist un= geeignet, da entweder zu viele Zellen leer bleiben oder zu wenige Spalten vorhanden sind. Also wird eine Detailtabelle (Mitwirk= ende, Projektbeteiligte, Etagen, Zimmer) erstellt, die in einer n:1 - Beziehung zur Grundtabelle (Filme, Projekte, H=C3=A4= user, Etagen) steht. Die Gruppe dieser gleichartig strukturierten Detail-Informationen wird in diese Detail-Tabelle ausgel= agert.

Zuordnung von Werttypen / Datentypen zu Attribute= n

Um eine zus=C3=A4tzliche Konsistenz der atomaren Eintr=C3=A4ge zu erzwin= gen, werden den Attributen (=3D Spalten) Datentypen zugeordnet. Damit kann das DBMS bei allen Einf=C3=BCgungs- und Aktualisi= erungsoperationen =C3=BCberpr=C3=BCfen, ob die Eingabedaten dem geforderten Datentyp entsprechen und die Ausf=C3=BChrung der Operati= on gegebenenfalls untersagen.

Standard-Datentypen

  • binary(L=C3=A4nge): Bin=C3=A4rdaten fester L=C3=A4= nge. Dieser kann mit analogen Datentypen verwendet werden, um Bilder, Videos, Word- oder PDF-Dokumente abzuspeic= hern.
  • Boolean bzw. bit: Boolsche Wahr /= Falsch bzw. Ja / Nein - Werte. Dieser Werttyp eignet sich zur Darstellung von = zwei einander ausschlie=C3=9Fenden Werten und kann als Checkbox zum Anhaken oder Pulldown-Liste (Ja/Nein) dargest= ellt werden.
  • char(L=C3=A4nge): Zeichenfolge (1-Byte-Zeichen) mi= t fester L=C3=A4nge (char(5) =3D f=C3=BCnf Zeichen). Dies erlaubt nur Zeichen aus dem Ascii bzw. den ISO-Codierungen, so da= =C3=9F maximal 256 verschiedene Zeichen gespeichert werden k=C3=B6nnen.
  • datetime: Datums- und Zeitfelder. Beide Informatio= nen werden gemeinsam gespeichert. Wurde nur das Datum angegeben, so wird als Zeit '00:00:00' genommen, b= ei einer reinen Zeitangabe wird meist als Bezugsdatum der 01.01.1900 verwendet. Jedes DBMS kennt Funktionen,= mit welchen aus einem datetime-Feld nur der Datums- oder nur der Zeitanteil herausgezogen werden kann. Ebe= nso gibt es in jedem DBMS Funktionen f=C3=BCr Datumsoperationen, mit welchen Datumsangaben addiert oder Dat= ums-Differenzen ausgegeben werden k=C3=B6nnen.
  • decimal[(p[, s])], Synonym numeric: Dezimal-Datentyp f=C3=BCr numerische Datentypen mit einer fest vorgegebenen Genauigkeit = und fest definierten Anzahl von Dezimalstellen. p legt die Zahl aller Stellen vor und nach dem Dezimalpunkt fest und kann =C3=BC= blicherweise zwischen 1 und knapp 40 liegen. s fixiert die Nachkommastellen und liegt zwischen 0 und p. s =3D 0 bedeutet, da=C3= =9F der Datentyp nur Ganzzahlen akzeptiert. decimal(15,5) deklariert einen Datentyp mit f=C3=BCnf Nachkomma- und ma= ximal 10 Vorkomma-Stellen.
  • float bzw. real: Ungef=C3=A4hre Z= ahlendatentypen, die f=C3=BCr numerische Gleitkomma-Daten genutzt werden k=C3=B6nnen. I= ntern werden diese in der wissenschaftlichen Darstellung 5.79E2 dargestellt, also als 5.79 * 10^2 =3D 579. Diese Da= tentypen sind ungef=C3=A4hr, da nicht alle Werte im zul=C3=A4ssigen Zahlbereich genau dargestellt werden. float i= st in der Regel doppelt so genau wie real und ben=C3=B6tigt 8 statt 4 Byte.
  • image: Binary-Daten variabler L=C3=A4nge, meist mi= t einer maximalen L=C3=A4nge in der Gr=C3=B6=C3=9Fenordnung 2^31
  • int bzw. Integer: Ganzzahl mit ne= gativen oder positiven Werten. Im Regelfall mit 4 Byte implementiert, damit kann ein Wertebereich von +/- 2^31, al= so -2.147.483.648 bis +2.147.483.648 abgedeckt werden. Ist eine Spalte als Prim=C3=A4rschl=C3=BCssel defini= ert, so hat sie diesen Datentyp, eine Spalte mit einer Fremdschl=C3=BCsseleinschr=C3=A4nkung mu=C3=9F dementspreche= nd ebenfalls vom Typ Integer sein.
  • money: W=C3=A4hrungsdatentyp. W=C3=A4hrungen werde= n mit hinreichend vielen Nachkomma-Stellen gespeichert
  • nchar(L=C3=A4nge): Unicode-Zeichenfolge mit fester= L=C3=A4nge, ben=C3=B6tigt zwei Byte pro Zeichen.
  • ntext: Unicode-Zeichenfolge variabler L=C3=A4nge, = in der Regel bis zu 2^30 Zeichen.
  • nvarchar(L=C3=A4nge): Unicode-Zeichenfolge variabl= er L=C3=A4nge, beim Ms-Sqlserver beschr=C3=A4nkt auf 4000 Zeichen.
  • text: Nicht-Unicode-Zeichenfolge variabler L=C3=A4= nge, in der Regel bis zu 2^31 Zeichen.
  • varbinary(L=C3=A4nge): Binary-Daten variabler L=C3= =A4nge zwischen 0 und dem durch 'L=C3=A4nge' festgelegten Wert. Beim Ms-SqlServer existiert eine zus=C3= =A4tzliche Obergrenze von 8000 Zeichen.
  • varchar(L=C3=A4nge): Zeichenfolge (1-Byte-Zeichen)= mit variabler L=C3=A4nge, maximal der durch 'L=C3=A4nge' festgelegte Wert.

Spezielle Datentypen

  • timestamp: Ein datenbankweit eindeutiger Ausdruck,= der bei jeder =C3=84nderung der Daten automatisch hochgez=C3=A4hlt wird. Wird einer Tabelle eine S= palte vom Typ timestamp hinzugef=C3=BCgt, so kann diese zur Versionskennung der Zeile verwendet werden. Beim Lesen = der Daten wird dieser Wert mitgesandt, beim Schreiben geht der timestamp-Wert zusammen mit dem Prim=C3=A4rsch= l=C3=BCssel in die Where-Bedingung ein. Hat ein anderer Nutzer in der Zwischenzeit diese Zeile ge=C3=A4ndert, so schei= tert die Aktualisierung.
  • uniqueidentifier: Ein global eindeutiger Bezeichne= r (GUID, Global unique Identifier). Auto-Werte sind nur innerha= lb der Tabelle eindeutig. Werden global eindeutige Werte ben=C3=B6tigt, so k=C3=B6nnen GUID's genutzt un= d in uniqueidentifier-Spalten abgelegt werden. Die Verwendung als Prim=C3=A4rschl=C3=BCssel ist jedoch nicht zu empfeh= len, da die Indizes, welche den Prim=C3=A4rschl=C3=BCssel nutzen, dann sehr gro=C3=9F werden.
  • int Identity(1, 1), eine Identit=C3=A4tssp= alte: Dies definiert eine Spalte vom Typ Integer, die zus=C3=A4tzlich einen Identit=C3=A4ts= wert erh=C3=A4lt, eine Zahl, die vom DBMS automatisch hochgez=C3=A4hlt u= nd deren Eindeutigkeit damit garantiert ist. Solche Spalten sind gute Kan= didaten f=C3=BCr Prim=C3=A4rschl=C3=BCssel. Die erste Zahl legt den Startwert fest, die zweite Zahl deklariert die Schrittweite. Werden Da= tens=C3=A4tze eingef=C3=BCgt, so wird =C3=BCblicherweise f=C3=BCr eine Identit=C3=A4tsspalte kein Wert angegeben. MsAccess l=C3=A4=C3=9Ft es = zu, da=C3=9F ein Wert angegeben wird, sofern dieser bislang noch nicht verwendet wurde. Beim Ms-Sqlserver mu=C3=9F zuvor die Spalte mit SET IDENTITY_INSERT <Tabellenname> ON f=C3=BCr solche Aktionen zugelassen und anschlie=C3=9Fend mit 'OFF' wi= eder deaktiviert werden.

    Ver=C3=A4nderte Schrittweiten lassen sich bsp. dann verwenden, falls s= p=C3=A4ter Zeilen eingef=C3=BCgt werden, bei welchen bereits an der Id deutlich werden soll, da=C3=9F es sich um besondere Objekte han= delt. So legt eine Anweisung 'int Identity(2, 2)' fest, da=C3=9F nur die Zahlen 2, 4, 6, ... f=C3=BCr das automatische E= inf=C3=BCgen vom Benutzer verwendet werden k=C3=B6nnen. Vom System eingef=C3=BCgte Zeilen m=C3=B6gen ungerade Zahlen erhalten. Ein sp=C3=A4= terer Test modulo 2 unterscheidet beide Typen.

Hinweise zum Gebrauch der Datentypen

  • Verwenden Sie als Prim=C3=A4rschl=C3=BCssel den Integer-Datentyp, m= eist kombiniert mit einer automatischen Erh=C3=B6hung. Vermeiden Sie Zeichendaten als Prim=C3=A4rschl=C3=BCssel= . Zum einen werden Integer mit einer festen Gr=C3=B6=C3=9Fe abgespeichert. Zum anderen gen=C3=BCgt ein Bit-f=C3=BCr= -Bit-Vergleich, da keine Gro=C3=9F-Klein-Schreibung ber=C3=BCcksichtigt werden mu=C3=9F. Damit ist der Vergleich zwischen zwei Integer-Zellen a= uf jeden Fall schneller als zwischen zwei Text-Zellen. Schlie=C3=9Flich wird der Prim=C3=A4rschl=C3=BCssel b= ei anderen Indizes verwendet. Lange Textfelder bl=C3=A4hen diese Indizes unn=C3=B6tig auf. Der Aufwand f=C3=BCr eine zus=C3=A4tzli= che Spalte d=C3=BCrfte immere gering im Vergleich zu solchen Seiteneffekten sein. Die Eindeutigkeit einer Spalte (etwa Telef= onnummern) l=C3=A4=C3=9Ft sich auch mit einer UNIQUE-Einschr=C3=A4nkung in Kombination mit NOT NULL erzwingen.
  • F=C3=BCr Telefonnummern sind in der Regel char- oder varchar-Datent= ypen notwendig. W=C3=BCrden stattdessen Integer-Werte genutzt, so w=C3=BCrden f=C3=BChrende Nullen entfernt wer= den. Telefonnummern oder isoliert abgelegte Hausnummern sollten ohne Leerzeichen abgespeichert und die bei der Such= e vom Nutzer eingegebenen Leerzeichen entfernt werden. Ansonsten k=C3=B6nnten Werte nicht gefunden werden.
  • Bei der Verwendung von Unicode-Datentypen (nchar, nvarchar, ntext) = anstelle der gew=C3=B6hnlichen Text-Datentypen (char, varchar, text) ist zu beachten, da=C3=9F diese z= war korrekt gespeichert werden, die Anzeige jedoch fehlerhaft sein kann. De= nn wird zur Anzeige nicht ein passender Unicode-Font genutzt, so werden Unicode-Zeichen oberhalb Asci= i nur als leere Quadrate dargestellt. Hier ist bsp. im Ms-Access-Formular als Font 'MS Arial Unicode' zu verw= enden. Im deutschen bzw. europ=C3=A4ischen Sprachraum bzw. f=C3=BCr eine nur in dieser Region verwendeten Datenban= k kann es gen=C3=BCgen, nur Ascii-Texte zuzulassen. F=C3=BCr internationale Namen, Produktbeschreibungen in verschiedenen S= prachen oder wissenschaftliche Texte, bei welchen Sonderzeichen aus verschiedenen ISO-Codepages ben=C3=B6tigt wer= den, sollten sofort Unicode-Datentypen verwendet werden.
  • Ein Nachteil von Unicode beim Einsatz auf dem Ms-SqlServer ist zu b= eachten: Dort betr=C3=A4gt die maximale Datengr=C3=B6=C3=9Fe pro Zeile etwa 8000 Byte. Man kann folglich Ascii-= Texte bis zu 8000 oder Unicode-Text bis 4000 Zeichen ablegen. Sollte sich eine Tabelle dieser Grenze ann=C3=A4hern, so kann = man nach dem Muster der 1:1 - Beziehung Texte mit nvarchar-Datentyp auch in eine Nebentabelle auslagern.
  • Die Verwendung der binary large object (BL= OB) Datentypen text-, ntext- und image-Daten bedeutet, da=C3=9F in der Zeil= e nur ein Zeiger gespeichert und der eigentliche Inhalt ausgelagert wird. Damit sind zwar einerseits= hinreichend gro=C3=9Fe Daten verwaltbar, jedoch k=C3=B6nnen diese Daten nicht in einer =C3=BCblichen Where-Klaus= el genutzt werden. Auf text/ntext l=C3=A4=C3=9Ft sich allerdings der LIKE-Operator anwenden. Beim Ms-SqlServer ist es m=C3=B6glich, dies= e BLOB-Datentypen in einer eigenen Dateigruppe abzulegen, so da=C3=9F die Dateigruppe f=C3=BCr die Hauptdaten hiervon unabh=C3=A4ngi= g ist.
  • Allgemein wird davon abgeraten, Bilder, Videos und =C3=A4hnliches i= n Datenbank-Spalten abzulegen. Denn die eigentlichen St=C3=A4rken eines DBMS wie Vergleiche, Filterung und = Sortierung k=C3=B6nnen bei BLOB-Daten ohnehin kaum verwendet werden. Diese bl=C3=A4hen jedoch die Datenbank unn=C3=B6tig a= uf und erschweren damit Sicherungen. Da BLOB-Daten normalerweise nur sehr selten ge=C3=A4ndert werden, ist es sinnvoller, = diese im Dateisystem abzulegen und lediglich relative Pfadangaben sowie das Datum der letzten Aktualisierung in der = Datenbank zu speichern.

TOP

Zweite Normalform - volle funktionale Abh=C3=A4ng= igkeit der Attribute vom Prim=C3=A4rschl=C3=BCssel

Ein System von Tabellen ist dann in der zweiten Normalform (NF2), wenn die Tabellen in der ersten Normalform sind und wenn zus=C3=A4tzlich alle Nichtschl=C3= =BCssel-Attribute voll funktional vom Prim=C3=A4rschl=C3=BCssel abh=C3=A4ngig sind. Umgekehrt formuliert hei=C3=9Ft dies: Eine Tabelle i= st noch nicht in zweiter Normalform, wenn sie einen zusammengesetzten Prim=C3=A4rschl=C3=BCssel hat und ein Nichtschl=C3= =BCssel-Attribut nicht vom ganzen Prim=C3=A4rschl=C3=BCssel, sondern nur von einem Teilschl=C3=BCssel abh=C3=A4ngt. In diesem Fall wi= rd das Nichtschl=C3=BCssel-Attribut mit dem Prim=C3=A4rschl=C3=BCssel-Te= il, von dem es funktional abh=C3=A4ngig ist, in eine eigene Tabelle herausge= zogen.

Am einem Ausschnitt von Beispiel 1 deutlich gemacht, die notwendige Zerl= egung von V_NAME und V_ANSCH wird aktuell ignoriert:

U_NRA_NAMEA_PREISA_STUECKDATUMV_NAMEV_ANSC= H
1Oberhemd39,804024.06.1999Meyer, EmilWendeweg 10, 2800 Bremen
2Mantel360,001024.06.1999Meier, FranzKohlstr. 1, 2800 Bremen
3Oberhemd44,207024.06.1999Meyer, EmilWendeweg 10, 2800 Bremen
4Oberhemd44,202025.06.1999Schulze, FritzGem=C3=BCseweg 3, 2800 Bremen

Offenkundig ist es wesentlich, welcher Vertreter diesen Umsatz erbracht = hat. Also geh=C3=B6rt bei einer Umsatz-Zeile die Spalte V_NAME zum Schl=C3=BCssel mit hinzu. Die Vertreteranschrift V= _ANSCH hat jedoch nichts mit dem aktuellen Umsatz zu tun, ist also ein Nicht-Schl=C3=BCssel-Attribut. V_ANSCH h=C3=A4ngt nur von V_NAME, ni= cht vom einzelnen Umsatz, dessen Datum oder dem beteiligten Artikel ab - im Gegensatz zu A_STUECK, das offenbar f=C3=BCr= die einzelne Umsatzzeile charakteristisch ist. Also k=C3=B6nnen V_NAME und V_ANSCH in eine kleine Tabelle herausgezogen und um einen Pri= m=C3=A4rschl=C3=BCssel erg=C3=A4nzt werden, der in eine zus=C3=A4tzliche= Spalte hinzugef=C3=BCgt wird.

Wurden die beteiligten 'Handlungspartner' oder die 'agierenden Instanzen= ' korrekt identifiziert und in eigene Tabellen ausgelagert, so scheint die zweite Normalform trivial zu sein. Denn sie = ist automatisch erf=C3=BCllt, wenn die Attribute, also die Spalten einer= Tabelle, 'sinnvoll' zum Prim=C3=A4rschl=C3=BCssel geh=C3=B6ren und der Prim=C3=A4= rschl=C3=BCssel aus einer Spalte besteht, es also keinen zusammengesetzt= en Prim=C3=A4rschl=C3=BCssel gibt.

Um ein interessantes Beispiel f=C3=BCr die Nicht-Erf=C3=BCllung der zwei= ten Normalform zu finden, mu=C3=9F nach einem Beispiel gesucht werden, bei dem ein Attribut scheinbar von einem zusamm= engesetzten Schl=C3=BCssel abh=C3=A4ngt, eine tiefere Analyse jedoch lehrt, da=C3=9F das Attribut in Wirklichkeit nur = von einem Teilschl=C3=BCssel abh=C3=A4ngt.

Betrachtet man die obige Tabelle, so liegt es nahe, die Artikel mit ihre= n Preisen in eine eigene Tabelle herauszuziehen und durch eine Spalte mit den Artikelnummern zu ersetzen. Wird dasselbe = mit den Vertreter-Informationen durchgef=C3=BChrt, so ergibt sich die bereits bekannte Tabelle UMSATZ:

=
UMSATZ_NRV_NRA_NRA_STUECKDAT= UM
18413124024.06.1999
25016221024.06.1999
38413117024.06.1999
41215112025.06.1999
55016223525.06.1999
68413133524.06.1999
7121513524.06.1999
81215121024.06.1999
98413112025.06.1999

Es gibt also Artikel mit festen Preisen, ein eindeutiger Schl=C3=BCssel = in der Tabelle UMSATZ ist eine Kombination aus V_NR, A_NR, A_STUECK und DATUM. Da sich eine solche Aufteilung gut e= ignet, um Erfahrungen mit dem Sql-Select-Befehl zu sammeln, wurde diese Normalisierung den befehlsbezogenen Beispielen z= ugrundegelegt.

Ein Problem dieser zun=C3=A4chst plausiblen Aufteilung wird deutlich, fa= lls sich der Preis eines Artikels =C3=A4ndert. Wird dies direkt in der Tabelle ARTIKEL durchgef=C3=BChrt, so werden auch ber= eits abgeschlossene Verk=C3=A4ufe ge=C3=A4ndert, dies ist offenkundig falsch. Um dieses Problem zu vermeiden, k=C3=B6nnte man den = Preis in der UMSATZ-Tabelle belassen, also die folgende Tabelle verwenden:

UMSATZ_NRV_NRA_NRA_STUECKA_P= REISDATUM
18413124039.8024.06= .1999
250162210360.0024.0= 6.1999

Damit ist A_PREIS ein Nichtschl=C3=BCssel-Attribut in der Tabelle UMSATZ= . W=C3=BCrden nach diesem Muster viele Einzelums=C3=A4tze aufgezeichnet werden, so sind zwei Alternativen denkbar.
  • Der Preis eines Artikels =C3=A4ndert sich jede Minute. Man denke an= den Preis eines Artikels, der von W=C3=A4hrungsschwankungen abh=C3=A4ngt und dessen Preis sich aus dem a= ktuellen, minutengenauen W=C3=A4hrungsverh=C3=A4ltnis ergibt. In diesem Fall ist der Preis ein unabh=C3=A4ngiges Nicht-Schl=C3=BCssel-Attribut= von Datum und Uhrzeit, ein Artikel kann an einem Tag zu verschiedenen End-Preisen verkauft werden. A_PREIS w=C3= =A4re ein korrektes Attribut in der Tabelle UMSATZ.
  • Der Preis eines Artikels =C3=A4ndert sich h=C3=B6chstens einmal pro= Tag oder h=C3=B6chstens zu einem Termin in der Woche bzw. zu Monatsbeginn. In diesem Fall ist der Preis nicht von der Uhrzei= t, sondern vom Datum abh=C3=A4ngig, das Datum ist ein Schl=C3=BCsselattribut. Derselbe Artikel wird zwar ni= cht an allen, jedoch an vielen aufeinanderfolgenden Tagen zu demselben Preis verkauft. Damit ist der Preis als Nicht-Schl=C3= =BCssel-Attribut nicht abh=C3=A4ngig vom gesamten, zusammengesetzten Schl=C3=BCssel, sondern blo=C3=9F abh=C3=A4= ngig von der Kombination aus Datum und Artikel-Nummer, unabh=C3=A4ngig dagegen vom Vertreter. Man w=C3=BCrde eine neue Tabelle erstellen, die = wie folgt aussieht:

    A_NRDATUMA_PREIS
    1101.06.199944.20
    1201.06.199939.80
    1125.06.199929.90
    1127.06.199944.20

    Hier sind A_NR und DATUM die beiden Schl=C3=BCsselspalten, A_PREIS ist = Nicht-Schl=C3=BCsselattribut. Der Artikel mit der Nummer 11 wurde am 25.06.1999 f=C3=BCr zwei Tage mit einem redu= zierten Preis angeboten. Die Tabelle UMSATZ beh=C3=A4lt die Spalten A_NR sowie DATUM, die Spalte A_PREIS wird entfe= rnt.
Man sieht an diesem Beispiel, da=C3=9F die Frage nach abh=C3=A4ngigen At= tributen nicht ausschlie=C3=9Flich unter mathematischen Gesichtspunkten oder anhand vorhandener Daten entschieden werden kann. B= ei Preisen, die =C3=BCber lange Zeitr=C3=A4ume stabil sind, k=C3=B6nnten die Preise auch in der Artikel-Tabelle belassen werde= n und bei Preis=C3=A4nderungen ein neuer Artikel eingef=C3=BChrt werden. Ebenso k=C3=B6nnten die aktuellen Werte von A_NAME (Hose, Mantel= , Oberhemd) in eine schmale, zwei Spalten (Id und Begriff) umfassende Tabelle herausgezogen werden und als Kategor= ie-Begriffe verwendet werden. Ein Artikel ist dann nur noch durch eine Nummer gekennzeichnet, ihm wird eine Katego= rie und ein Preis in ARTIKEL zugeordnet, bei einer Preis=C3=A4nderung wird ein neuer Artikel definiert. Werden da= gegen Lagerbest=C3=A4nde mitber=C3=BCcksichtigt, so darf diese Technik des 'neuen Artikels' bei einer Preis=C3=A4nderung offenkundig ni= cht verwendet werden, da das einzelne Objekt nicht verschwunden ist, sondern nur einen anderen Preis erh=C3=A4lt.

TOP

Dritte Normalform - ein Nicht-Schl=C3=BCssel-Attr= ibut darf nicht von einem Schl=C3=BCssel und einem anderen Nicht-Schl=C3= =BCssel abh=C3=A4ngen

Die dritte Normalform (NF3) verlangt, = da=C3=9F bei allen in der Datenbank definierten Tabellen, die bereits in der zweiten Normalform sind, kein Attribut C existiert, das b= ereits funktional von einem Nicht-Schl=C3=BCssel-Attribut B abh=C3=A4ngt= . Denn da das Attribut C zur Tabelle geh=C3=B6rt, sollte es vom Prim=C3=A4rschl=C3= =BCssel A dieser Tabelle voll funktional abh=C3=A4ngig sein. A umfa=C3=9F= t nur ein Attribut, da die Tabelle bereits in der zweiten Normalform ist. Ist = C jedoch zus=C3=A4tzlich vom Nicht-Schl=C3=BCssel-Attribut B abh=C3=A4ng= ig und ist das Nicht-Schl=C3=BCssel-Attribut vom Prim=C3=A4rschl=C3=BCss= el A abh=C3=A4ngig, so ist die Folgerung A -> C zwingend. Das transitiv ab= h=C3=A4ngige Attribut C und das Attribut B bilden eine neue, bislang noch nicht in einer eigenen Tabelle isolierte Relation. Di= ese kann aus der aktuellen Tabelle herausgezogen werden, in die aktuelle Tabelle wird nur noch Attribut B bzw. der Prim=C3=A4rsch= l=C3=BCssel der neu gebildeten Tabelle eingetragen.

Der Unterschied zur vollen funktionalen Abh=C3=A4ngigkeit der zweiten No= rmalform besteht darin, da=C3=9F es sich hier um eine zus=C3=A4tzliche Beziehung zwischen zwei Nicht-Schl=C3=BCssel-Attri= buten handelt. Die Frage nach der zweiten Normalform lautet dagegen, ob ein Nicht-Schl=C3=BCssel-Attribut vom gesamten Schl=C3= =BCssel oder nur von einem Teilschl=C3=BCssel abh=C3=A4ngt. Falls letzteres der Fall ist, wird das Attribut in eine bereits vorhandene Tab= elle, in welcher der Teilschl=C3=BCssel der Prim=C3=A4rschl=C3=BCssel ist, verschoben.

Betrachten Sie den folgenden Ausschnitt aus dem urspr=C3=BCnglichen Beis= piel 2:

lfNrLiefer-NrDatum Artikel (E)LieferantEPZahl Artikel (V)Empf=C3=A4ngerEPZahl
12415.2.2003 Hosen, blauFA Muster-Liefer GbR, N=C3=BCrnberg39.9= 050
22415.2.2003 Hose, braunFA Muster-Liefer GbR, N=C3=BCrnberg39.9= 050

Zun=C3=A4chst ist offensichtlich, da=C3=9F der Lieferant herausgezogen u= nd die Adresse aufgesplittet wird. In die aktuelle Tabelle wird lediglich die Lieferanten-Nummer eingetragen. Dann k=C3=B6n= nen Artikel-Namen und Farbbezeichnungen in schmale, zweispaltige Tabellen bestehend aus Id und Begriff, ausgelagert werden. = Dies erlaubt es, f=C3=BCr die Eingabe Pulldown-Felder zu nutzen und vermeidet Fehler aufgrund von Rechtschreib-Problemen bei d= er Texteingabe. Die Tabelle sieht wie folgt aus:

Zahl
lfNrLiefer-NrDatum Artikel-NrFarb-IdLieferanten-IdEP

Es f=C3=A4llt auf, da=C3=9F eine Lieferung, durchgef=C3=BChrt an einem Tag, aus mehreren Artikeln bestehen kann, so da=C3=9F mehrere Zeilen die= selbe Liefer-Nummer und dasselbe Datum enthalten sowie sich auf einen Lieferanten beziehen. Besteht jede Lieferung nur au= s einem Artikel, so ist die Spalte Liefer-Nr =C3=BCberfl=C3=BCssig und k=C3=B6nnte entfernt bzw. durch 'lfNr' ersetzt= werden. Besteht eine Lieferung aus mehreren Artikeln, so sind Datum und= Lieferanten-Nummer abh=C3=A4ngig von der Liefer-Nummer. Der Artikel, sein Einkaufspreis und= die Artikel-Anzahl h=C3=A4ngen jedoch nur vom Prim=C3=A4rschl=C3=BCssel= dieser Zeile ab und unterscheidet sich von anderen Zeilen, die zu dersel= ben Lieferung geh=C3=B6ren. Also kann eine Tabelle gebildet werden, welche die Grunddaten jeder Lieferung enth=C3=A4lt. Eine auf dieser basi= erende Detailtabelle 'Lieferdetails' beinhaltet pro Zeile eine Kombination aus Artikel, Farbe und Preis. Damit ergibt sich f=C3=BCr die= Lieferungen die folgende Aufteilung:

Tabelle tbl_Lieferungen:

Liefer-NrDatumLieferanten-Id

Tabelle tbl_Lieferdetails:

lfNr-DetailsLiefer-NrArtikel-NrFarb-N= rEPZahl

Die detaillierte Betrachtung einzelner Liefer-Details f=C3=BChrt zum Sic= htbar-Werden von Wiederholungen, so da=C3=9F ein neues 'Objekt' 'Bestell-Rahmendaten', 'Grundtatsachen einer Lieferun= g' identifiziert und in eine eigene Tabelle ausgelagert wird. Beachten Sie, da=C3=9F dies nur dann gilt, fal= ls tats=C3=A4chlich eine Lieferung aus mehreren Artikeln besteht. Selbstverst=C3=A4ndlich sind Szenarien denkbar, in wel= chen dies nicht gilt - dann ist eine solche zus=C3=A4tzliche, eingeschobene Tabelle redundant.

Ein Beispiel mit partieller Abh=C3=A4ngigkeit Betrachten Sie die folgende denormalisierte Tabelle:

DatumStrasseHausEtageWohnung= Z=C3=A4hlerStandMitarbeiter

Ein Mitarbeiter eines Strom- oder Gaslieferanten liest diverse Strom- od= er Gasz=C3=A4hler ab. Zur Stra=C3=9Fen-Id geh=C3=B6ren viele H=C3=A4user, zu jedem Haus mehrere Etagen, zu jeder Etage mehrere = Wohnungen. In jeder Wohnung befindet sich ein Z=C3=A4hler mit einer eindeutigen Nummer. Dessen Stand wird zu einem fes= tgelegten Datum turnusgem=C3=A4=C3=9F von verschiedenen Mitarbeitern abg= elesen.

Jede Zeile kann eindeutig durch die beiden Spalten Datum und Z=C3=A4hler= nummer identifiziert werden. Denn jeder Z=C3=A4hler wird an einem Tag h=C3=B6chstens einmal abgelesen. Damit bilden diese be= iden Spalten den zusammengesetzten Prim=C3=A4rschl=C3=BCssel. Die Mitarbeiter-Id h=C3=A4ngt nat=C3=BCrlich von diesem Gesch=C3=A4ftsvo= rfall der Z=C3=A4hler-Ablesung ab. Die Stra=C3=9Fe ist ein nur vom Z=C3=A4= hler, nicht vom Datum abh=C3=A4ngiges Attribut. Denn von der Z=C3=A4hlernummer= ausgehend ist die Stra=C3=9Fe =C3=BCber die Wohnung, Etage und das Haus= festgelegt. Zum Erreichen der zweiten Normalform werden deshalb Wohnung, Etage, Haus= und Stra=C3=9Fe herausgezogen, all diese Werte sind durch die Z=C3=A4hler-Id festgelegt. Bei der zweiten Normalform erg= ibt sich damit die folgende Tabelle:

=
DatumZ=C3=A4hlerStandMitarbeiter

Werden in diese Tabelle viele Zeilen eingetragen, so wird eine zus=C3=A4tzliche Regelm=C3= =A4=C3=9Figkeit sichtbar: Ein Mitarbeiter sammelt an einem Tag Informationen von allen H=C3=A4usern einer Stra=C3=9Fe. Die Sp= alte Mitarbeiter ist also bereits determiniert durch die Kombination aus Datum und Hausnummer und wird bsp. im Rahmen e= iner Arbeitsverteilung in voraus festgelegt. Oder die Mitarbeiter sind von vornherein Ablesebereichen zugeteilt, so d= a=C3=9F - unabh=C3=A4ngig vom Datum - bekannt ist, welcher Mitarbeiter f=C3=BCr die Ablesung innerhalb eines Intervalls zus= t=C3=A4ndig ist. Im datumsfreien Fall gilt also die folgende transitive Abh=C3=A4ngigkeit:

Z=C3=A4hler ―> Stra=C3=9Fe ―> Mitarbeiter

Hier kann das Attribut 'Mitarbeiter' zur Tabelle 'Stra=C3=9Fe' hinzugef=C3= =BCgt und aus der aktuellen Tabelle entfernt werden. F=C3=BCr diese Stra=C3=9Fe ist jener Mitarbeiter zust=C3=A4ndig. Bei der= Version mit Datum gilt:

Z=C3=A4hler ―> Stra=C3=9Fe
Datum + Stra=C3=9Fe―> Mitarbeiter

Hier gibt es eine neue Tabelle mit Stra=C3=9Fen-Id und Datum als Prim=C3= =A4rschl=C3=BCssel sowie der Mitarbeiter-Id als Nicht-Schl=C3=BCssel-Att= ribut. Die Stra=C3=9Fe darf nicht zur normalisierten Tabelle mit Datum, Z=C3=A4= hler und Z=C3=A4hlerstand hinzugenommen werden, weil sie vom Z=C3=A4hler voll funktional abh=C3=A4ngig ist. Die restlichen Spalten werden gem=C3=A4=C3=9F der 1:n - Beziehung kanoni= sch normalisiert, so da=C3=9F sich insgesamt die folgende Tabellenstrukt= ur ergibt:

Strassen-IdOrtNameweitere f=C3=BCr St= ra=C3=9Fen typische Eigenschaften

Haus-IdStrassen-IdHausnummerweitere f= =C3=BCr H=C3=A4user typische Eigenschaften

Etagen-IdHaus-IdEtagennummerweitere f= =C3=BCr Etagen typische Eigenschaften

Wohnungs-IdEtagen-IdHauptmieterweiter= e f=C3=BCr Wohnungen typische Eigenschaften

Z=C3=A4hler-IdWohnungs-IdWerksnummer - 10-stel= lig mit Buchstabenweitere f=C3=BCr Z=C3=A4hler typische Eigensc= haften

Die neu identifizierte Tabelle mit Datum und Stra=C3=9Fen-Id als Prim=C3= =A4rschl=C3=BCssel:

DatumStra=C3=9Fen-IdMitarbeiter

Die Tabelle mit den eigentlichen Ablesedaten sieht nun wie folgt aus:

=

DatumZ=C3=A4hler-IdZ=C3=A4hlerstandBe= merkungen

Erl=C3=A4uterungen zum Verh=C3=A4ltnis zwischen d= er zweiten und der dritten Normalform

Die Notwendigkeit der ersten Normalform d=C3=BCrfte den meisten Lesern u= nmittelbar einleuchten. Die Forderung nach dem Erf=C3=BCllen der zweiten und der dritten Normalform bzw. nach dem Unter= schied zwischen beiden Normalformen d=C3=BCrfte dagegen eher irritieren, da es sich hierbei um relativ stark mathematisch gepr=C3= =A4gte Konzepte handelt. Es folgen deshalb einige erl=C3=A4uternde Bemerkungen.
  • Die zweite Normalform verlangt, da=C3=9F Attribute in den korrekten= Tabellen untergebracht sind. Normalerweise lassen sich einige 'statische Entit=C3=A4ten' rasch identifizieren und = in eigene Tabellen mit Prim=C3=A4rschl=C3=BCsseln exportieren. Dann kann es zus=C3=A4tzliche Bewegungsdaten geben, we= lche diese Grunddaten, oft zeitpunktgebunden, miteinander verkn=C3=BCpfen. Eine solche Tabelle enth=C3=A4lt einige Fr= emdschl=C3=BCssel auf die Grundtabellen sowie zus=C3=A4tzliche Spalten. Damit umfa=C3=9Ft ein Schl=C3=BCssel-Kandidat mehrere Attribute. Bei de= n Nicht-Schl=C3=BCssel-Attributen mu=C3=9F gepr=C3=BCft werden, ob sie t= ats=C3=A4chlich zum aktuellen Gesch=C3=A4ftsvorfall oder zu einer der Grundtabellen geh= =C3=B6ren, falls es sich um zeitlich unver=C3=A4nderliche Eigenschaften handelt. =C3=84ndern sie sich dagegen in gr=C3=B6=C3=9Feren Abst=C3=A4n= den, so da=C3=9F zu verschiedenen Gesch=C3=A4ftsvorf=C3=A4llen derselbe = Attributwert geh=C3=B6rt, dieses jedoch nicht einer Grundtabelle zugewiesen werden kann, so ist d= as Attribut in eine eigene Tabelle herauszuziehen.
  • Die dritte Normalform entspricht im wesentlichen der Forderung, 'ei= genst=C3=A4ndige Einheiten' korrekt zu identifizieren. Ist eine denormalisierte Tabelle mit Filmtiteln, Reg= isseuren und ihren Geburtsdaten gegeben, so ist offenkundig das Geburtsdatum nur vom Regiseur, nicht jedoch von = dem Film abh=C3=A4ngig, in welchem der Schauspieler mitwirkt. Die Personen werden mit dem Attribut 'Geburtsdat= um' herausgezogen, in eine eigene Tabelle mit Prim=C3=A4rschl=C3=BCssel abgelegt und nur dieser in die Filmtabell= e eingebunden.
  • Werden solche Tabellen, die gewisse 'Handelnde', 'eigenst=C3=A4ndig= e Objekte' oder 'Stammdaten' beschreiben, mit einem zus=C3=A4tzlichen Prim=C3=A4rschl=C3=BCssel als Autowert defi= niert, so sind diese Tabellen in der Regel bereits in der zweiten Normalform. Denn das 'eigenst=C3=A4ndige Objekt', das du= rch eine Zeile abgebildet ist, determiniert seine Attribute. Da der hinzugef=C3=BCgte Prim=C3=A4rschl=C3=BCssel aus= einer Spalte besteht, kann keine echte Teilmenge des Prim=C3=A4rschl=C3=BCssels gebildet werden.
  • Zusammengefa=C3=9Ft: Die Attribute innerhalb einer Tabelle m=C3=BCs= sen durch den Prim=C3=A4rschl=C3=BCssel vollst=C3=A4ndig determiniert sowie voneinander unabh=C3=A4ngig sein. Abh=C3=A4ngigkeite= n zwischen Attributen sind in eigene Tabellen zu isolieren.

TOP

Sql - Structured Query Language - Merkmale und Be= sonderheiten dieser Programmiersprache

Die folgenden Bemerkungen skizzieren einige wesentliche Merkmale von Sql= .

Das Verh=C3=A4ltnis zwischen Sql und dem Datenban= k-Management-System (DBMS)

Im Kapitel Datenbank
-Grundbegriffe wurde erl=C3=A4utert, d= a=C3=9F das Datenbank-Managementsystem die einzelnen Datenbanken vor dem direkten Zugriff abschirmt und lediglich Schnittstel= len anbietet, so da=C3=9F Nutzer =C3=BCber diese Schnittstellen Daten abfragen und bearbeiten k=C3=B6nnen. Handelt es sic= h bei dem DBMS um ein relationales DBMS, das Sql unterst=C3=BCtzt, dann nimmt diese Schnittstelle Sql-Befehle in Form= von Texten / Strings entgegen. Diese werden zun=C3=A4chst von einem passenden Modul auf syntaktische Korrektheit gep= r=C3=BCft und von einem Parser in die logischen Einheiten (Schl=C3=BCsselw=C3=B6rter, Operatoren, Tabellen- und Spaltenbezeichner)= zerlegt. Anschlie=C3=9Fend mu=C3=9F ein Ablaufplan festgelegt werden. Denn f=C3=BCr bald jede Sql-Anweisung gibt es verschiedene M=C3=B6= glichkeiten, in welcher Reihenfolge JOIN- und WHERE-Bedingungen auf die beteiligten Tabellen angewandt werden k=C3=B6n= nen. Ebenso wird auf dieser Ebene entschieden, ob f=C3=BCr Zugriffe Indizes genutzt oder ob ein Tabellenscan vielleicht= schneller ist. Der interne Optimierer versucht, aus diesen Varianten jene auszuw=C3=A4hlen, welche die geringsten Kosten= verursacht, das Ergebnis wird als Ablaufplan im Arbeitsspeicher abgelegt. Anschlie=C3=9Fend kann dieser ausgef=C3=BChrt = und eventuell zur=C3=BCckgegebene Zeilen in eine Art tempor=C3=A4re Tabelle geschrieben werden. Nach Abschlu=C3=9F der Dateno= peration liegt eine Statusmeldung vor. Diese wird - eventuell mit den Daten - an die aufrufende Instanz zur=C3=BCckgegeben= . Ein Vorteil eines serverbasierten DBMS im Gegensatz zu einem Desktop-System liegt darin, da=C3=9F ein serverbasiertes DBMS b= ereits kompilierte Ablaufpl=C3=A4ne im Arbeitsspeicher halten und wiederverwenden kann. Bei der n=C3=A4chsten Anforderung mit d= erselben Befehlsfolge kann der erstellte Ablaufplan wiederverwendet, die f=C3=BCr seine Erstellung notwendige Zeit damit ein= gespart werden. Desktop-basierte Systeme, bei welchen ausschlie=C3=9Flich die CPU des Clients diese Operationen ausf=C3= =BChrt, erstellen in der Regel den Ablaufplan zwar schneller, jedoch auch statischer. Diese Erstellung eines Ablaufplans wi= rd bei jedem Aufruf wiederholt. Bei Zugriffen mehrerer Clients sind voneinander unabh=C3=A4ngige CPUs beteil= igt, so da=C3=9F jeder Client seinen eigenen Ablaufplan erstellen mu=C3=9F.

Sql-Ausf=C3=BChrung durch einen Interpreter oder = eingebettet in eine Wirtssprache

F=C3=BCr das bislang vorgestellte Szenario sind zwei verschiedene Initia= lisierungen denkbar. Zum einen kann das DBMS selbst oder ein Client eine interaktive M=C3=B6glichkeit anbieten, welche das d= irekte Eintippen von Sql-Befehlen erlaubt. Beispiele hierf=C3=BCr sind der 'SQL Query Analyzer' vom MS-SqlServer, d= as ebenfalls der MSDE-Engine beiliegende OSQL.Exe, falls dieses im interaktiven Modus genutzt wird oder das Sql-interaktiv-= lernen aus den Fre= eware - Tools. Diese Werkzeuge erlauben es, den Sql-Code direkt einzugeben und liefern das Re= cordset sowie eventuelle Statusmeldungen zur=C3=BCck. Ferner kann ein solches clientseitig verwendetes Tool auch = eine graphische M=C3=B6glichkeit anbieten, Tabellen und Spalten auszuw=C3=A4hlen sowie Filterbedingungen zu setzen. Im Hinte= rgrund generiert das Clientsystem aus den Nutzereingaben den zugeh=C3=B6rigen Sql-Befehl. Werkzeuge wie der Access-Entwurfsmodus = f=C3=BCr Abfragen, die Erstellung von Sichten =C3=BCber die graphische Oberfl=C3=A4che innerhalb eines auf der MSDE ba= sierenden Projektes oder eine =C3=BCber ein Webinterface verwaltete Sql-Datenbank zum Mieten sind von diesem Typ. Manche dieser W= erkzeuge erlauben ein Umschalten zwischen graphischer Oberfl=C3=A4che und erzeugtem Sql-Code, so da=C3=9F Sql hier= =C3=BCber unmittelbar zu lernen ist.

Die andere M=C3=B6glichkeit besteht darin, innerhalb einer Programmiersp= rache ein Objekt zu verwenden, welches Kontakt zu einem DBMS aufnehmen, diesem Sql-Befehle =C3=BCbergeben und R= ecordsets sowie Statusmeldungen empfangen und weiterverarbeiten kann. In diesem Fall wird die umgebende Programmierspr= ache, die Sql-Strings an das DBMS weiterreicht, als Wirtssprache bezeichnet. Der Vorteil einer solchen = Architektur besteht darin, da=C3=9F bei verschiedenen Clients, die wom=C3=B6glich sogar verschiedene Program= miersprachen nutzen, die Ebene des Datenzugriffs getrennt werden kann von der Ebene der clientseitigen Verarbeitung. Den = Programmierern des Clients mu=C3=9F nur bekannt sein, welche Daten sie anfordern, dies =C3=BCbergeben sie als Sql-String= . Als Ergebnis erhalten sie eine Statusmeldung sowie eine Tabelle, welche sie weiterverarbeiten k=C3=B6nnen. Diese Konz= eption l=C3=A4=C3=9Ft sich nochmals entscheidend dadurch verbessern, da=C3=9F als Befehle nur noch g=C3=BCltige Namen ges= peicherter Prozeduren (stored Procedures) zul=C3=A4ssig sind, f=C3=BCr welche= der Client die Ausf=C3=BChrungs- (Execute-) Berechtigung besitzt. Damit ben=C3=B6tigt die DBMS-Benutzerkennung, =C3=BCber welche = sich der Client am Datenbankserver anmeldet, keine der SELECT-, INSERT-, UPDATE- oder DELETE-Berechtigungen, mit welc= hen er ganze Tabellen bearbeiten k=C3=B6nnte. Ebenso mu=C3=9F diese Benutzerkennung nicht Mitglied einer speziellen Nu= tzergruppe mit besonderen Rechten sein. Schlie=C3=9Flich lassen sich hierdurch bei korrekter Initialisierung des Clientobjektes a= lle Probleme mit Sql Injections vermeiden, mit welchen es ansonsten m=C3= =B6glich w=C3=A4re, den Sql-Code durch die Eingabe zus=C3=A4tzlicher Zeichen in die normalen Datenfelder um eigene = Logik zu erg=C3=A4nzen und hierdurch Daten zu manipulieren.

Sql als mengenorientierte Sprache im Gegensatz zu= m datensatzorientierten Zugriff

Ein f=C3=BCr manche Programmierer gew=C3=B6hnungsbed=C3=BCrftiges Charak= teristikum von Sql besteht darin, da=C3=9F Sql mengenorientiert<= /strong> (set-orientated) und nicht datensatz-orientiert= (row-level-orientated) arbeitet. Aus den Daten in mehreren Tabellen wird durch JOIN-Verkn=C3=BC= pfungen eine gro=C3=9Fe Tabelle gebildet und diese als Menge abgefragt bzw. bearbeitet. Durch die Festlegung von Spalten un= d Where-Klauseln - also Zeilen - kann diese Menge in der Breite und in der H=C3=B6he eingeschr=C3=A4nkt werden. Mu=C3=9F die bislang ver= wendete Auswahl anhand weitergehender Kriterien verkleinert werden, k=C3= =B6nnen Unterabfragen erstellt und diese per JOIN mit der Ausgangstabelle verkn=C3= =BCpft werden. Ein datensatzorientiertes Vorgehen w=C3=BCrde dagegen eine Tabelle Zeile um Zeile von der Wirtsspr= ache her abrufen, dort auf das Vorliegen gewisser Kriterien pr=C3=BCfen und - falls die Kriterien erf=C3=BCllt sind - die = Daten weiterverarbeiten.

Die eigentlichen St=C3=A4rken von Sql liegen in der Bearbeitung einer gr= o=C3=9Fen Menge 'auf einmal', der Nutzung der speziell optimierten Indizes sowie der Verwendung eines internen Optimierers zur Erstellung e= ines Ablaufplans und dessen Wiederverwendbarkeit f=C3=BCr mehrere Abfrag= en Diese St=C3=A4rken kommen nur dann wirklich zum Tragen, wenn datensatzorientierte Befehlsfolgen m=C3=B6glichst selte= n eingesetzt werden. Alle Probleme der Datenauswahl und der Datenbearbeitung m=C3=BC=C3=9Ften sich ohne die Verwendung zeile= norientierter Operationen bew=C3=A4ltigen lassen. Leider finden sich bei Recherchen wiederholt Beispiele, in welchen Daten= s=C3=A4tze etwa in eine tempor=C3=A4re Tabelle oder in einen Cursor geladen und anschlie=C3=9Fend Zeile um Zeile verarbeitet= werden. Im extremen Fall wird in einer Schleife aus der tempor=C3=A4r angelegten Tabelle oder aus dem Cursor eine Datenzeile geh= olt, diese innerhalb der Wirtssprache auf Eigenschaften gepr=C3=BCft - anstatt diese Kriterien in der WHERE-Bedingung zu formuli= eren - und weiterverarbeitet. Tats=C3=A4chlich jedoch d=C3=BCrfte nur in jenen F=C3=A4llen ein datensatzorientiertes Vorgehen = notwendig sein, in welchen aus den selektierten Informationen - etwa Nutzernamen - im Rahmen einer Metaverarbeitung dynamisch Sql-Befe= hle generiert werden sollen und diese Befehle nur als Einzelanweisungen ausgef=C3=BChrt werden d=C3=BCrfen. Di= es gilt beim MS-SqlServer bsp. f=C3=BCr Befehle wie Create Procedure ... As ... oder Create View ... As .... B= ei diesen speziellen, objekterzeugenden Befehlen mu=C3=9F dieser Create-Befehl am Anfang des B= efehlsstapels stehen und darf keinen weiteren Befehl enthalten. Selbst in diesem Fall ist zu pr=C3=BCfen, ob der Befeh= l nicht bereits in der Sql-Select-Anweisung zusammengesetzt werden kann. Falls ja, gen=C3=BCgt es, die Zeile abzuruf= en und den String sofort auszuf=C3=BChren. Die Alternative, von der Wirtssprache her die Werte abzurufen, erst dort den= Sql-Befehl zusammenzusetzen und ihn anschlie=C3=9Fend auszuf=C3=BChren, ist aufwendiger. Lediglich die aufgr= und der Vervielfachung der Texte vergr=C3=B6=C3=9Ferte Tabelle und die hierdurch produzierte gr=C3=B6=C3=9Fere Speicherauslastung des C= lients w=C3=A4re in wenigen, sehr seltenen F=C3=A4llen ein Argument, das gegen den Einsatz dieser Technik spricht.

Sql als Sprache der vierten Generation - 4GL

= Ein zentrales Merkmal von Sql ist, da=C3=9F nicht gesagt wird, w= ie etwas gemacht werden soll, sondern da=C3=9F nur mitgeteilt wird, was zu tun = sei. SQL wird deshalb als eine Sprache der vierten Generation klassifiziert. Programmi= ersprachen k=C3=B6nnen grob gem=C3=A4=C3=9F der folgenden Liste sortiert werden:
  • Sprachen der ersten Generation oder Maschi= nensprachen: Dies sind Programmiersprachen, die in Bin=C3=A4rform, also als Bit-Folg= e von Nullen und Einsen geschrieben werden. Alternativ k=C3=B6nnen auch Werte aus dem Hexadezimalsystem verwendet w= erden, so da=C3=9F ein Block von vier Bit durch die 2^4 =3D 16 Alternativen 0-9 und A-F belegt werden kann. Ein Byte is= t damit durch zwei Werte aus dem Hexadezimalsystem festgelegt.
  • Sprachen der zweiten Generation oder Assem= blersprachen: Die Sprachen der ersten Generation sind extrem schlecht lesbar, damit f= ehleranf=C3=A4llig. Deshalb werden die rohen Maschinenbefehle in wiederkehrenden Gruppen zusammengefa=C3=9Ft und mit= englischsprachigen Begriffen benannt. Hinzu kommen Register, die feststehende Namen f=C3=BCr Speicheradressen darst= ellen. Das Ergebnis sind Ausdr=C3=BCcke, die bsp. so aussehen k=C3=B6nnen:
    	mov eax, 100		Wert 100 nach eax schreiben
    	add eax, 10		zum Wert in eax 10 addieren
    Jedem dieser Assembler-Au= sdr=C3=BCcke entspricht ein Maschinenbefehl, so da=C3=9F Assembler-Befeh= lsfolgen Eins-zu-Eins auf Befehlsfolgen in der Maschinensprache abgebildet werde= n. Assembler kennt jedoch keine komplexeren Anweisungen, keine Datentypen und kaum die aus h=C3=B6heren= Programmiersprachen bekannten Konstrukte der for- und while-Schleifen. Stattdessen m=C3=BCssen bsp. mehrfache Ad= ditionen in Einzelanweisungen zerlegt und die =C3=BCbliche if-then-else - Anweisung mittels eines Vergleichs sowi= e eines anschlie=C3=9Fenden GoTo - eines Sprungs - behandelt werden. Ferner ist der gesamte Code maschinenabh=C3=A4ngig. Damit lassen sich e= inerseits Programme schreiben, die weitaus schneller sein k=C3=B6nnen als ihr Analogon in der Hochsprache. Anderer= seits sind die Programme nicht portabel, so da=C3=9F jede Verteilung von Software begrenzt ist und das Programm f=C3= =BCr einen neuen Maschinentyp eventuell angepa=C3=9Ft werden mu=C3=9F.
  • Sprachen der dritten Generation oder h=C3=B6= here Programmiersprachen: Diese Gruppe umfa=C3=9Ft Sprachen wie C, Fortran oder VisualBasic, dere= n Quelltext interaktiv von einem Interpreter direkt interpretiert oder einmalig von einem Compiler in eine ausf=C3=BC= hrbare Datei =C3=BCbersetzt wird. Es stehen komplexe und selbst definierbare Datentypen sowie diverse Schleifenkonstrukte zur Verf=C3=BC= gung. Der Quellcode ist in der Regel unabh=C3=A4ngig von der Maschine, auf welcher er sp=C3=A4ter ausgef=C3=BChrt wird. S=C3= =A4mtliche maschinenspezifischen Probleme werden vom Compiler behandelt, so da=C3=9F der Maschinencode aufwendiger ist als e= in speziell angepa=C3=9Fter Assemblercode mit demselben Leistungsumfang. Sprachen der dritten Generation sind prozedurorientiert insofern, da das Programm sowohl Datenstrukturen als auch Zugriffsproze= duren selbst definiert und festlegt, wie etwas gemacht werden soll. Damit liegt die Verantw= ortung bsp. f=C3=BCr effiziente Sortier- und Filteralgorithmen oder f=C3=BCr die Erstellung eines leist= ungsf=C3=A4higen Index beim Programmierer.
  • Sprachen der vierten Generation oder daten= orientierte Programmiersprachen: Diese Sprachen sind dadurch gekennzeichnet, da=C3=9F sie nicht mehr pro= zess-, sondern datenorientiert sind und da=C3=9F beim Programmieren nicht mehr Schritt f=C3=BCr Schritt festgel= egt wird, wie etwas gemacht werden soll, sondern blo=C3=9F noch bestimmt wird, was zu tun sei. Dies bedeutet eine= rseits eine Reduktion gegen=C3=BCber den Sprachen der dritten Generation, da viele Details au=C3=9Ferhalb de= s Einflu=C3=9Fbereichs des eigenen Quellcodes liegen und beim Programmieren nur verwendet, jedoch nicht mehr beeinflu= =C3=9Ft werden k=C3=B6nnen. Andererseits impliziert dies eine Entlastung von diesen wiederkehrenden Routineaufgaben wie dem= Entwerfen einer Datenstruktur, dem Speichern und Laden aus der Datei oder der Entwicklung eines effizienten Sortiera= lgorithmus. Diese Aufgaben bleiben den Entwicklern der Programmierumgebung =C3=BCberlassen, so da=C3=9F diese = bei gro=C3=9Fen Datenmengen leistungskritischen Aufgaben durch das hierf=C3=BCr notwendige Spezialwissen abgedeckt sind.
  • Sprachen der f=C3=BCnften Generation oder = Sprachen der K=C3=BCnstlichen Intelligenz: Im Gegensatz zu den Sprachen von der ersten bis zur vierten Generation,= die sich an dem Aufbau von Rechenmaschinen orientieren und imperativ Probleme Befehl um Befehl abarbeiten, verarbe= iten die Sprachen der f=C3=BCnften Generation Eingaben deklarativ entlang eines Systems aus Regeln und Schlu=C3=9Ffolgerungen.
Die Zuordnung von SQL als Programmiersprache der vierten Generation ergi= bt sich daraus, da=C3=9F Sql-Befehle nur noch beschreiben, was gemacht werden soll: 'Erzeuge oder bearbeite ein Objekt= , manipuliere diese Daten oder gib jene Daten zur=C3=BCck'. Eine Sprache der dritten Generation m=C3=BC=C3=9Fte = ein eigenes Tabellenobjekt definieren und eigenst=C3=A4ndig Verfahren entwickeln, um bsp. eine Zeile m=C3=B6glichst effizient zu suc= hen und zur=C3=BCckzugeben. Solche Algorithmen k=C3=B6nnten als Objekte mit Methoden gekapselt werden. Damit w=C3=A4re = der Datenzugriff jedoch an diese Programmiersprache gebunden. Wenn man mag, kann man ein relationales DBMS mit einer Sql-Sch= nittstelle interpretieren als ein allgemeines Objekt, welches mittels geeigneter Connection-Objekte von verschiedenen = Programmiersprachen genutzt werden kann. Dieses RDBMS kennt gewisserma=C3=9Fen nur die Methode 'F=C3=BChre den fo= lgenden Sql-Befehl aus', dessen Eigenschaft (=3D der auszuf=C3=BChrende = Sql-Befehl) wird zuvor als Stringvariable =C3=BCbergeben. Die Methode liefert einen = Statuswert =C3=BCber Erfolg oder Fehlschlag sowie eventuelle R=C3=BCckgabedaten aus.

TOP

Einige historische Anmerkungen

Die Entwicklung von SQL bewegt sich zwischen Forschungsarbeiten, Aktivit= =C3=A4ten von Firmen sowie staatlichen und internationalen Organisationen. Der Sprachkern ist seit etwa 1989 durcha= us stabil. Standards und Produkte einzelner Firmen gehen jedoch weit =C3=BCber diesen Kern hinaus, so da=C3= =9F einige sich auf den ersten Blick widersprechende Kurzbezeichnungen zu finden sind. Die folgenden Ausf=C3=BChrungen orient= ieren sich an den angegebenen Fundstellen.
Inzwischen existieren einzelne Produkte, bei welchen (1) das DBMS http-S= chnittstellen unterst=C3=BCtzt sowie (2) als Eingabe einen Sql-Befehl mit angeh=C3=A4ngter 'FOR XML'-Klausel akze= ptiert. Die Daten werden nicht mehr in einem bin=C3=A4ren Format, sondern direkt als Xml-Dokument zur=C3=BCckgegeben.= Damit kann einerseits die Leistungsf=C3=A4higkeit heutiger Datenbanksysteme erhalten und weiterentwickelt werden. Anderers= eits lassen sich Daten nicht mehr nur noch =C3=BCber Rechner-, sondern nun auch =C3=BCber Betriebssystemgrenzen hin= weg in einer hochstrukturierten Form abfragen und austauschen.

TOP

Zeilen einf=C3=BCgen mit INSERT

Syntax

  • INSERT INTO <Tabellenname>(<Spaltenname> [, weiter=
    e Spaltennamen])
    	VALUES (<Wert f=C3=BCr die erste Spalte> [, weitere Werte])
    = Einfache Form: Hinter VALUES werden alle einzuf=C3=BCgenden Werte der R= eihe nach aufgelistet. Es wird genau eine neue Zeile erzeugt.
  • INSERT INTO <Tabellenname>(<Spaltenname> [, weiter=
    e Spaltennamen])
    
    	SELECT <Spalte-1> [, weitere Ausgaben]
    	[FROM ...]
    	[WHERE ...]
    	[GROUP BY ...]
    	[HAVING ...]
    Einf=C3=BCgen mehrerer Zeilen. Als Select-Anweisung i= st jede beliebige Anweisung m=C3=B6glich, sofern die Zahl der Ausgabespalten mit der Zahl der Zielspalten sowie die Dat= entypen =C3=BCbereinstimmen. Das Select-Recordset kann auch keine Zeilen zur=C3=BCckliefern, dies ist kein Fehler, es we= rden keine Zeilen hinzugef=C3=BCgt.

Beispiele

  • INSERT INTO ARTIKEL(A_NR, A_NAME, A_PREIS)
    		VALUES(12, 'Oberhemd', 39.80)
    Dies f=C3=BCgt in die Tabelle Artik= el die erste Zeile aus der Artikel.txt ein. Dies gelingt allerdings nur deshalb, da die Spalte A_NR keine automatisch erzeugte = fortlaufende Nummer enth=C3=A4lt und deshalb der Wert f=C3=BCr den Prim=C3=A4rschl=C3=BCssel per Hand festgelegt werden mu=C3= =9F.
  • F=C3=BCr den Fall, da=C3=9F die Tabelle einen automatisch erzeugten= Wert enth=C3=A4lt, mu=C3=9F weder die Spalte noch ein Wert angegeben werden. Beispiel:
    CREATE TABLE [Artikel-mit-Id]
    	(A_NR int Identity(1, 1) Primary Key,
    		A_Name varchar(50),
    		A_Preis money)
    Dies erzeugt eine Tabelle, bei welcher der ersten Spalte ein automatisch erstellter Wert zugewiesen wird
    INSERT INTO [Artikel-mit-Id](A_NAME, A_PREIS)
    	VALUES ('Oberhemd', 39.80)
    In die neue Tabelle wird eine Zeile ein= getragen. Ist die Tabelle soeben neu erstellt worden, so erh=C3=A4lt die neue Zeile den Wert 1 als Prim=C3=A4rschl=C3=BCssel= .
  • INSERT INTO ARTIKEL(A_NR, A_NAME, A_PREIS)
    	SELECT 12, 'Oberhemd', 39.80
    	UNION
    	SELECT 22, 'Mantel', 360.00
    	UNION
    	SELECT 11, 'Oberhemd', 44.20
    	UNION
    	SELECT 13, 'Hose', 110.50
    Dies f=C3=BCgt Daten ein, die =C3=BCber = eine Dummy-Select-Anweisung mit UNION zusammengestellt wurden. Beachten Sie, da=C3=9F eine solche Konstruktion mit Ms-Access nicht ge= lingt. Dort kann man mit dem Einf=C3=BCgen einer Dummy-Tabelle sowie der TOP 1 - Klausel erreichen, da=C3=9F eine Zeile zur=C3=BCckge= geben wird. Die UNION-Anweisung l=C3=A4=C3=9Ft sich jedoch nicht direkt in eine Tabelle einf=C3=BCgen, sie mu=C3=9F in einer Unterabfrage vers= teckt werden. Die folgende Anweisung ist m=C3=B6glich:
    CREATE TABLE ATest(A_NR int, A_NAME varchar(50), A_PREIS money)
    	
    INSERT INTO ATest(A_Nr, A_NAME,A_PREIS)
    	SELECT A.A_Nr, A.A_Name, A.A_Preis
    	From (
    		SELECT Top 1 12 As A_NR, 'Oberhemd' AS A_NAME,
    		39.80 AS A_PREIS From Artikel
    		UNION
    		SELECT Top 1 22, 'Mantel', 360.00 From Artikel
    		UNION
    		SELECT Top 1 11, 'Oberhemd', 44.20 From Artikel
    		UNION
    		SELECT Top 1 13, 'Hose', 110.50 From Artikel
    		Order By A_Nr)
    	As A
  • INSERT INTO ARTIKEL(A_NR, A_NAME, A_PREIS)
    	SELECT A.A_NR + 100,
    		A.A_NAME,
    		A.A_PREIS * 1.1
    	FROM ARTIKEL As A
    Dies f=C3=BCgt in die Tabelle Artikel vier neue Zeilen ein, die Artikel= -Nummer ist um 100, der Artikelpreis um 10% erh=C3=B6ht.
  • SELECT A.A_NR, A.A_NAME,
    	A.A_PREIS As Gesamt
    		INTO ArtikelAuswertung
    	FROM ARTIKEL As A
    	WHERE 0 =3D 1
    
    INSERT INTO ArtikelAuswertung
    	(A_NR, A_NAME, Gesamt)
    SELECT A.A_NR, A.A_=
    NAME,
    	SUM(A.A_PREIS * U.=
    A_STUECK)
    FROM ARTIKEL As A INNER JOIN UMSATZ As U
    	On A.A_NR =3D U.A_=
    NR
    GROUP BY A.A_NR, A.=
    A_NAME
    Dies ist eine typische Anwendung der INSERT-Anweisung, um Daten unabh=C3=A4ngig von d= er Hauptdatenbank auswerten oder weiterverarbeiten zu k=C3=B6nnen. Zun=C3=A4chst wird die gew=C3=BCnschte Zieltabelle erstellt, indem eine= passende SELECT-Anweisung mit INTO in eine neue Tabelle umgelenkt und in diese mit '0 =3D 1' keine Daten =C3=BCbertragen werden. Anschlie= =C3=9Fend werden die tats=C3=A4chlich gew=C3=BCnschten Nutzdaten aggregi= ert und kopiert. Eine solche Trennung anstelle eines direkten SELECT ... IN= TO ... FROM kann hilfreich sein, falls die Tabelle auf jeden Fall erstellt werden soll, es jedoch bsp. zu Laufzeitfehlern bei = der SELECT-Abfrage kommen kann, so da=C3=9F diese nicht ausgef=C3=BChrt wird.
  • Verwenden einer gespeicherten Prozedur mit Parametern zum Einf=C3=BC= gen von Daten:
    CREATE PROCEDURE up_ins_Artikel
    		@A_NR int,
    		@A_NAME nvarchar(50),
    		@A_PREIS money
    As
    	INSERT INTO ARTIKEL(A_NR, A_NAME, A_PREIS)
    	VALUES (@A_NR, @A_NAME, @A_PREIS)
    
    Execute up_ins_Artikel 50, 'Schlapphut', 49.90
    Dies ist die Standar= d-Syntax zur Erzeugung gespeicherter Prozeduren mit Parametern. Die Prozedur nutzt die Parameterwerte, um eine Zeile einzuf= =C3=BCgen. Ms-Access hat seine eigene Syntax. Hier d=C3=BCrfen - bei der Verwendung =C3=BCber .NET - die Parameter nicht deklariert werd= en und sind nach Position anzusprechen. Mit ADO ist eine Syntax m=C3=B6glich, wie sie innerhalb DAO verwendet wird:
    PARAMETERS [@a_nr] int, [@a_name] nvarchar(50), [@a_preis] money;
    	CREATE ... 

Bemerkung zu allen Data Man= ipulation Language - Befehlen (DML)

  • Falls Sie bislang noch wenig Erfahrung mit Datenbank-Befehlen haben= : Beachten Sie, da=C3=9F es auf dieser Ebene des Zugriffs keinen 'R=C3=BCckg=C3=A4ngig-Button' mehr gibt, wie Sie ihn vielleicht = von Word oder Excel gewohnt sind. Eine Datenbank stellt einen elementare= n Datenspeicher dar, INSERT/UPDATE/DELETE ver=C3=A4ndert diesen Speicher = direkt. Und was Sie eingef=C3=BCgt, ge=C3=A4ndert oder gel=C3=B6scht hab= en, ist unwiderruflich eingef=C3=BCgt, ge=C3=A4ndert und gel=C3=B6scht.
    Falls es in Programmen wie Word einen R=C3=BCckg=C3=A4ngig-Button gibt,= so setzt dies in irgendeiner Form eine Datenbankstruktur voraus, welche= sich die zuletzt durchgef=C3=BChrten Aktionen merkt und diese zur=C3=BC= cksetzt. Ben=C3=B6tigen Sie auf der Ebene einer Datenbank eine Historie,= so mu=C3=9F diese explizit in Form eines Tabellenschemas erstellt und z= u einer Zeile nicht nur die aktuellen Werte, sondern zus=C3=A4tzlich das =C3=84nderungsdatum erfa=C3=9Ft werden. Alternativ kann man eine zu= s=C3=A4tzliche Tabelle erstellen und immer die drei letzten Versionen in= dieser ablegen.

TOP

Zeilen bearbeiten mit UPDATE

Vorbemerkung

Der Update-Befehl nimmt unter den Sql-Anweisungen insofern eine Sonderpo= sition ein, da sich die Syntax bei Verwenden einer JOIN-Klausel zwischen Ms-Access und Ms-SqlServer unterscheidet. Damit di= e Beispiele mit dem Sql-interaktiv-lernen getestet werden k=C3=B6nnen, werden in diesen F=C3=A4llen beide Versionen angegeb= en.

Syntax

  • Update einer Tabelle ohne Verkn=C3=BCpfung mit anderen Tabellen
    UPDATE <Tabelle>
    	SET <Name einer Spalte> =3D <Ausdruck aus Spalten,
    		Konstanten, Funktionen>
    		[, weitere Spaltennamen =3D Ausdruck]
    	WHERE <Bedingung>
  • Update einer Tabelle mit JOIN (Ms-Access)
    UPDATE <Tabelle> [INNER | LEFT | RIGHT] JOIN <Tabelle>=
    
    	ON <Spalte-1 =3D Spalte-2>
    	SET <Name einer Spalte> =3D <Ausdruck aus Spalten,
    		Konstanten, Funktionen>
    		[, weitere Spaltennamen =3D Ausdruck]
    	WHERE <Bedingung>
  • Update einer Tabelle mit JOIN (ANSI, Ms-SqlServer)
    UPDATE <Tabelle | View>
    	SET <Name einer Spalte> =3D <Ausdruck aus Spalten,
    		Konstanten, Funktionen>
    		[, weitere Spaltennamen =3D Ausdruck]
    	[FROM <Tabelle> [INNER | LEFT | RIGHT] JOIN <Tabelle>
    	ON <Spalte-1 =3D Spalte-2>]
    	WHERE <Bedingung>
  • Zun=C3=A4chst wird die zu aktualisierende Tabelle angegeben. Nach S= ET folgt die Liste der zu aktualisierenden Zellen, f=C3=BCr die rechts vom Gleichheitszeichen der neue Wert angeg= eben wird. Im ANSI-Standard kann anschlie=C3=9Fend eine JOIN-Verkn=C3=BCpfung folgen, durch welche die von der Aktualisie= rung betroffenen Zeilen genauer eingeschr=C3=A4nkt werden. Schlie=C3=9Flich werden mit einer WHERE-Klausel einzelne Zeilen ausgew= =C3=A4hlt.

Beispiele

F=C3=BCgen Sie zu den beiden Tabellen ARTIKEL und UMSATZ mit dem folgend= en Befehl eine neue Spalte 'Gesamt' hinzu:
ALTER TABLE ARTIKEL ADD Gesamt money
ALTER TABLE UMSATZ ADD Gesamt money
Diese Spalten k=C3=B6nnen zu Testzwecken beliebig manipuliert werden, oh= ne da=C3=9F sich die Grunddaten deshalb =C3=A4ndern.
  1. UPDATE ARTIKEL
    	SET Gesamt =3D 0
    Einfachste Version einer Update-Anweisung: Eine S= palte wird mit einem neuen Wert, hier mit der Konstanten 0 belegt, die Aktualisierung wird f=C3=BCr alle Zeilen ausge= f=C3=BChrt.
  2. UPDATE ARTIKEL
    	SET Gesamt =3D A_PREIS
    Jeder Zelle 'Gesamt' ist die Zelle 'A_PREIS= ' derselben Zeile zugeordnet. Also wird der Wert der letzteren in die Zelle 'Gesamt' kopiert.
  3. UPDATE ARTIKEL
    	SET Gesamt =3D A_PREIS * 1.19
    Dasselbe wie zuvor, nun erg=C3=A4nzt= um die Multiplikation mit einer Konstanten. Eine solche Spalte mag bsp. den Bruttopreis eines Artikels enthalten.
  4. UPDATE ARTIKEL
    	SET Gesamt =3D A_PREIS * 1.19
    	WHERE A_PREIS > 100
    Nun wird die Menge der zu aktualisierenden = Zeilen eingeschr=C3=A4nkt, auf da=C3=9F nicht alle, sondern nur jene Zeilen aktualisiert werden, deren Preis vor der Aktualisierung gr=C3= =B6=C3=9Fer 100 ist.
  5. Erstellung der gespeicherten Prozedur:
    CREATE PROCEDURE up_upd_=
    Artikel
    	@A_Nr int,
    	@A_Name nvarchar(50),
    	@A_Preis money
    As
    	UPDATE ARTIKEL
    		SET A_NAME =3D @A_Name,
    			A_PREIS =3D @A_Preis
    	WHERE A_Nr =3D @A_Nr
    Ausf=C3=BChrung:
    Execute up_upd_Artikel 1=
    1, 'Oberhemd (Doppelpackung)', 59.90
    Dies ist ein kanonisches Beispiel f=C3=BCr eine gespeicherte Prozedur, = welche den Datensatz mit der =C3=BCbergebenen @A_Nr aktualisiert. F=C3=BCr die Ms-Access-Version =C3=BCber .NET sind die Parameter zu ent= fernen.
  6. Ms-Access:
    UPDATE ARTIKEL As A IN=
    NER JOIN UMSATZ AS U
    	On A.A_NR =3D U.A_=
    NR
    	SET U.Gesamt =3D A.A_PREIS * U.A_STUECK
    Ms-SqlServer:
    UPDATE UMSATZ
    	SET Gesamt =3D U.A_STUECK * A.A_PREIS
    	FROM UMSATZ AS U INNER JOIN ARTIKEL As A
    	On U.A_NR =3D A.A_=
    NR
    Diese Anweisung berechnet in der Tabelle 'Umsatz' den Wert jeder einzelnen Zeile, indem= der zum Artikel geh=C3=B6rende Preis mit 'A_Stueck' multipliziert wird. Da es zu jeder Umsatz-Zeile genau eine Zeile in der= Tabelle 'Artikel' gibt, ist diese Anweisung eindeutig.
  7. Aktualisieren der Spalte ARTIKEL.Gesamt mit dem Produkt aus ARTIKEL= .A_PREIS und der Summe aller UMSATZ.A_STUECK f=C3=BCr diesen Artikel.
    Zur L=C3=B6sung dieser Aufgabe scheint es zun=C3=A4= chst zu gen=C3=BCgen, den Aktualisierungsausdruck
    SET A.Gesamt =3D A.A_PREIS * SUM(U.A_STUECK)
    zu verwenden, f=C3= =BCr Ms-SqlServer w=C3=BCrde man das Pr=C3=A4fix bei 'A.Gesamt' entfernen. Eine solche Abfrage l=C3=A4=C3=9Ft sich mit Ms-Ac= cess sogar speichern, jedoch nicht ausf=C3=BChren. Es wird die von Gruppierungsabfragen bekannte Fehlermeldung "Sie wollten eine Abfra= ge ausf=C3=BChren, die den angegebenen Ausdruck 'Gesamt' nicht als Teil der Aggregatfunktion einschlie=C3=9Ft" ausgibt (vgl. Mit GROUP BY Daten aggregieren und auswerten - Bemerkungen).= Jeder Versuch, die Update-Anweisung um eine Group-By-Klausel zu erg=C3=A4= nzen, scheitert jedoch ebenfalls. Beim Ms-SqlServer ist die Fehlermeldung genauer: Ein Aggregat kann= nicht in der SET-Liste einer UPDATE-Anweisung auftreten. Diese Aufgabe kann deshalb nur mit einer eigenst=C3=A4ndigen Unterabfra= ge gel=C3=B6st werden, welche f=C3=BCr jeden Artikel bereits die Summati= on =C3=BCber die diesem Artikel zugeordneten A_Stueck enth=C3=A4lt. Tats=C3= =A4chlich gelingt dies nur beim Ms-SqlServer. Bei Ms-Access wird nur ein= e einzige virtuelle Tabelle als das zu aktualisierende Recordset betracht= et. Die Hilfe f=C3=BCr Office XP (Access, Abschnitt Microsoft JET-SQL-Referenz) erw=C3=A4hnt die M=C3=B6glichkeit eines JOIN nicht ei= nmal. Diese virtuelle Tabelle mu=C3=9F vollst=C3=A4ndig aktualisierbar s= ein, eine Abfrage, welche Aggregatfunktionen verwendet und gruppiert, ist jedoch = schreibgesch=C3=BCtzt. Deshalb kann nur eine L=C3=B6sung f=C3=BCr Ms-Sql= Server angegeben werden:
    UPDATE ARTIKEL
    	SET Gesamt =3D A.A_PREIS * U1.A_Stueck_Ge=
    samt
    	FROM ARTIKEL As A INNER JOIN
    		(SELECT B.A_NR, SUM(B.A_STUECK
    		FROM UMSATZ As B
    		GROUP BY B.A_NR) As U1
    	On A.A_NR =3D B.A_=
    NR
    F=C3=BCr Ms-Access m=C3=BC=C3=9Fte die Unterabfrage als eigenst=C3=A4nd= ige SELECT-Anweisung in eine tempor=C3=A4re Tabelle kopiert, =C3=BCber d= iese die Verkn=C3=BCpfungs-Aktualisierung durchgef=C3=BChrt und die tempor=C3= =A4re Tabelle am Schlu=C3=9F gel=C3=B6scht werden. Dies gilt analog f=C3=BCr DBMS, welche Unterabfragen nicht unterst=C3=BCtzen.
  8. Zerlegung von Vertreter.V_Name in Vorname und Nachname:
    Offenk= undig ist die Tabelle VERTRETER nicht normalisiert. So sind Nachname und Vorname in einer Spalte zusammengefa= =C3=9Ft, dies verletzt die Forderung nach atomaren Attributen. Als Folge kann bsp. eine Suche nach einem Nachnamen nicht e= infach diesen angeben und mit dem Gleichheitsoperator (=3D) =C3=BCberpr=C3=BCfen, sondern es mu=C3=9F eine Anweisung der Form
    A_NAME LIKE 'Meyer,%'
    verwendet werden. Mittels der Update-An= weisung und unter Verwendung von Funktionen k=C3=B6nnen solche Spalten in ihre Bestandteile zerlegt werden.
    ALTER TABLE VERTRETER ADD Nachname nvarchar(50)
    ALTER TABLE VERTRETER ADD Vorname nvarchar(50)
    Dies f=C3=BCgt zwei neue Spalten 'Nachname' und 'Vorname' ein.

    Ms-Access:
    UPDATE VERTRETER
    	SET Nachname =3D Left(V_NAME, InStr(VERTRETER, ',') - 1),
    		Vorname =3D Trim(Mid(VERTRETER,
    			InStr(VERTRETER, ',') + 1))
    Ms-SqlServer:
    UPDATE VERTRETER
    	SET Nachname =3D Left(V_NAME, CharIndex('=
    ,', V_NAME) - 1),
    		Vorname =3D LTrim(SubString(V_NAME,
    			CharIndex(',', V_NAME) + 1))
  9. Berechnung des h=C3=B6chsten Einzelumsatzes pro Artikel, eingetrage= n in der Tabelle UMSATZ (Ms-SqlServer):
    UPDATE UMSATZ SET Gesamt =3D Null
    
    UPDATE UMSATZ
    	SET Gesamt =3D A.A_PREIS * U.A_STUECK
    FROM ARTIKEL As A INNER JOIN UMSATZ As U
    On A.A_NR =3D U.A_N=
    R
    WHERE A.A_PREIS * U.A_STUECK =3D
    	(SELECT MAX(A.A_PREIS * U.A_STUECK
    	FROM ARTIKEL As A INNER JOIN UMSATZ As V
    	On B.A_NR =3D V.A_=
    NR
    	WHERE B.A_NR =3D A.A_NR)
    Diese Anweisung setzt zun=C3=A4chst alle Eintr=C3=A4ge in UMSATZ.Gesamt= zur=C3=BCck und tr=C3=A4gt nur in jene Zeilen den Gesamtumsatz ein, die f=C3=BCr diesen Artikel den h=C3=B6chsten Einzelumsatz darstellen. = Hier wird sowohl ein JOIN als auch eine korrelierte Unterabfrage genutzt, die sich allerdings in einen JOIN mit Unterabfrage aufl=C3=B6s= en l=C3=A4=C3=9Ft:
    UPDATE UMSATZ
    	SET Gesamt =3D A.A_PREIS * U.A_STUECK
    FROM ARTIKEL As A INNER JOIN UMSATZ As U
    On A.A_NR =3D U.A_N=
    R INNER JOIN
    	(SELECT B.A_NR, MAX(B.A_PREIS * U1.A_STUECK) As Maxim=
    um
    	FROM ARTIKEL As B INNER JOIN UMSATZ As U1
    	On B.A_NR =3D U1.A=
    _NR
    	GROUP BY B.A_NR) As C
    On U.A_NR =3D C.A_N=
    R AND
    	A.A_PREIS * U.A_ST=
    UECK=3D C.Maximum
    Diese Anweisung ist ein Beispiel daf=C3=BCr, wie eine JOIN-Klausel daf=C3= =BCr genutzt werden kann, wenige Zeilen aus der zu aktualisierenden Tabelle auszuw=C3=A4hlen. Aktualisiert wird die Tabelle UMSATZ, das Hin= zunehmen von ARTIKEL reduziert die Zahl der Zeilen nicht. Erst die zus=C3=A4tzliche JOIN-Klausel, die pro Artikel nur noch eine Z= eile enth=C3=A4lt, vermindert die Zahl der vom UPDATE betroffenen Zeilen auf vier.

Bemerkungen

  • Deterministische und nichtdeterministische= Anweisungen: Bei UPDATE-Befehlen mit JOIN-Klausel mu=C3=9F sichergestellt sein, da=C3=9F der JOIN zu je= der zu aktualisierenden Zeile nur einen Ausdruck liefert. Ist dies der Fall, so spricht man von deterministischen Anweisu= ngen. Ansonsten handelt es sich um eine nichtdeterministische Anweisung, deren Ergebnis nicht eindeutig definie= rt ist. Denn in diesem Fall ist nicht vorhersehbar, welcher Ausdruck tats=C3=A4chlich in die Zelle eingetragen wird. Dieses= Problem taucht haupts=C3=A4chlich dann auf, wenn eine Spalte in der Grundtabelle aktualisiert werden soll und im JOIN eine Detailtabell= e herangezogen wird, so da=C3=9F in der Detailtabelle kein, ein oder mehrere Datens=C3=A4tze f=C3=BCr die Grundzeile zur Verf=C3=BC= gung stehen.

    Ms-Access:
    UPDATE ARTIKEL As A INNER =
    JOIN UMSATZ AS U
    	On A.A_NR =3D U.A_=
    NR
    	SET A.Gesamt =3D A.A_PREIS * U.A_STUECK
    Ms-SqlServer:
    UPDATE ARTIKEL
    	SET Gesamt =3D U.A_STUECK * A.A_PREIS
    	FROM UMSATZ AS U INNER JOIN ARTIKEL As A
    	On U.A_NR =3D A.A_=
    NR
    Dies ist fast dasselbe Beispiel wie oben (6), nur wird nun die Spalte A= RTIKEL.Gesamt aktualisiert. Da zu einem Artikel mehrere Einzelums=C3=A4tze existieren, ist nicht bekannt, welcher Einzelumsatz = zur Berechnung ausgew=C3=A4hlt wird.
  • Anmerkungen zur Syntax: Bei Ms-Access kann nur ein Ausdruck aktuali= siert werden, der eine g=C3=A4nzlich aktualisierbare Tabelle darstellt. Diese kann real oder virtuell, als JOIN deklariert = sein, so da=C3=9F praktisch mehrere Tabellen neue Eintr=C3=A4ge erhalten. So funktioniert die folgende Anweisung in Ms-Access:
    UPDATE ARTIKEL As A INNER JOIN UMSATZ As U
    	On A.A_NR =3D U.A_=
    NR
    	SET A.Gesamt =3D Null,
    		U.Gesamt =3D A.A_PREIS * U.A_STUECK
    Gem=C3=A4=C3=9F dem ANSI-Standard ist jedoch nur die Aktualisierung ein= es einzigen Objektes m=C3=B6glich. Bei diesem kann es sich allerdings um= einen mehrere Tabellen umfassenden View handeln, als Objektbezeichner d= arf auf die UPDATE-Anweisung jedoch nur ein Ausdruck folgen. F=C3=BCr die in Ms-Access funktionierende obige Anweisung, die eine tem= por=C3=A4re Sicht erstellt, w=C3=A4re in Ms-SqlServer zun=C3=A4chst ein eigenst=C3=A4ndiger View zu erstellen, dieser k=C3=B6nnte genutzt werde= n.
    Eine ernstzunehmende Einschr=C3=A4nkung bei Ms-Access ist die Unm=C3=B6= glichkeit, zwischen SET und WHERE einen JOIN festzulegen, mit welchem entweder gewisse Zeilen zur Aktualisierung ausgew=C3=A4hlt werden oder = mit welchem zus=C3=A4tzliche Spalten zur Berechnung des neuen Wertes herangezogen werden k=C3=B6nnen.

    Bei Ms-SqlServer ist zu beachten, da=C3=9F das Objekt, welches upgedate= d werden soll, ohne Alias-Namen verwendet werden mu=C3=9F. Ferner darf im folgenden JOIN-Abschnitt dieses Objekt h=C3=B6chstens einmal au= fgef=C3=BChrt werden, hier sind Alias-Namen erlaubt und w=C3=BCnschenswe= rt.
  • Die Technik, Zellen mittels Funktionen in atomare Werte zu zerlegen= , wird in vielf=C3=A4ltiger Weise ben=C3=B6tigt, falls schwach strukturierte Daten in eine Datenbank eingelesen werden sollen.= Im Regelfall ist es das beste, die Daten zun=C3=A4chst in eine einzige Textspalte einzulesen und diese Spalte anschlie=C3=9Fend mit Da= tenbank-Techniken schrittweise zu zerlegen. Ein zeilenweises Zerlegen vor dem Einlesen in die Datenbank d=C3=BCrfte in den meisten F= =C3=A4llen unter Performance-Gesichtspunkten schlechter sein, da die Leistung eines DBMS gerade darin besteht, eine Menge vieler Zeil= en auf einmal zu verarbeiten. Eventuelle Ein- bzw. Ausschlie=C3=9Fungskriterien (etwa ein fehlendes Komma zwischen Nachnam= e und Vorname) k=C3=B6nnen =C3=BCber die WHERE-Bedingung ausgeschlossen werden. Die Funktionen sind leider in den verschiedenen DBMS h=C3=B6chs= t unterschiedlich implementiert, so da=C3=9F f=C3=BCr ein konkretes Prob= lem die jeweilige Dokumentation zu Rate gezogen werden mu=C3=9F.

T= OP

Zeilen l=C3=B6schen mit DELETE

Syntax

  • DELETE FROM <Tabelle>
    Dies l=C3=B6scht den Inhalt d= er gesamten angegebenen Tabelle. Die Tabelle selbst wird nicht gel=C3=B6scht, das Ergebnis ist eine leere Tabelle.
  • DELETE FROM <Tabelle>
    	WHERE <Bedingung>	
    Dies l=C3=B6scht alle Zeilen der Tabelle,= f=C3=BCr welche die Bedingung zutrifft.
  • DELETE FROM <Tabelle>
    	FROM <Tabelle> [[INNER | LEFT | RIGHT] JOIN] <Tabelle>
    		ON <JOIN-Bedingung> [weitere JOIN-Klauseln]
    	WHERE <Bedingung>	
    Diese ANSI- bzw. Ms-SqlServer-Syntax erm=C3= =B6glicht, analog zur UPDATE-Klausel, das Festlegen weiterer Kriterien zur Auswahl der zu l=C3=B6schenden Zei= len. Nur jene Zeilen, welche den Verkn=C3=BCpfungsbedingungen der JOIN-Klausel entsprechen, werden gel=C3=B6scht.

Beispiele

Vorbemerkung: Wenn Sie die folgenden Beispiele mit dem Sql-interaktiv-le= rnen testen wollen, dann erstellen Sie sich am besten mit Select * Into <neue-Tabelle> From Artikel einige neue Tabellen, welche Sie zum L=C3=B6schen verwenden. Dies erspart Ihnen das st=C3=A4ndige Neueingeben der Daten bz= w. das Zur=C3=BCckkopieren der gesicherten Access-Datenbank.
  • DELETE FROM ARTIKEL
    Dies l=C3= =B6scht alle Zeilen der Tabelle Artikel.
  • DELETE FROM ARTIKEL
    	WHERE A_NR =3D 11
    	
    Dies l=C3=B6scht nur die Zeile mit der Artikel-Nummer 11.
  • DELETE FROM UMSATZ
    	FROM UMSATZ As U INNER JOIN ARTIKEL As A
    	On U.A_NR =3D A.A_=
    NR
    	WHERE A_NR =3D 11
    	
    Dies l=C3=B6scht in der Tabelle UMSATZ alle Zeilen, welche sich a= uf den Artikel 11 beziehen.
  • DELETE FROM UMSATZ
    FROM ARTIKELAs A INNER JOIN UMSATZ As U
    	ON A.A_NR =3D U.A_=
    NR INNER JOIN
    		(SELECT B.A_NR,
    			MAX(B.A_PREIS * C.A_STUECK) As Maximum
    		FROM Artikel As B Inner Join Umsatz As C
    		On B.A_Nr =3D C.A_Nr
    		Group By B.A_NR) As D
    	On U.A_NR =3D D.A_=
    NR And A.A_PREIS * U.A_STUECK < D.Maximum
    Diese nur noch auf ANSI-kompatiblen DBMS funktionierende Beispiel besti= mmt zun=C3=A4chst =C3=BCber die Unterabfrage zu jeder Artikelnummer den h=C3=B6chsten Einzelumsatz. Die JOIN-Anweisung verkn=C3=BCpft diese= aus zwei Spalten und vier Zeilen bestehende Tabelle mit den beiden anderen Tabellen, so da=C3=9F zun=C3=A4chst die Artikelnummern einander= zugeordnet sind und zus=C3=A4tzlich alle Zeilen ausgew=C3=A4hlt werden,= deren Produkt aus A_Preis und A_Stueck kleiner dem Maximum f=C3=BCr die= sen Artikel ist. Diese Zeilen werden gel=C3=B6scht.
  • F=C3=BCr das folgende Beispiel f=C3=BCgen Sie zun=C3=A4chst in die = Tabelle ARTIKEL einen neuen Artikel ein. Da eine JOIN-Klausel genutzt wird, gelingt dies nicht mit Ms-Access bzw. dem Sql-interaktiv.= Dort m=C3=BCssen Sie sich mit der korrespondierenden SELECT-Klausel begn=C3=BCgen.
    INSERT INTO ARTIKEL (A_NR, A_NAME, A_PREIS)
    	VALUES(55, 'Jeans', 99.90)
    Mit diesem Artikel ist kein Umsatz gemacht worden, er soll deshalb gel=C3= =B6scht werden.
    DELETE FROM ARTIKEL
    	FROM ARTIKEL As A LEFT JOIN UMSATZ As U
    	On A.A_NR =3D U.A_=
    NR
    	WHERE U.UMSATZ_NR IS NULL

Bemerkungen

  • Ersetzen Sie bei komplexen Anweisungen mit eigenst=C3=A4ndigem FROM= -Abschnitt zun=C3=A4chst die erste Zeile 'DELETE FROM <Tabelle>' durch 'SELECT *'. Damit werden Ihnen all= e Zeilen ausgegeben, die als Kandidaten zum L=C3=B6schen ausgew=C3=A4hlt werden.
  • Wird eine interaktive Umgebung genutzt, die Transaktionen unterst=C3= =BCtzt, dann l=C3=A4=C3=9Ft sich das Testen von DELETE-Befehlen vereinfachen. Vor dessen Ausf=C3=BChrung wird eine Transaktion gestart= et, dann der L=C3=B6schbefehl ausgef=C3=BChrt und das Ergebnis anschlie=C3=9Fend mit einer SELECT-Abfrage =C3=BCberpr=C3=BCft. Am End= e wird die Transaktion per RollBack wieder zur=C3=BCckgesetzt, so da=C3=9F= keine =C3=84nderungen an den Tabellen gespeichert werden.

    Wenn Sie mit dem OSql.exe interaktiv eine DosBox ge=C3=B6ffnet haben, = so k=C3=B6nnen Sie schrittweise die folgenden Zeilen aus dem linken Fenster eingeben und jeweils anschlie=C3=9Fend mit Return best=C3= =A4tigen.

    Begin Transaction
    go
    
    Select * From Umsatz
    go
    
    Delete From Umsatz Where A_Nr < 13
    go
    
    Select * From Umsatz
    go
    
    RollBack Transaction
    go
    
    Select * From Umsatz
    
    Tr=
    ansaktion starten
    
    
    Ausgabe von 9 Zeilen
    
    
    L=C3=B6schen aller Zeilen mit A_Nr < 13
    
    
    Ausgabe 4 Zeilen
    
    
    Transaktion zur=C3=BCcksetzen
    
    
    Ausgabe von wieder 9 Zeilen
    
    

=C2=A9 2003-2008 J=C3= =BCrgen Auer, Berlin. , Original: http:= //www.sql-und-xml.de/sql-tutorial/
Copyright der Druckversion: S= ie d=C3=BCrfen diese Version f=C3=BCr den privaten Gebrauch und / oder z= u Lehrzwecken nutzen, ausdrucken und in unver=C3=A4nderter Form kostenlos weitergeben. Sie k=C3=B6nne= n diese Version online stellen, sofern auf der hinf=C3=BChrenden Seite auf das Original verwiesen wird. Die Meta-Angabe robots=3D'noi= ndex' verhindert eine Indizierung durch Suchmaschinen.
------------hCIO5lKGmo8K5cqvFf690d Content-Disposition: inline; filename=favicon.ico Content-Type: image/x-icon; name=favicon.ico Content-Location: http://www.sql-und-xml.de/images/favicon.ico Content-Transfer-Encoding: Base64 AAABAAUAICAAAAEACACoCAAAVgAAABAQAAABAAgAaAUAAP4IAAAQEBAAAQAEACgB AABmDgAAICACAAEAAQAwAQAAjg8AABAQAgABAAEAsAAAAL4QAAAoAAAAIAAAAEAA AAABAAgAAAAAAIAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA AACAAIAAgIAAAMDAwADA3MAA8MqmANTw/wCx4v8AjtT/AGvG/wBIuP8AJar/AACq /wAAktwAAHq5AABilgAASnMAADJQANTj/wCxx/8Ajqv/AGuP/wBIc/8AJVf/AABV /wAASdwAAD25AAAxlgAAJXMAABlQANTU/wCxsf8Ajo7/AGtr/wBISP8AJSX/AAAA /gAAANwAAAC5AAAAlgAAAHMAAABQAOPU/wDHsf8Aq47/AI9r/wBzSP8AVyX/AFUA /wBJANwAPQC5ADEAlgAlAHMAGQBQAPDU/wDisf8A1I7/AMZr/wC4SP8AqiX/AKoA /wCSANwAegC5AGIAlgBKAHMAMgBQAP/U/wD/sf8A/47/AP9r/wD/SP8A/yX/AP4A /gDcANwAuQC5AJYAlgBzAHMAUABQAP/U8AD/seIA/47UAP9rxgD/SLgA/yWqAP8A qgDcAJIAuQB6AJYAYgBzAEoAUAAyAP/U4wD/sccA/46rAP9rjwD/SHMA/yVXAP8A VQDcAEkAuQA9AJYAMQBzACUAUAAZAP/U1AD/sbEA/46OAP9rawD/SEgA/yUlAP4A AADcAAAAuQAAAJYAAABzAAAAUAAAAP/j1AD/x7EA/6uOAP+PawD/c0gA/1clAP9V AADcSQAAuT0AAJYxAABzJQAAUBkAAP/w1AD/4rEA/9SOAP/GawD/uEgA/6olAP+q AADckgAAuXoAAJZiAABzSgAAUDIAAP//1AD//7EA//+OAP//awD//0gA//8lAP7+ AADc3AAAubkAAJaWAABzcwAAUFAAAPD/1ADi/7EA1P+OAMb/awC4/0gAqv8lAKr/ AACS3AAAerkAAGKWAABKcwAAMlAAAOP/1ADH/7EAq/+OAI//awBz/0gAV/8lAFX/ AABJ3AAAPbkAADGWAAAlcwAAGVAAANT/1ACx/7EAjv+OAGv/awBI/0gAJf8lAAD+ AAAA3AAAALkAAACWAAAAcwAAAFAAANT/4wCx/8cAjv+rAGv/jwBI/3MAJf9XAAD/ VQAA3EkAALk9AACWMQAAcyUAAFAZANT/8ACx/+IAjv/UAGv/xgBI/7gAJf+qAAD/ qgAA3JIAALl6AACWYgAAc0oAAFAyANT//wCx//8Ajv//AGv//wBI//8AJf//AAD+ /gAA3NwAALm5AACWlgAAc3MAAFBQAPLy8gDm5uYA2traAM7OzgDCwsIAtra2AKqq qgCenp4AkpKSAIaGhgB6enoAbm5uAGJiYgBWVlYASkpKAD4+PgAyMjIAJiYmABoa GgAODg4A8Pv/AKSgoACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAD///////////////+czZgfnMiZ/8nImf/jypn/48qZ/+PK mf/jwhn/ycIZ/5zHGf+cxxn//////////////////////////////7//wfBwP5zm c//8zTP/+M8z/+HPM//DzzP/j88z/5/PM/+c5nP/wfDz/////////////////ygA AAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACA AAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYA1PD/ALHi/wCO1P8Aa8b/AEi4 /wAlqv8AAKr/AACS3AAAerkAAGKWAABKcwAAMlAA1OP/ALHH/wCOq/8Aa4//AEhz /wAlV/8AAFX/AABJ3AAAPbkAADGWAAAlcwAAGVAA1NT/ALGx/wCOjv8Aa2v/AEhI /wAlJf8AAAD+AAAA3AAAALkAAACWAAAAcwAAAFAA49T/AMex/wCrjv8Aj2v/AHNI /wBXJf8AVQD/AEkA3AA9ALkAMQCWACUAcwAZAFAA8NT/AOKx/wDUjv8Axmv/ALhI /wCqJf8AqgD/AJIA3AB6ALkAYgCWAEoAcwAyAFAA/9T/AP+x/wD/jv8A/2v/AP9I /wD/Jf8A/gD+ANwA3AC5ALkAlgCWAHMAcwBQAFAA/9TwAP+x4gD/jtQA/2vGAP9I uAD/JaoA/wCqANwAkgC5AHoAlgBiAHMASgBQADIA/9TjAP+xxwD/jqsA/2uPAP9I cwD/JVcA/wBVANwASQC5AD0AlgAxAHMAJQBQABkA/9TUAP+xsQD/jo4A/2trAP9I SAD/JSUA/gAAANwAAAC5AAAAlgAAAHMAAABQAAAA/+PUAP/HsQD/q44A/49rAP9z SAD/VyUA/1UAANxJAAC5PQAAljEAAHMlAABQGQAA//DUAP/isQD/1I4A/8ZrAP+4 SAD/qiUA/6oAANySAAC5egAAlmIAAHNKAABQMgAA///UAP//sQD//44A//9rAP// SAD//yUA/v4AANzcAAC5uQAAlpYAAHNzAABQUAAA8P/UAOL/sQDU/44Axv9rALj/ SACq/yUAqv8AAJLcAAB6uQAAYpYAAEpzAAAyUAAA4//UAMf/sQCr/44Aj/9rAHP/ SABX/yUAVf8AAEncAAA9uQAAMZYAACVzAAAZUAAA1P/UALH/sQCO/44Aa/9rAEj/ SAAl/yUAAP4AAADcAAAAuQAAAJYAAABzAAAAUAAA1P/jALH/xwCO/6sAa/+PAEj/ cwAl/1cAAP9VAADcSQAAuT0AAJYxAABzJQAAUBkA1P/wALH/4gCO/9QAa//GAEj/ uAAl/6oAAP+qAADckgAAuXoAAJZiAABzSgAAUDIA1P//ALH//wCO//8Aa///AEj/ /wAl//8AAP7+AADc3AAAubkAAJaWAABzcwAAUFAA8vLyAObm5gDa2toAzs7OAMLC wgC2trYAqqqqAJ6engCSkpIAhoaGAHp6egBubm4AYmJiAFZWVgBKSkoAPj4+ADIy MgAmJiYAGhoaAA4ODgDw+/8ApKCgAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP// AAD///8AcHAAAHBwAAEAAAABAAAAAABwcHBwcAABAAAAAQAAAAAAAHBwcAAAAQAA AAEAAAAAAABwcHAAAAEAAQABAAAAAABwcHBwcAABAAEAAQAAAABwcHAAcHAAAQEB AQEAAAAAcHAAAHBwAAEBAAEBAAAAAAAAAAAAAAAAAAAAAAAAAABwcHBwAAAAAAEB AQAAAAAAcHBwcHAAAAEBAQEBAAAAAAAAcHBwAAABAQEBAQAAAAAAcHBwAAAAAQAB AAEAAAAAAHBwAABwAAEAAAABAAAAAABwcABwcAABAQABAQAAAAAAcHBwcHAAAQEB AQEAAAAAAABwcHAAAAABAQEAAAAAADLoAACC6AAAxukAAMapAACCqQAAEgkAADJJ AAD//wAADxgAAAYIAADGCQAAjqkAAJrpAACSSQAAggkAAMcZAAAoAAAAEAAAACAA AAABAAQAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA AACAAIAAgIAAAMDAwACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AMwA zAEAAQAADMzMAQABAAAAzMABAAEAAADMwAEBAQAADMzMAQEBAADMwMwBEREAAMwA zAEQEQAAAAAAAAAAAADMzAAAERAAAMzMwAEREQAAAMzAARERAAAMzAABAQEAAAzA DAEAAQAADMDMARARAAAMzMwBEREAAADMwAAREAAAMugAAILoAADG6QAAxqkAAIKp AAASCQAAMkkAAP//AAAPGAAABggAAMYJAACOqQAAmukAAJJJAACCCQAAxxkAACgA AAAgAAAAQAAAAAEAAQAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////nM2YH5zI mf/JyJn/48qZ/+PKmf/jypn/48IZ/8nCGf+cxxn/nMcZ//////////////////// //////////+//8HwcD+c5nP//M0z//jPM//hzzP/w88z/4/PM/+fzzP/nOZz/8Hw 8/////////////////8oAAAAEAAAACAAAAABAAEAAAAAAIAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMugAAALoAACG6QAAxqkAAIIJ AAASSQAA//8AAD94AAAeOAAAzBkAAIgJAAAZSQAAOckAACiJAAAMGQAAjjkAAA== ------------hCIO5lKGmo8K5cqvFf690d--