Erlernen einer Datenbanksprache: Structured Query Language (SQL) I

From DHVLab

Revision as of 16:32, 19 November 2020 by Jschulz (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Einstieg in SQL

Im vorangehenden Abschnitt sind wir bereits zwei Mal mit der Datenbanksprache SQL in Kontakt gekommen, zum Einen beim Import einer CSV-Datei, zum Anderen bei der Erstellung einer Tabelle. Die beiden zugehörigen SQL-Befehle seien an dieser Stelle zur Erinnerung noch einmal angeführt:

  • Anlegen einer Tabelle in phpMyAdmin (mit fortlaufender ID-Spalte, zugleich Primärschlüssel):

CREATE TABLE Historiker
(
historikerID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255),
vorname varchar(255),
einrichtung varchar(255),
ort varchar(255)
);

  • Import einer CSV-Datei in die Datenbank:

LOAD DATA LOCAL INFILE '[pfad]/dateiname.csv' INTO TABLE `tabellenname` FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS;

Es ist also an der Zeit, dass wir uns nun umfassend mit der Structured Query Language auseinandersetzen. Ein paar grundlegende Informationen zu SQL:

  • SQL ist semantisch an die englische Umgangssprache angelehnt und besitzt eine relativ einfach aufgebaute Syntax
  • Der Bestandteil "Query" bezieht sich auf eine der Hauptaufgaben der Sprache: Das Abfragen von, in einer Datenbank vorgehaltenen Daten, um sie dem/der Benutzer/in oder einer Anwendersoftware zur Verfügung zu stellen
  • SQL unterscheidet nicht zwischen Groß- und Kleinschreibung in den Befehlen. Im Folgenden werden die SQL-Befehle stets in Großbuchstaben geschrieben, um die Syntax besser verständlich zu machen. Dies ist im Anwendungsfall nicht zwangsläufig erforderlich.
  • Abfrageergebnisse werden stets als neue Tabelle ausgegeben und sind beliebig weiter verarbeitbar.

SQL: DDL, DCL und DML

Die Abfragen/Befehle der Datenbanksprache SQL lassen sich in drei Kategorien unterteilen:

  • Data Definition Language (DDL)
  • Data Control Language (DCL)
  • Data Manipulation Language (DML)


DDL: Datenstrukturen anlegen, ändern
Der oben angeführte Befehl zur Erstellung einer Tabelle gehört zur DDL, da er ein Datenbankschema definiert. Neben CREATE TABLE existieren in SQL u.a. folgende DCL-Befehle:

SQL-Eingabe Beschreibung
ALTER TABLE Historiker ADD Postleitzahl int(5) Ergänzt in der Tabelle 'Historiker' eine Spalte namens 'Postleitzahl' mit der Länge von 5 Zeichen
DROP TABLE Historiker Löscht die Tabelle 'Historiker'
CREATE INDEX idx_name ON Historiker (name) Zur Beschleunigung der Suche nach Datensätzen in der Tabelle 'Historiker' wird eine Index mit der Bezeichnung idx_name angelegt.
DROP INDEX idx_name Der eben angelegte Index kann selbstverständlich auch wieder gelöscht werden


DCL: Verwaltung von Zugriffsrechten
Mit DCL können Berechtigungen innerhalb des DBMS vergeben werden; da dies für uns nicht so sehr von Relevanz ist (noch sind wir keine Datenbank-Admins), werden wir gleich zu DML übergehen.

DML:
Die Datenbearbeitungssprache DML ermöglicht uns das Auswählen (SELECT), Einfügen (INSERT INTO), Ändern (UPDATE) und Löschen (DELETE FROM/TRUNCATE TABLE) von Daten innerhalb von Tabellen[A 1]. Mit dieser Art von Datenbankanfragen werden wir am häufigsten in unserer tagtäglichen Arbeit mit relationalen Datenbanken konfrontiert. Im Folgenden werden wir uns wichtige Datenbankanfragen näher ansehen.

Datenbankanfragen (DML/DQL): Daten lesen, schreiben, ändern, löschen

Mit Hilfe von SQL können Anfragen an eine relationale Datenbank gestellt werden[A 2]. Ein Parser zerlegt die Anfrage in ihre einzelnen relationalen Operatoren, um mit Hilfe der daraus gewonnenen Informationen die durch den Nutzer gestellte Anfrage zu beantworten.

Grundform einer Datenbankanfrage

