ER- och EER-diagram kan ritas på flera olika sätt. Om du använder en annan notation än kursboken, måste du förklara den notation som du använder.
En kommentar: Det går att tolka scenariot som i ER-diagrammet ovan, att penntyper från olika tillverkare visserligen kan ha samma namn, men det är olika typer. Man kan också tolka det som att flera olika tillverkare kan tillverka samma typ av penna. Penntypernas namn blir då unika, och vi får ett många-till-många-samband mellan tillverkare och penntyper.
Du behöver inte skriva create table-kommandon i SQL, men du ska ange vilka relationer som finns och vilka attribut varje relation innehåller. Ange också alla kandidatnycklar, vilken av dessa som är primärnyckel, samt vilka referensattribut som finns och vad de refererar till.
Implementationen ska vara bra.
Tillverkare(Nummer, Namn)
Penntyper(Nummer, Namn, Tillverkare)
Färger(Nummer, Namn)
Pennor(Nummer, Typ, Färg, Status)
Primärnycklarna är understrukna. I tabellen Tillverkare är även Namn en kandidatnyckel. I tabellen Färger är även Namn en kandidatnyckel. I tabellen Penntyper är även kombinationen av Namn och Tillverkare en sammansatt kandidatnyckel.
Främmande nycklar:
Penntyper.Tillverkare till Tillverkare.Nummer
Pennor.Typ till Penntyper.Nummer
Pennor.Färg till Färger.Nummer
Nedan visas create table-kommandon och exempeldata, för att underlätta provkörningar.
DROP TABLE Pennor; DROP TABLE Färger; DROP TABLE Penntyper; DROP TABLE Tillverkare; CREATE TABLE Tillverkare (Nummer INTEGER NOT NULL PRIMARY KEY, Namn NVARCHAR(13) NOT NULL UNIQUE); CREATE TABLE Penntyper (Nummer INTEGER NOT NULL PRIMARY KEY, Namn NVARCHAR(26) NOT NULL, Tillverkare INTEGER NOT NULL REFERENCES Tillverkare(Nummer), UNIQUE (Namn, Tillverkare)); CREATE TABLE Färger (Nummer INTEGER NOT NULL PRIMARY KEY, Namn NVARCHAR(7) NOT NULL UNIQUE); CREATE TABLE Pennor (Nummer INTEGER NOT NULL PRIMARY KEY, Penntyp INTEGER NOT NULL REFERENCES Penntyper(Nummer), Färg INTEGER NOT NULL REFERENCES Färger(Nummer), Status NVARCHAR(10)); INSERT INTO Tillverkare (Nummer, Namn) VALUES (1, 'Faber-Castell'); INSERT INTO Tillverkare (Nummer, Namn) VALUES (2, 'Ballograf'); INSERT INTO Tillverkare (Nummer, Namn) VALUES (3, 'Shachihata'); INSERT INTO Penntyper (Nummer, Namn, Tillverkare) VALUES (10, 'Winner 152', 1); INSERT INTO Penntyper (Nummer, Namn, Tillverkare) VALUES (11, 'Friendly Whiteboard Marker', 2); INSERT INTO Penntyper (Nummer, Namn, Tillverkare) VALUES (12, 'Artline 519', 3); INSERT INTO Penntyper (Nummer, Namn, Tillverkare) VALUES (13, 'Ultrabultra', 1); INSERT INTO Penntyper (Nummer, Namn, Tillverkare) VALUES (14, 'Trultrabultra', 2); INSERT INTO Färger VALUES (1, 'svart'); INSERT INTO Färger VALUES (2, 'röd'); INSERT INTO Färger VALUES (3, 'blå'); INSERT INTO Färger VALUES (4, 'grön'); INSERT INTO Färger VALUES (5, 'vit'); INSERT INTO Färger VALUES (6, 'osynlig'); INSERT INTO Pennor (Nummer, Penntyp, Färg, Status) VALUES (1, 11, 2, 'helt slut'); INSERT INTO Pennor (Nummer, Penntyp, Färg, Status) VALUES (2, 10, 1, 'helt slut'); INSERT INTO Pennor (Nummer, Penntyp, Färg, Status) VALUES (3, 11, 1, 'ganska bra'); INSERT INTO Pennor (Nummer, Penntyp, Färg, Status) VALUES (5, 11, 2, 'helt slut'); INSERT INTO Pennor (Nummer, Penntyp, Färg, Status) VALUES (6, 10, 3, 'helt slut'); INSERT INTO Pennor (Nummer, Penntyp, Färg, Status) VALUES (7, 12, 3, 'ny'); INSERT INTO Pennor (Nummer, Penntyp, Färg, Status) VALUES (11, 12, 4, 'helt slut'); SELECT * FROM Pennor; SELECT * FROM Färger; SELECT * FROM Penntyper; SELECT * FROM Tillverkare;
a) (1p) Hur många olika tillverkare finns det?
SELECT COUNT(*) FROM Tillverkare;
b) (2p) Vilken eller vilka tillverkare tillverkar en penntyp med ett namn som innehåller ultra, till exempel Ultramarker 2000 eller Turbo-ultratronic B-36?
-- Alternativ 1, med implicit join: SELECT Tillverkare.Namn FROM Penntyper, Tillverkare WHERE Penntyper.Tillverkare = Tillverkare.Nummer AND Penntyper.Namn LIKE '%ultra%'; -- Alternativ 2, med explicit join: SELECT Tillverkare.Namn FROM Penntyper JOIN Tillverkare ON Penntyper.Tillverkare = Tillverkare.Nummer WHERE Penntyper.Namn LIKE '%ultra%'; -- Alternativ 3, med en underfråga: SELECT Namn FROM Tillverkare WHERE Nummer IN (SELECT Tillverkare FROM Penntyper WHERE Namn LIKE '%ultra%');
En kommentar: En del databashanterare skiljer som default på stora och små bokstäver, och andra gör det inte. Mimer råkar vara en som skiljer, och för att jämförelsen med '%ultra%' ska matcha även till exempel Turbo-ultratronic B-36, behöver man lägga till COLLATE SWEDISH till frågan. Dessa detaljer ligger dock utanför den här kursen.
c) (2p) Hur många typer av pennor tillverkas av Faber-Castell?
SELECT COUNT(*) FROM Penntyper, Tillverkare WHERE Penntyper.Tillverkare = Tillverkare.Nummer AND Tillverkare.Namn = 'Faber-Castell';
d) (2p) Hur många av våra enskilda pennor har tillverkats av Faber-Castell?
SELECT COUNT(*) FROM Pennor, Penntyper, Tillverkare WHERE Pennor.Penntyp = Penntyper.Nummer AND Penntyper.Tillverkare = Tillverkare.Nummer AND Tillverkare.Namn = 'Faber-Castell';
e) (3p) Vilken färg finns det flest enskilda pennor av?
-- Alternativ 1, med en CTE (funkar av någon anledning inte i Mimer): WITH AntalPennorPerFärg AS (SELECT Färger.Namn AS Färg, COUNT(*) AS Antal FROM Pennor, Färger WHERE Pennor.Färg = Färger.Nummer GROUP BY Färger.Namn) SELECT Färg FROM AntalPennorPerFärg WHERE Antal IN (SELECT MAX(Antal) FROM AntalPennorPerFärg); -- Alternativ 2, med en vy (funkar i Mimer): CREATE VIEW AntalPennorPerFärg AS SELECT Färger.Namn AS Färg, COUNT(*) AS Antal FROM Pennor, Färger WHERE Pennor.Färg = Färger.Nummer GROUP BY Färger.Namn; SELECT Färg FROM AntalPennorPerFärg WHERE Antal IN (SELECT MAX(Antal) FROM AntalPennorPerFärg);
a) (1p) Hur skulle man kunna få sökningen i delfråga 3a att gå snabbare att köra?
Många databashanterare håller reda på statistik om vilka data som finns i tabellerna, bland annat antalet rader, och då går denna fråga mycket snabbt att köra. Eftersom frågan dock "tar lång tid att köra", enligt förutsättningarna, fungerar tydligen den här databashanteraren inte så.
Det finns några olika saker man kan prova:
b) (3p) Hur skulle man kunna få sökningen i delfråga 3b att gå snabbare att köra?
Här är det lämpligt att skapa index på de kolumner som används i villkoret:
Det hjälper förmodligen inte att skapa ett index av traditionell typ på Penntyper.Namn, eftersom vi inte söker på början av texten. (Jämför med ett uppslagsverk i bokform, och att slå upp inte bara ordet "ultra" som förstås står under bokstaven U, utan ord som innehåller "ultra".) Om databashanteraren har möjlighet att skapa någon sorts fritextindex kan det fungera.
Man ska inte skapa ett index på Tillverkare.Namn, eftersom den kolumnen visserligen finns med i resultatet, men den används inte för att söka fram rader.
Pennor | |||||
---|---|---|---|---|---|
Penn-nummer | Färg | Penntyp | Tillverkare | Status | |
1 | röd | Friendly Whiteboard Marker | Ballograf | helt slut | |
2 | svart | Winner 152 | Faber-Castell | helt slut | |
3 | svart | Friendly Whiteboard Marker | Ballograf | ganska bra | |
5 | röd | Friendly Whiteboard Marker | Ballograf | helt slut | |
6 | blå | Winner 152 | Faber-Castell | helt slut | |
7 | blå | Artline 519 | Shachihata | ny | |
11 | grön | Artline 519 | Shachihata | helt slut |
a) (1p) Vilka kandidatnycklar finns i tabellen?
Svar: Penn-nummer
b) (1p) Vilka fullständiga funktionella beroenden finns i tabellen?
Svar: Från Penn-nummer till vart och ett av de fyra andra attributen
c) (1p) Vilka av de fyra normalformerna 1NF, 2NF, 3NF och BCNF uppfyller tabellen?
Svar: Alla.
d) (2p) Är det här ett bra sätt att lösa uppgift 2? Motivera svaret!
Svar: Inte särskilt bra. Tabellen uppfyller visserligen normalformerna, men det finns ändå flera problem. Vi kan till exempel inte lagra en penntyp om vi inte har pennor av den typen, och vi kan inte lagra en tillverkare om denna inte tillverkar pennor, eller om vi inte har några pennor som den tillverkaren tillverkat.
Ett annat men antagligen inte lika allvarligt problem är att namnen, som är textsträngar, upprepas många gånger. Informationen, till exempel att penna nummer 5 är en Friendly Whiteboard Marker som tillverkats av Ballograf, upprepas inte, men man kunde sparat en del plats i databasen (och förmodligen gjort den snabbare) om man i stället gjort som i lösningsförslaget till uppgift 2 och lagrat att penna nummer 5 är av typ nummer 11 som tillverkats av tillverkare nummer 2.
e) (2p) Användarna trivs med en databas som ser ut som den här enda tabellen. Skapa en vy som motsvarar denna tabell, baserad på dina egna tabeller i din egen lösning på uppgift 2.
-- Förslag 1 CREATE VIEW Pennvy AS SELECT P.Nummer AS Pennummer, F.Namn AS Färg, Typ.Namn AS Penntyp, Tv.Namn AS Tillverkare, P.Status AS Status FROM Pennor AS P JOIN Penntyper AS Typ ON P.Penntyp = Typ.Nummer JOIN Tillverkare AS Tv ON Typ.Tillverkare = Tv.Nummer JOIN Färger AS F ON P.Färg = F.Nummer; -- Förslag 2 CREATE VIEW Pennvy AS SELECT P.Nummer AS Pennummer, F.Namn AS Färg, Typ.Namn AS Penntyp, Tv.Namn AS Tillverkare, P.Status AS Status FROM Pennor AS P, Penntyper AS Typ, Tillverkare AS Tv, Färger AS F WHERE P.Penntyp = Typ.Nummer AND Typ.Tillverkare = Tv.Nummer AND P.Färg = F.Nummer AND P.Penntyp = Typ.Nummer;
a) SQL-kommandona update och alter table
Svar: Update ändrar på tabellens data, dvs innehållet på raderna, medan alter table ändrar på schemat, dvs kolumnerna, deras domäner, integritetsvillkor och så vidare.
b) SQL-kommandona drop och delete
Svar: Även här handlar det om att ändra data respektive schema. Drop tar bort en hel tabell, vy eller annat objekt i schemat, medan delete tar bort en eller flera rader ur en tabell.
c) SQL-kommandona revoke och rollback
Svar: Revoke tar bort åtkomsträttigheter som man delat ut tillen användare, medan rollback avbryter en transaktion och ändrar tillbaka alla ändringar som den transaktionen gjort.
d) group by och order by i SQL
Svar: Order by sorterar raderna i resultatet, medan group by används tillsammans med aggregatfunktioner för att dela upp raderna som ska aggregeras i olika grupper, så varje grupp får sitt aggregeringsvärde.
e) en vy och en tabell
Svar: En tabell är en samling data som lagras i databasen, medan en vy är en sökning, där man lagrat sökkommandot i databasen, och sökningen körs på nytt när man behöver datat i vyn. (En del databashanterare har också så kallade materialiserade vyer, där vyresultatet förberäknas och lagras i databasen. Man kan också göra egna materialiserade vyer med en separat tabell och triggers.)
f) en databashanterare och en databasadministratör
Svar: En databashanterare är ett program, eller en samling program, som används för att arbeta med och söka i databasen, medan en databasadministratör är en person, eller en hel grupp personer, som arbetar med databasens dagliga drift och administration.
g) atomicitet och isolering (i samband med transaktioner)
Svar: Atomicitet innebär att transaktionen ska genomföras som en helhet, så att antingen genomförs alla dess ändringar eller inga av dem, medan isolering innebär att olika transaktioner som körs samtidigt inte ska påverka varandra, till exempel genom att skriva över varandras resultat på ett sätt som leder till en inkonsistent databas.