Musterlösung

Werbung
Eidgenössische
Technische Hochschule
Zürich
Ecole polytechnique fédérale de Zurich
Politecnico federale di Zurigo
Swiss Federal Institute of Technology Zurich
Dr. C. Türker
Objektrelationale, erweiterbare Datenbanken
WS03/04
Übung 7
Musterlösung
Aufgabe 1: Typisierte Sichten
Auf den vorherigen Übungsblättern sind Typ- und Tabellenhierarchien für Kunden, Angestellte, Personen und Bestellungen angegeben worden.
1. Realisieren Sie unter Einsatz typisierter Sichten folgende Dienste“ mittels
”
SQL:1999:
(a) Einem Adresshandel werden die Nachnamen, die Adressen und die Telefonnummern aller Kunden verkauft. Stellen Sie eine typisierte Sicht zur
Verfügung, wobei keine weiteren Schutzmechanismen vorgesehen werden müssen.
CREATE TYPE AdresshandelTyp AS
(
Nachname VARCHAR(30),
Anschrift AdressTyp,
Telefonnummern VARCHAR(20) ARRAY[3]
)
NOT FINAL
REF FROM Nachname;
CREATE VIEW Adresshandel OF AdresshandelTyp
(
REF IS oid DERIVED
)
AS SELECT Name, Adresse, Telefone
FROM ONLY(Kunden);
(b) Den Mitarbeitern einer Telefonmarketingfirma sollen nur der Nachname und die Telefonnummern von Kunden angezeigt werden, wobei
natürlich nur die Kunden von Interesse sind, die auch ein Telefon haben.
Diese Firma darf und soll allerdings auch die Telefonnummern aktualisieren können. Es muss aber sichergestellt sein, dass auch anschliessend
ein Kunde noch über mindestens eine Telefonnummer verfügt.
CREATE TYPE TelefonmarketingTyp AS
(
Nachname
VARCHAR(30),
Telefonnummern VARCHAR(20) ARRAY[3]
)
NOT FINAL
REF USING VARCHAR(30);
CREATE VIEW Telefonmarketing OF TelefonmarketingTyp
(
REF IS oid USER GENERATED
)
AS SELECT TelefonmarketingTyp(Name), Name, Telefone
FROM ONLY(Kunden)
WHERE CARDINALITY(Telefone)>0
WITH CHECK OPTION;
(c) Die Telefonmarketingfirma möchte nun nur die Kunden anrufen, die eine Telefonnummer in Zürich haben. Wie ermitteln Sie diese Kunden?
SELECT *
FROM Telefonmarketing
WHERE Telefonnummern[1] LIKE "0041-1%" OR
Telefonnummern[2] LIKE "0041-1%" OR
Telefonnummern[3] LIKE "0041-1%";
2. Setzen Sie nun die obigen Aufgaben mittels DB2SQL um!
Die Umsetzung in DB2SQL muss entsprechend der vorangegangenen Musterlösungen angepasst werden. Wir definieren zunächst eine Tabelle, in denen wir die Telefonnummern der Kunden verwalten und füllen diese mit
Beispieldaten. Aus Demonstrationsgründen spezifizieren wir einen strukturierten Typ für Anschriften, mit dem wir die Generierung von strukturierten
Werten aus einzelnen atomaren Werten zeigen wollen. Diesem Typ geben wir
auch zwei Methoden mit, welche die Anschriften als VARCHAR in einer besonderen Form zurückliefern.
Der AdresshandelTyp wird gemäss den DB2SQL-Vorgaben umgesetzt. Da
DB2 keine Kollektionen unterstützt, definieren wir drei Attribute für die maximal drei zulässigen Telefonnummern.
CREATE TABLE Telefone
(
Person REF(PersonTyp),
Nummer1 VARCHAR(20),
Nummer2 VARCHAR(20),
Nummer3 VARCHAR(20)
) $
INSERT INTO Telefone
VALUES ((SELECT oid FROM Kunden WHERE Kundennummer = 1234),
’0041-1-9876543’, ’0049-172-3432222’, ’0049-611-6733219’) $
INSERT INTO Telefone
VALUES ((SELECT oid FROM Kunden WHERE Kundennummer = 2345),
’0041-1-2612345’, NULL, NULL) $
CREATE TYPE AdressTyp AS
(
Strasse VARCHAR(30),
Nr DECIMAL(4),
PLZ DECIMAL(5),
Ort VARCHAR(25),
Land VARCHAR(20)
)
MODE DB2SQL
NOT FINAL
WITH FUNCTION ACCESS
REF USING INTEGER
METHOD Wohnort() RETURNS VARCHAR(31) LANGUAGE SQL,
METHOD Adresse() RETURNS VARCHAR(89) LANGUAGE SQL $
CREATE METHOD Wohnort()
RETURNS VARCHAR(31)
FOR AdressTyp
RETURN (RTRIM(CAST(CAST(SELF..PLZ AS INT) AS CHAR(5))) || ’ ’ ||
SELF..Ort) $
CREATE METHOD Adresse()
RETURNS VARCHAR(87)
FOR AdressTyp
RETURN (SELF..Strasse || ’ ’ ||
RTRIM(CAST(CAST(SELF..Nr AS INT) AS CHAR(5))) || ’, ’ ||
RTRIM(CAST(CAST(SELF..PLZ AS INT) AS CHAR(5))) || ’ ’ ||
SELF..Ort || ’, ’ ||
SELF..Land) $
CREATE TYPE AdresshandelTyp AS
(
Nachname VARCHAR(30),
Anschrift AdressTyp,
Telefon1 VARCHAR(20),
Telefon2 VARCHAR(20),
Telefon3 VARCHAR(20)
)
MODE DB2SQL
NOT FINAL $
CREATE VIEW Adresshandel OF AdresshandelTyp MODE DB2SQL
(
REF IS oid USER GENERATED UNCHECKED
)
AS
SELECT AdresshandelTyp(CAST(Kundennummer AS CHAR(13))),
Name,
AdressTyp()..Strasse(Strasse)..Nr(Nr)..PLZ(PLZ)..Ort(Ort)),
(SELECT Nummer1 FROM Telefone WHERE Person = k.oid),
(SELECT Nummer2 FROM Telefone WHERE Person = k.oid),
(SELECT Nummer3 FROM Telefone WHERE Person = k.oid)
FROM ONLY(Kunden) k$
-- Die Sicht Adresshandel ist nicht änderbar. Typisierte Sichten, die
-- berechnete Attribute haben, sind generell nicht in DB2 änderbar!
SELECT oid, Nachname, Anschrift..Adresse() AS Anschrift,
Telefon1, Telefon2, Telefon3
FROM Adresshandel $
SELECT Nachname,
CASE WHEN Telefon1 LIKE ’0041-1%’ THEN Telefon1 END AS T1,
CASE WHEN Telefon2 LIKE ’0041-1%’ THEN Telefon2 END AS T2,
CASE WHEN Telefon3 LIKE ’0041-1%’ THEN Telefon3 END AS T3
FROM Adresshandel
WHERE Telefon1 LIKE ’0041-1%’ OR
Telefon2 LIKE ’0041-1%’ OR
Telefon3 LIKE ’0041-1%’ $
CREATE TYPE MarketingTyp AS
(
Nachname VARCHAR(30),
Telefon1 VARCHAR(20),
Telefon2 VARCHAR(20),
Telefon3 VARCHAR(20)
)
MODE DB2SQL
NOT FINAL $
CREATE VIEW Telefonmarketing OF MarketingTyp MODE
(
REF IS oid USER GENERATED UNCHECKED
)
AS
SELECT MarketingTyp(Name),
Name,
(SELECT Nummer1 FROM Telefone WHERE Person
(SELECT Nummer2 FROM Telefone WHERE Person
(SELECT Nummer3 FROM Telefone WHERE Person
FROM ONLY(Kunden) k
WHERE EXISTS(SELECT *
FROM Telefone
WHERE Person = k.oid AND (Nummer1 IS
OR Nummer2 IS
OR Nummer3 IS
DB2SQL
= k.oid),
= k.oid),
= k.oid)
NOT NULL
NOT NULL
NOT NULL)) $
INSERT INTO Kunden
VALUES (KundeTyp(’123459’), ’Richie’, ’Bahnhofstrasse’, 13,
8006, ’Zürich’, CURRENT_DATE, ’[email protected]’,
7733, Franken(4500)) $
SELECT *
FROM Telefonmarketing
WHERE Telefon1 LIKE ’0041-1%’ OR
Telefon2 LIKE ’0041-1%’ OR
Telefon3 LIKE ’0041-1%’ $
Aufgabe 2: Rekursion
Gegeben sei folgende Definition einer Tabelle, die Verwandtschaftsbeziehungen
verwaltet:
CREATE TABLE Stammbaum
(
MenschID
INTEGER PRIMARY KEY,
Name
VARCHAR(30) NOT NULL,
GebDatum
Mutter
Vater
DATE,
INTEGER REFERENCES Stammbaum,
INTEGER REFERENCES Stammbaum
);
1. Ermitteln Sie mittels SQL:1999 alle Vorfahren von ’Jim’.
WITH RECURSIVE Vorfahren(MenschID, Vorfahr) AS
(
SELECT MenschID, Mutter
FROM Stammbaum
WHERE Name = ’Jim’
UNION
SELECT MenschID, Vater
FROM Stammbaum
WHERE Name = ’Jim’
UNION
SELECT v.MenschID, s.Mutter
FROM Vorfahren v, Stammbaum s
WHERE v.Vorfahr = s.MenschID
UNION
SELECT v.MenschID, s.Vater
FROM Vorfahren v, Stammbaum s
WHERE v.Vorfahr = s.MenschID
)
SELECT *
FROM Vorfahren
WHERE Vorfahr IS NOT NULL
ORDER BY MenschID;
2. Ermitteln Sie mittels SQL:1999 alle Nachkommen von ’Bob’.
WITH RECURSIVE Nachkommen(MenschID, Nachkomme) AS
(
SELECT Mutter, MenschID
FROM Stammbaum
UNION
SELECT Vater, MenschID
FROM Stammbaum
UNION
SELECT v.MenschID, s.MenschID
FROM Nachkommen v, Stammbaum s
WHERE v.Nachkomme = s.Mutter
UNION
SELECT v.MenschID, s.MenschID
FROM Nachkommen v, Stammbaum s
WHERE v.Nachkomme = s.Vater
)
SELECT *
FROM Nachkommen
WHERE MenschID IN (SELECT MenschID
FROM Stammbaum
WHERE Name = ’Bob’)
ORDER BY MenschID;
3. Setzen Sie die obige Tabelle und die rekursiven Anfragen in DB2 um.
DROP TABLE Stammbaum $
CREATE TABLE Stammbaum
(
MenschID
INTEGER NOT NULL PRIMARY KEY,
Name
VARCHAR(30) NOT NULL,
GebDatum
DATE,
Mutter
INTEGER REFERENCES Stammbaum,
Vater
INTEGER REFERENCES Stammbaum
) $
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INTO
INTO
INTO
INTO
INTO
INTO
INTO
Stammbaum
Stammbaum
Stammbaum
Stammbaum
Stammbaum
Stammbaum
Stammbaum
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
(1,
(2,
(7,
(3,
(4,
(5,
(6,
’Bob’, ’11-29-1927’, NULL, NULL) $
’Joe’, ’10-23-1952’, NULL, 1) $
’Mark’, ’08-30-1957’, NULL, NULL) $
’Joanna’, ’09-12-1954’, NULL, NULL) $
’Kim’, ’03-15-1997’, 3, 2) $
’Jim’, ’12-24-1995’, 3, 2) $
’Cloe’, ’05-07-1999’, 3, 7) $
WITH Vorfahren(MenschID, Vorfahr) AS
(
SELECT MenschID, Mutter
FROM Stammbaum
WHERE Name = ’Jim’
UNION ALL
SELECT MenschID, Vater
FROM Stammbaum
WHERE Name = ’Jim’
UNION ALL
SELECT v.MenschID, s.Mutter
FROM Vorfahren v, Stammbaum s
WHERE v.Vorfahr = s.MenschID
UNION ALL
SELECT v.MenschID, s.Vater
FROM Vorfahren v, Stammbaum s
WHERE v.Vorfahr = s.MenschID
)
SELECT *
FROM Vorfahren
WHERE Vorfahr IS NOT NULL
ORDER BY MenschID $
WITH Nachkommen(MenschID, Nachkomme) AS
(
SELECT Mutter, MenschID
FROM Stammbaum
UNION ALL
SELECT Vater, MenschID
FROM Stammbaum
UNION ALL
SELECT v.MenschID, s.MenschID
FROM Nachkommen v, Stammbaum s
WHERE v.Nachkomme = s.Mutter
UNION ALL
SELECT v.MenschID, s.MenschID
FROM Nachkommen v, Stammbaum s
WHERE v.Nachkomme = s.Vater
)
SELECT *
FROM Nachkommen
WHERE MenschID IN (SELECT MenschID
FROM Stammbaum
WHERE Name = ’Bob’)
ORDER BY MenschID $
Herunterladen