SELECT * (* steht für "all"; es kann auch gezielt nach einen oder mehrere Attributsnamen gesucht werden, durch Kommata getrennt)
FROM (ein oder mehrere Tabellenname)
WHERE (Bedingung)
Optionale Ergänzungen:
GROUP BY (Zusammenfassung mehrerer Zeilen mit demselben Attribut)
HAVING (Bedingung; z.B. nur wenn mehr als drei Vorkommen eines Attributs)
ORDER BY (Sortierung nach einem bestimmten Attribut)

Grundlegende Hinweise zur Grundform einer Datenbankanfrage:

  • Die SQL-Syntax ist in funktionale Einheiten gegliedert, die man Klauseln nennt (z.B. SELECT-Klausel, WHERE-Klausel).
  • Es müssen nicht alle dieser Klauseln in einer Anfrage vorkommen.
  • Die oben angeführte Reihenfolge muss jedoch immer eingehalten werden.
  • SQL-Befehle werden stets mit einem Semikolon abgeschlossen.
  • Möchten Sie eine abgeschickte Anfrage abändern, so genügt ein Klick auf "Inline bearbeiten" unterhalb des angezeigten SQL-Befehls.
  • Sobald Sie beginnen, eine SQL-Klausel einzugeben, werden Ihnen über die Autovervollständigung Eingabemöglichkeiten angezeigt.
  • Senden Sie eine fehlerhafte SQL-Anfrage ab, wird Ihnen eine Fehlermeldung ausgegeben. Diese kann (muss aber nicht immer) hilfreich sein, um dem Fehler auf den Grund zu gehen (z.B. wenn eine schließende Klammer fehlt oder ein Anführungszeichen falsch gesetzt wurde).
  • Zeilenumbrüche und Leerzeichen können beliebig im Code gesetzt werden; dies empfiehlt sich aus Gründen der besseren Übersichtlichkeit.
  • Abfrageergebnisse können unmittelbar exportiert bzw. als neue Tabelle abgespeichert werden.


Verschiedene Datenbankanfragen

Einfache Abfrage (= Selektion)

~ Geben Sie eine Anfrage an die Datenbank ein, um sich die Tabelle 'Historiker' komplett ausgeben zu lassen.

SELECT * FROM `historiker`;



Abfrage mit Auswahl der Spalten (= Projektion)

~ Geben Sie eine Anfrage an die Datenbank ein, um sich von der Tabelle 'Historiker' nur die Spalten `vorname` und `name` ausgeben zu lassen.

SELECT `vorname`, `name` FROM `Historiker`;



  • Bei einer Selektion können einzelne Spalten ausgewählt werden
  • Die Liste der Feldnamen ist kommagetrennt, hinter dem letzten Feldnamen vor der FROM-Klausel darf kein Komma stehen!
  • Die Reihenfolge der Spalten kann bei der Ausgabe verändert werden
  • Spalten können bei der Ausgabe beliebig oft ausgewählt werden



Distinct-Abfrage

~ Geben Sie eine Anfrage an die Datenbank ein, um sich von der Tabelle 'Historiker' alle vorhandenen Unistandorte nur einmal ausgeben zu lassen (nicht zu verwechseln mit GROUP BY).

SELECT DISTINCT `ort` FROM `Historiker`;



Gefilterte Abfrage

~ Geben Sie eine Anfrage an die Datenbank ein, um sich von der Tabelle 'Historiker' nur die Spalten `vorname` und `name` der Historiker ausgeben zu lassen, die in München wohnhaft sind.

SELECT `vorname`, `name` FROM `Historiker` WHERE `ort` = 'München';



Abfrage mit HAVING-Klausel

~ Geben Sie eine Anfrage an die Datenbank ein, um sich von der Tabelle 'Historiker' die Anzahl der Historiker pro Universitätsstandort ausgeben zu lassen, jedoch mit der Bedingung, dass dort mehr als 10 Historiker tätig sind.

SELECT COUNT(`id`), `ort` FROM `Historiker` GROUP BY `ort` HAVING COUNT(`id`) > 10;



  • Die HAVING-Klausel kann im Gegensatz zur WHERE-Klausel in Verbindung mit Aggregatfunktionen[A 3] wie COUNT eingesetzt werden.



Limitierung des Abfrageergebnis

~ Geben Sie eine Anfrage an die Datenbank ein, um sich von der Tabelle 'Historiker' die Spalten `vorname` und `name` nur der ersten fünf Historiker ausgeben zu lassen, die in München wohnhaft sind.

SELECT `vorname`, `name` FROM `Historiker` WHERE `ort` = 'München' LIMIT 5;



  • Es ist ebenso möglich, sich aus der Ergebnismenge nur eine Anzahl ausgeben zu lassen: ... FROM `Historiker` LIMIT 2, 5. In diesem Fall würden fünf Datensätze ausgegeben, beginnend beim zweiten Datensatz, d.h. Datensatz 3-7.



