SQL - Benutzer-Homepage-Server der TH Mittelhessen

Werbung
Mehr SQL
Views
SQL-Anweisung 1. Definition einer View
Beispiel:
Kontakte als View
create view Kontakte as
select Vorname || ’ ’ || Name as Name,
PLZ || ’ ’ || Ort as Anschrift2 from
union
select Firma as Name, ’PF ’|| Postfach
PLZ || ’ ’ || Ort as Anschrift2 from
Str as Anschrift1,
Kunde
as Anschrift1,
Lieferant
SQL-Anweisung 2. Verwendung einer View
Beispiel:
Teile der Kontakte ausgeben
select * from Kontakte
where Name like ’%Kehl%’
Ausgabe:
name
| anschrift1
|
anschrift2
-------------+---------------+------------------Thomas Kehl | Im Riesling 3 | 68734 Eltville
Thomas Kehl | Weinstr. 3
| 79675 Kaiserstuhl
(2 rows)
SQL-Anweisung 3. View löschen
Beispiel:
Kontakte löschen
drop view Kontakte
1
Mehr SQL
Benutzerdefinierte Funktionen
SQL-Anweisung 4. Eine einfache benutzerdefinierte Funktion
Beispiel:
Eine einfache Funktion erstellen
create function kartonpreis(numeric) returns numeric as $$
select $1 * 11;
$$ language sql
SQL-Anweisung 5. Einfache Funktionen verwenden
Beispiel:
Kartonpreis aus Preis berechnen
select ArtNr, Bez, kartonpreis(Preis) as "Kartonpreis"
from Artikel
Ausgabe:
artnr |
bez
| Kartonpreis
--------+---------------------+------------100001 | Les Châteaux
|
196.90
100002 | Chablis
|
170.50
100003 | Château Caraguilhes |
163.90
604851 | Prosecco Val Monte |
83.60
145119 | Le Cop de Cazes
|
75.90
(5 rows)
SQL-Anweisung 6. Funktion auf einer Tabelle
Beispiel:
Funktion erstellen
create function kartonpreis(Artikel) returns numeric as $$
select $1.preis * 11;
$$ language sql
Wir haben zwei Funktionen mit dem Namen „kartonpreis“ erstellt, die
sich durch ihre Parameter unterscheiden, d.h. SQL unterstützt das Überladen von Funktionen.
2
Mehr SQL
SQL-Anweisung 7. Verwendung der Funktion
Beispiel:
Kartonpreise ausgeben
select ArtNr, Bez, kartonpreis(Artikel.*) as "Kartonpreis"
from Artikel
Ausgabe:
artnr |
bez
| Kartonpreis
--------+---------------------+------------100001 | Les Châteaux
|
196.90
100002 | Chablis
|
170.50
100003 | Château Caraguilhes |
163.90
604851 | Prosecco Val Monte |
83.60
145119 | Le Cop de Cazes
|
75.90
(5 rows)
SQL-Anweisung 8. Funktionen löschen
Beispiel:
Beide Funktionen werden wieder entfernt
drop function kartonpreis(numeric);
drop function kartonpreis(artikel);
Benutzerdefinierte Funktionen und Prozeduren
Der SQL-Standard (ab SQL:1999) kennt benutzerdefinierte Funktionen
und Prozeduren.
Benutzerdefinierte Funktionen haben einen Rückgabewerte, benutzerdefinierte Prozeduren haben keinen Rückgabewert. Außerdem unterscheiden sie sich durch ihren Aufruf: benutzerdefinierte Prozeduren werden
mit dem SQL-Befehl call aufgerufen, wohingegen Funktionen in einem
Ausdruck auftreten.
PostgreSQL hat keine Implementierung der Call-Anweisung, deshalb nur
Beispiele von benutzerdefinierten Funktionen hier.
Trigger
3
Mehr SQL
SQL-Anweisung 9. Vorbereitung eines Szenarios mit Triggern
Beispiel:
Einrichten einer Tabelle für die Historie der Kundentabelle
create table HistorieKunde (
like Kunde
);
alter table HistorieKunde
add column Benutzer varchar(20);
alter table HistorieKunde
add column Aktion char(1) check (Aktion in (’i’, ’u’, ’d’));
alter table HistorieKunde
add column Zeitpunkt timestamp;
Die Tabelle HistorieKunde wollen wir verwenden, um alle Änderungen
an den Daten der Tabelle Kunde zu protokollieren.
SQL-Anweisung 10. Funktion programmieren
Beispiel:
Modifikation von Kunden protokollieren
create function auditKunde() returns trigger as $auditKunde$
begin
if ( tg_op = ’INSERT’ ) then
insert into HistorieKunde select new.*, user, ’i’, now();
return new;
elsif ( tg_op = ’UPDATE’ ) then
insert into HistorieKunde select new.*, user, ’u’, now();
return new;
elsif ( tg_op = ’DELETE’ ) then
insert into HistorieKunde select old.*, user, ’d’, now();
return old;
end if;
return null;
end;
$auditKunde$ language plpgsql;
SQL-Anweisung 11. Trigger erzeugen
Beispiel:
Trigger für das Protokoll von Änderungen an Kunden
create trigger InsertTrigger after insert
on Kunde for each row
execute procedure auditKunde();
4
Mehr SQL
create trigger UpdateTrigger after update
on Kunde for each row
execute procedure auditKunde();
create trigger DeleteTrigger after delete
on Kunde for each row
execute procedure auditKunde();
SQL-Anweisung 12. Triggerverwendung provozieren
Beispiel:
Neuen Kunden eingeben, ändern und löschen
insert into Kunde
values ( 200001, ’Neumann’, ’Klaus’, ’Hauptstr.’, ’35390’, ’Gießen’ );
update Kunde
set Str = ’Marktplatz’
where KndNr = 200001;
delete from Kunde
where KndNr = 200001;
SQL-Anweisung 13. Effekt des Triggers
Beispiel:
Protokoll inspizieren
select * from HistorieKunde
Ausgabe:
kndnr | name
|..|
str
|..| ben | a |
zeitpunkt
--------+---------+--+------------+--+-----+---+------------------------200001 | Neumann | | Hauptstr. | | br | i | 2009-04-02 12:11:28.555
200001 | Neumann | | Marktplatz | | br | u | 2009-04-02 12:11:28.665
200001 | Neumann | | Marktplatz | | br | d | 2009-04-02 12:11:28.665
(3 rows)
SQL-Anweisung 14. Trigger löschen
Beispiel:
Protokoll der Aktionen wieder entfernen
drop function auditKunde() cascade;
drop table HistorieKunde;
5
Mehr SQL
Ausgabe:
NOTICE:
NOTICE:
NOTICE:
drop cascades to trigger inserttrigger on table kunde
drop cascades to trigger deletetrigger on table kunde
drop cascades to trigger updatetrigger on table kunde
Abfrage war erfolgreich nach 150 ms. Keine Zeilen geliefert.
Sequenzen
Manchmal haben Entitäten, die in einer Tabelle gespeichert werden,
„natürliche“ Primärschlüssel. So ist z.B. die Matrikelnummer bei Studierenden eigens von der Studierendenverwaltung so vergeben worden,
dass sie als identifizierendes Merkmal verwendet werden kann. Andere
Systeme, wie z.B. in der Bibliothek können deshalb die Matrikelnummer
als Primärschlüssel einsetzen.
In anderen Fällen gibt es solch ein Merkmal nicht und es wird ein „künstlicher“ Primärschlüssel eingesetzt1 .
Ein solcher Schlüssel kann durch eine Anwendung oder durch das Datenbankmanagementsystem vergeben werden. DBMS sehen Mechanismen
zur Erzeugung von fortlaufenden Werten vor. In SQL ist der Mechanismus der Sequenzgenerator (sequence generator).
SQL-Anweisung 15. Sequenzen
Beispiel:
Erzeugen und Verwenden eines Sequenzgenerators mit Startwert 200000
create sequence KndNr_seq start 200000;
insert into Kunde(KndNr, Name, Vorname, PLZ, Str, Ort)
values( nextval(’KndNr_seq’), ’Neumann’, ’Holger’, ’60311’,
’Heinestr. 12’, ’Frankfurt am Main’);
select * from
Kunde;
Ausgabe:
kndnr |
name
| vorname |
str
|
plz
|
ort
--------+----------+---------+--------------------+---------+------------------100101 | Kehl
| Thomas | Weinstr. 3
| 79675
| Kaiserstuhl
100102 | Kehl
| Thomas | Im Riesling 3
| 68734
| Eltville
100105 | Riesling | Karin
| 67, Rue du Ch?teau | F-68567 | Colmar
200000 | Neumann | Holger | Heinestr. 12
| 60311
| Frankfurt am Main
(4 Zeilen)
1
Die Matrikelnummer ist aus Sicht der Studierendenverwaltung, die die Matrikelnummer ursprünglich vergibt, natürlich auch ein „künstlicher“ Schlüssel – nur für
andere Systeme ist er dann als vorhandenes eindeutiges Merkmal verwendbar.
6
Mehr SQL
Möchte man den aktuellen Wert wissen, kann man die Sequenz abfragen.
Man muss ja einer Kundenverwaltung z.B. wissen, welche Kundennummer das DBMS beim insert vergeben hat:
SQL-Anweisung 16. Sequenzen
Beispiel:
Ermitteln des aktuellen Werts der Sequenz
select currval(’KndNr_seq’);
Ausgabe:
currval
--------200000
(1 Zeile)
Man kann eine Sequenz auch bei der Definition einer Tabelle verwenden.
Dabei verwendet man nextval als Defaultwert für das entsprechende
Attribut der Tabelle. Beim Einfügen eines neuen Datensatzes lässt man
den Wert weg und das DBMS nimmt den nächsten Wert der Sequenz.
SQL-Anweisung 17. Sequenzen
Beispiel:
Verwenden eines Sequenz beim Erzeugen einer Tabelle
create sequence KndNr_seq start 100000;
create table Kunde (
kndnr numeric(6) primary key default nextval(’KndNr_seq’),
name varchar(40) not null,
vorname varchar(40),
str varchar(40),
plz varchar(8) not null,
ort varchar(40) not null
)
Rekursion in SQL
Für den folgenden Abschnitt verwenden wir die Datenbank „Twitter“,
die eine Tabelle FollowedBy hat, in der verzeichnet ist, welcher TwitterUser
welchen Follower hat.
Sehen wir uns die Tabelle mal an:
7
Mehr SQL
SQL-Anweisung 18. Twitter-Datenbank
Beispiel:
In Twitter gibt es TwitterUser und Follower in der Tabelle FollowedBy
select * from FollowedBy
Ausgabe:
twitteruser | follower
-------------+---------Jack
| Sarah
Sarah
| Justin
Sarah
| Jenny
Justin
| Jenny
Justin
| Tommy
(5 Zeilen)
Wenn man wissen möchte, welche Anhänger die Anhänger von ‚Jack‘
haben, dann kann man diese Anfrage mit der Technik des „Self-Joins“
lösen.
Im folgenden Beispiel wird ein solcher „Self-Join“ durchgeführt. Die Besonderheit gegenüber den früheren Beispielen, besteht in der „WITHKlausel“, in der man eine (virtuelle) Tabelle definieren kann, die dann
in der folgenden Anweisung verwendet werden kann.
SQL-Anweisung 19. SQL-Anweisung mit WITH
Beispiel:
Wir wollen die Anhänger der Anhänger von ’Jack’ finden
with
Follower(t,f) as (select F1.TwitterUser as t, F2.Follower as f
from FollowedBy F1, FollowedBy F2
where F1.Follower = F2.TwitterUser)
select t, f from Follower where t = ’Jack’
Ausgabe:
t
|
f
------+-------Jack | Jenny
Jack | Justin
(2 Zeilen)
Mit dieser Technik können wir aber nicht die Anhänger der Anhänger
der Anhänger. . . finden, wenn wir nicht wissen, wieviele Stufen es in der
Anhängerschaft gibt.
Beliebig tiefe Wege in dem Graphen, der die Anhängerschaft beschreibt,
finden wir mit rekursiven Anweisungen:
8
Mehr SQL
SQL-Anweisung 20. Rekursive SQL-Anweisung
Beispiel:
Wir wollen die Anhänger der Anhänger der Anhänger etc. von ’Jack’
finden
with recursive
Follower(t,f) as
(select TwitterUser as t, Follower as f from Followedby
union
select Follower.t, FollowedBy.follower as f
from Follower, FollowedBy
where Follower.f = FollowedBy.TwitterUser)
select t, f from Follower where t = ’Jack’
Ausgabe:
t
|
f
------+-------Jack | Sarah
Jack | Jenny
Jack | Justin
Jack | Tommy
(4 Zeilen)
SQL-Anweisung 21. Transitiver Abschluss
Beispiel:
Alle Beziehungen zwischen den Twitterern, egal über welchen Pfad
with recursive
Follower(t,f) as
(select TwitterUser as t, Follower as f from Followedby
union
select Follower.t, FollowedBy.follower as f
from Follower, FollowedBy
where Follower.f = FollowedBy.TwitterUser)
select t, f from Follower order by t
Ausgabe:
t
|
f
--------+-------Jack
| Sarah
Jack
| Jenny
Jack
| Justin
Jack
| Tommy
Justin | Tommy
Justin | Jenny
Sarah | Tommy
Sarah | Justin
Sarah | Jenny
(9 Zeilen)
9
Mehr SQL
Bisher hatte die Beispielrelation keine Zyklus. Wenn ein Zyklus besteht,
kann eine rekursive Abfrage zu einer unendlichen Schleife führen.
SQL-Anweisung 22. Zyklus in binärer Relation
Beispiel:
Zyklische Beziehung zwischen Twitterern erzeugen
insert into FollowedBy( TwitterUser, Follower)
values (’Tommy’, ’Jack’);
select * from FollowedBy;
Ausgabe:
twitteruser | follower
-------------+---------Jack
| Sarah
Sarah
| Justin
Sarah
| Jenny
Justin
| Jenny
Justin
| Tommy
Tommy
| Jack
(6 Zeilen)
SQL-Anweisung 23. Binäre Relation mit einem Zyklus, 1
Beispiel:
Alle Anhänger von „Jack“
with recursive
Follower(t,f) as
(select TwitterUser as t, Follower as f from Followedby
union
select Follower.t, FollowedBy.follower as f
from Follower, FollowedBy
where Follower.f = FollowedBy.TwitterUser)
select * from Follower where t = ’Jack’
Ausgabe:
t
|
f
------+-------Jack | Sarah
Jack | Jenny
Jack | Justin
Jack | Tommy
Jack | Jack
(5 Zeilen)
10
Mehr SQL
SQL-Anweisung 24. Binäre Relation mit einem Zyklus, 1
Beispiel:
Vorsicht: Folgende Anweisung endet nur, weil ein Timeout eingestellt
ist!!
set statement_timeout = ’1s’;
with recursive
Follower(t,f, depth) as
(select TwitterUser as t, Follower as f, 1 from Followedby
union
select Follower.t, FollowedBy.follower as f, Follower.depth + 1
from Follower, FollowedBy
where Follower.f = FollowedBy.TwitterUser)
select * from Follower where t = ’Jack’
Ausgabe:
FEHLER:
storniere Anfrage wegen Zeitüberschreitung
SQL-Anweisung 25. Binäre Relation mit einem Zyklus, 2
Beispiel:
Einfache Abhilfe: die Zahl der Ergebniszeilen limitieren
with recursive
Follower(t,f, depth) as
(select TwitterUser as t, Follower as f, 1 from Followedby
union
select Follower.t, FollowedBy.follower as f, Follower.depth + 1
from Follower, FollowedBy
where Follower.f = FollowedBy.TwitterUser)
select * from Follower where t = ’Jack’ limit 10
Ausgabe:
t
|
f
| depth
------+--------+------Jack | Sarah |
1
Jack | Jenny |
2
Jack | Justin |
2
Jack | Jenny |
3
Jack | Tommy |
3
Jack | Jack
|
4
Jack | Sarah |
5
Jack | Jenny |
6
Jack | Justin |
6
Jack | Jenny |
7
(10 Zeilen)
11
Mehr SQL
Sudoku in SQL
Mit rekursivem SQL kann man auch Sudoku lösen. Das geht so:
SQL-Anweisung 26. Sudoku in SQL
Beispiel:
Rekursives SQL löst Sudoku
-- Published by Marcin Mank in pgsql-general,
-- based on an Oracle version by Anton Scheffer
with recursive x(s, ind) as
( select sud, position(’ ’ in sud)
from (select ’ 24
38 6 72 91 481 7 3 96 48
97
69
51 75 9 8 414 16 57 9 96
83 ’::text
as sud) xx
union all
select substr( s, 1, ind - 1 ) || z || substr( s, ind + 1 ),
position(’ ’ in repeat(’x’,ind) || substr( s, ind + 1 ) )
from x, (select gs::text as z from Generate_series(1,9) gs) z
where ind > 0
and not exists ( select null
from generate_series(1,9) lp
where z.z = substr( s, ( (ind - 1 ) / 9 ) * 9 + lp, 1 )
or
z.z = substr( s, mod( ind - 1, 9 ) - 8 + lp * 9, 1 )
or
z.z = substr( s, mod( ( ( ind - 1 ) / 3 ), 3 ) * 3
+ ( ( ind - 1 ) / 27 ) * 27 + lp
+ ( ( lp - 1 ) / 3 ) * 6, 1 )
)
)
select s as "Lösung"
from x
where ind = 0;
Ausgabe:
Lösung
----------------------------------------------------------------------------------924156387637289154815743296148562973572391468369874512753928641481635729296417835
Burkhardt Renz
Technische Hochschule Mittelhessen
Fachbereich MNI
Wiesenstr. 14
D-35390 Gießen
Rev 6.1 – 2. Februar 2015
12
Herunterladen