Einschub: Operatoren, Platzhalter, Anführungszeichen, Kommentare

Der "SFW"-Block (SELECT, FROM, WHERE) bzw. die "WHERE-Klausel" erlauben eine Selektion einzelner Zeilen aus einer Tabelle, deren Inhalte einem bestimmten Muster entsprechen.

Für die Selektion stehen verschiedene, i.d.R. beliebig kombinierbare Operatoren zur Wahl (Beispielabfragen siehe unten):

Operator Funktion
= absolute Übereinstimmung zwischen Suchanfrage und Feldinhalt
!= oder <> absolut keine Übereinstimmung zwischen Suchanfrage und Feldinhalt
>= Größer oder gleich
<= Kleiner oder gleich
LIKE relative Übereinstimmung zwischen Suchanfrage und Feldinhalt. Der LIKE-Operator ermöglicht eine trunktierte Suche unter Verwendung von Platzhaltern

Für die trunktierte Suche mit dem LIKE-Operator kommen folgende Platzhalter zum Einsatz:

Platzhalter Funktion (erklärt anhand eines Beispiel)
% beliebig große Anzahl an Zeichen: Sch% -> Schulz; Scholz; Schneider etc.
_ genau ein beliebiges Zeichen: Sch_lz -> Schulz; Scholz
RLIKE ermöglicht die Suche nach regulären Ausdrücken, also einer abstrakten Darstellung von Zeichenketten
NOT LIKE keine relative Übereinstimmung zwischen Suchanfrage und Feldinhalt
AND, OR und / oder
IS NULL, IS NOT NULL[A 4] ermöglicht die Suche nach regulären Ausdrücken, also einer abstrakten Darstellung von Zeichenketten
BETWEEN 'Zahl 1' AND 'Zahl 2' Definition eines numerischen Wertebereichs (Werte können Nummern, Daten oder Text sein). Anfangs- und Endwert sind mitinbegriffen.


Beispielabfragen:
SELECT * FROM `Historiker` WHERE `name` LIKE 'M_mmsen' AND (Ort = 'Berlin' OR Ort = 'Bonn');
SELECT * FROM `Historiker` WHERE `ort` <> 'Berlin';
SELECT * FROM `Historiker` WHERE `postleitzahl` BETWEEN '85000' AND '89000';
SELECT * FROM `Historiker` WHERE `ort` IS NULL;


Wichtiger Hinweis: Gewiss sind Ihnen bereits die unterschiedlichen Anführungszeichen aufgefallen. Daher sei an dieser Stelle zum besseren Verständnis kurz auf die Unterschiede verwiesen[A 5]:

  • Doppelte Anführungszeichen (" ") und einfache Anführungszeichen/Hochkommata (' ') können synonym verwendet werden, um eine Zeichenkette (String), also z.B. einen zu suchenden Text zu kennzeichnen. Sie dürfen jedoch nur einheitlich und nicht gemischt verwendet werden.
  • Backticks[A 6] finden bei Tabellen- und Feldnamen Anwendung (SELECT `name` FROM `Historiker`). Ihre Verwendung ist nicht obligatorisch, es sei denn wenn Tabellen- oder Feldnamen
    • von MySQL missinterpretiert werden könnten (z.B. SELECT `alter`[A 7] FROM `Personen`;) oder
    • ein Leerzeichen enthalten (z.B. `spalte 1`)



Kommentare:
Es besteht die Möglichkeit, innerhalb von SQL-Statements Kommentare einzufügen, um einzelne Bestandteile auszukommentieren. Um eine einzelne Zeile auszukommentieren, setzt man zwei Minuszeichen, gefolgt von einem Leerzeichen: --[Leerzeichen]. Nachfolgender Text wird bis zum Zeilenende auskommentiert.
Um mehrere Zeilen, oder einen Bestandteil innerhalb einer Zeile auszukommentieren, setzt man folgende Zeichenkombination: /* ... */


Gefilterte Abfrage mit Sortierung

~ Geben Sie eine Anfrage an die Datenbank ein, um sich von der Tabelle 'Historiker' nur die Spalten `vorname` und `name` ausgeben zu lassen, sortiert nach `vorname`

SELECT `vorname`, `name` FROM `Historiker` ORDER BY `vorname`;
Die Anordnung der Gruppierung lässt sich durch die Anfügung DESC (= descending; absteigend) oder ASC (= ascending; aufsteigend) bestimmen. Standardmäßig wird aufsteigend sortiert.



  • Es ist auch möglich, nach dem Inhalt mehrerer Spalten zu sortieren, z.B: ORDER BY `vorname` ASC, `nachname` DSC. In diesem Fall wird zunächst nach dem Vornamen (aufsteigend), dann nach dem Nachnamen als zweites Kriterium (absteigend) sortiert.



Abfrage unter Zuteilung von Korrelationsnamen

SELECT `plz` AS Postzeitzahl, `ort` AS Universitätsstandort FROM `Historiker` ORDER BY `vorname`;
Bei der Ausgabetabelle werden die entsprechenden Spalten mit den Korrelationsnamen überschrieben. Sinnvoll ist dies v.a. bei der Abfrage mit verknüpften Tabellen (Joins), der wir uns weiter unten zuwenden werden. Alternativ können Aliasnamen auch wie folgt vergeben werden:
SELECT `plz` "Postzeitzahl", `ort` "Universitätsstandort" FROM `Historiker` ORDER BY `vorname`;


Einfügung von Werten in eine bestehende Tabelle

INSERT INTO `Historiker` (`vorname`, `name`) VALUES (Theodor, Mommsen), (Theodor, Schieder);
Soll ein Feld ohne Inhalt bleiben, so kann "NULL" gesetzt oder der entsprechende Feldname weggelassen werden. Die Reihenfolge der Werte muss jedoch immer mit der der Tabellenspalten übereinstimmen.

INSERT INTO tabelle2 (id, spalte2, spalte3) SELECT id, spalte2, spalte3 FROM tabelle1 WHERE id > 2;
Mit INSERT INTO ... SELECT können in gleicher Weise Datensätze aus einer Tabelle 1 in eine Tabelle 2 überführt werden. Die bereits vorhandenen Daten in Tabelle 2 bleiben davon unberührt. Die Datentypen in Tabelle 1 und 2 müssen übereinstimmen.


Werte in neue Tabelle überführen

SELECT spalte1, spalte3, ... INTO neuetabelle FROM altetabelle WHERE [Bedingung];
Die neue Tabelle wird mit den Spaltennamen und Datentypen der alten Tabelle erstellt. Um neue Spaltennamen zu vergeben, teilen Sie in der Abfrage Korrelationsnamen zu.


Aktualisierung eines Wertes in einer bestehenden Tabelle

UPDATE `Historiker` SET `vorname` = 'Theodor' WHERE `name` = 'Schieder';
UPDATE `Historiker` SET `vorname` = 'NULL' WHERE `id` = 92;
Um den Inhalt eines Feldes zu löschen wird "NULL" gesetzt.


Löschen eines Tabellenbereiches

DELETE FROM `Historiker` WHERE `id` < 197;

Zwei wichtige Hinweise:

  1. Verwechseln Sie nicht die beiden Zeichen < und > !
  2. Vergessen Sie nicht, eine WHERE-Klausel zu verwenden, da sonst ALLES aus der Tabelle gelöscht wird.



Löschen des gesamten Tabelleninhalts

DELETE FROM `Historiker`
Der DELETE-Befehl ohne WHERE-Klausel tilgt alle Daten, die Tabellenstruktur bleibt jedoch erhalten.
Beachten Sie: Der Befehl wird unwiderruflich durchgeführt; Sie werden vor Absenden des Befehls nicht mehr gewarnt.


Zurück zu Praktischer Einstieg in phpMyAdmin ⇐⇒ Weiter zu Erlernen einer Datenbanksprache: Structured Query Language (SQL) II

Anmerkungen

  1. Teilweise wird auch von DQL (Data Query Language) gesprochen, wenn Daten nur abgefragt und nicht manipuliert werden.
  2. Wie bereits bei den anderen Operationen kann in phpMyAdmin auch die Suche ohne den Einsatz von SQL über die entsprechende Suchmaske (via "Suche" in der operativen Leiste) erfolgen. Nach dem Abschicken einer Suchanfrage wird Ihnen jeweils die zugehörige SQL-Anfrage mit ausgegeben.
  3. Zu Funktionen vgl. ausführlich die nachfolgende Seite dieses Manuals.
  4. NULL bedeutet "Feld ohne Werte", d.h. bei Erstellung des Datensatzes wurde kein Wert eingetragen. NULL ist nicht zu verwechseln mit leeren Strings (von der Zeichenlänge 0).
  5. Fileformat: Diese Seite ist allgemein zu empfehlen, wenn man sich über die Kodierung eines Zeichens informieren möchte.
  6. Vgl. hierzu den Eintrag in DH-Lehre
  7. Das Wort alter würde ansonsten als SQL-Operator interpretiert.