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.
Svar:
Kommentarer: Man kan också ha en entitetstyp Skjutfält, och ett många-till-många-samband mellan skjutfält och provtillfällen.
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.
Svar:
Granattyper(Nummer, Namn, Kaliber, Vikt)
Granater(Serienummer, Typ, Vikt)
Provtillfällen(Nummer, Startdatum, Slutdatum, Plats)
Avfyrningar(Nummer, Datum, Tid, Granat, Provtillfälle)
Personer(Nummer, Namn)
Deltog(Person, Provtillfälle)
Kandidatnycklarna är understrukna. I tabellen Granattyper är Nummer primärnyckel och Namn en alternativnyckel. I tabellen Avfyrningar är Nummer primärnyckel, och eftersom varje granat bara kan avyras en gång är Granat en alternativnyckel.
Främmande nycklar:
Granater.Typ till Granattyper.Nummer
Avfyrningar.Granat till Granater.Nummer
Avfyrningar.Provtillfälle till Provtillfällen.Nummer
Deltog.Person till Personer.Nummer
Deltog.Provtillfälle till Provtillfällen.Nummer
Nedan visas create table-kommandon och exempeldata, för att underlätta provkörningar.
DROP TABLE Deltog CASCADE; DROP TABLE Personer CASCADE; DROP TABLE Provtillfällen CASCADE; DROP TABLE Avfyrningar CASCADE; DROP TABLE Granater CASCADE; DROP TABLE Granattyper CASCADE; CREATE TABLE Granattyper (Nummer INTEGER NOT NULL PRIMARY KEY, Namn NVARCHAR(20) NOT NULL UNIQUE, Kaliber INTEGER NOT NULL CHECK (Kaliber > 0), Vikt INTEGER NOT NULL CHECK (Vikt > 0)); INSERT INTO Granattyper VALUES (1, 'Strids-bomb 2000', 155, 46); INSERT INTO Granattyper VALUES (2, 'Turbo-Pang XL', 155, 47); INSERT INTO Granattyper VALUES (3, 'Mini-fjutt', 1, 1); CREATE TABLE Granater (Nummer INTEGER NOT NULL PRIMARY KEY, Typ INTEGER NOT NULL REFERENCES Granattyper(Nummer), Vikt FLOAT NOT NULL CHECK (Vikt > 0)); INSERT INTO Granater VALUES (1, 1, 46); INSERT INTO Granater VALUES (2, 1, 45.978); INSERT INTO Granater VALUES (3, 1, 45); INSERT INTO Granater VALUES (4, 2, 47); INSERT INTO Granater VALUES (5, 2, 48); CREATE TABLE Provtillfällen (Nummer INTEGER NOT NULL PRIMARY KEY, Startdatum DATE NOT NULL, Slutdatum DATE NOT NULL, Plats NVARCHAR(25) NOT NULL); INSERT INTO Provtillfällen VALUES (1, DATE '2025-01-10', DATE '2025-01-15', 'Villingsbergs skjutfält'); INSERT INTO Provtillfällen VALUES (2, DATE '2025-01-10', DATE '2025-01-15', 'Villingsbergs skjutfält'); INSERT INTO Provtillfällen VALUES (3, DATE '2025-01-10', DATE '2025-01-15', 'Hemma i trädgården'); CREATE TABLE Avfyrningar (Nummer INTEGER NOT NULL PRIMARY KEY, Datum DATE NOT NULL, Tid TIME NOT NULL, Granat INTEGER NOT NULL UNIQUE REFERENCES Granater(Nummer), Provtillfälle INTEGER NOT NULL REFERENCES Provtillfällen(Nummer)); INSERT INTO Avfyrningar VALUES (1, DATE '2025-01-11', TIME '07:01:00', 1, 1); INSERT INTO Avfyrningar VALUES (2, DATE '2025-01-12', TIME '07:02:00', 2, 1); INSERT INTO Avfyrningar VALUES (3, DATE '2025-01-13', TIME '07:03:00', 4, 2); CREATE TABLE Personer (Nummer INTEGER NOT NULL PRIMARY KEY, Namn NVARCHAR(20) NOT NULL); INSERT INTO Personer VALUES (1, 'Kajsa Kanon'); INSERT INTO Personer VALUES (2, 'Hans Haubits'); INSERT INTO Personer VALUES (3, 'Mats Mörsare'); CREATE TABLE Deltog (Person INTEGER NOT NULL REFERENCES Personer(Nummer), Provtillfälle INTEGER NOT NULL REFERENCES Provtillfällen(Nummer), PRIMARY KEY (Person, Provtillfälle)); INSERT INTO Deltog VALUES (1, 3); INSERT INTO Deltog VALUES (2, 2); INSERT INTO Deltog VALUES (3, 1); INSERT INTO Deltog VALUES (3, 2); INSERT INTO Deltog VALUES (3, 3); SELECT * FROM Granattyper; SELECT * FROM Granater; SELECT * FROM Provtillfällen; SELECT * FROM Avfyrningar; SELECT * FROM Personer; SELECT * FROM Deltog;
Svar:
Det är tabellerna. Det är inte kopplingarna mellan tabellerna i form av referensattribut eller främmande nycklar, och det är inte heller sambandstyperna i ett ER-diagram.
a) (2p) Vilka datum har vi avfyrat granater av typen Strids-bomb 2000?
Svar:
SELECT Datum FROM Avfyrningar, Granater, Granattyper WHERE Avfyrningar.Granat = Granater.Nummer AND Granater.Typ = Granattyper.Nummer AND Granattyper.Namn = 'Strids-bomb 2000';
En alternativ lösning med nästlade frågor:
SELECT Datum FROM Avfyrningar WHERE Granat IN (SELECT Nummer FROM Granater WHERE Typ IN (SELECT Nummer FROM Granattyper WHERE Namn = 'Strids-bomb 2000'));
En lösning med explicit join:
SELECT Datum FROM Avfyrningar JOIN Granater ON Avfyrningar.Granat = Granater.Nummer JOIN Granattyper ON Granater.Typ = Granattyper.Nummer WHERE Granattyper.Namn = 'Strids-bomb 2000';
b) (2p) Det finns bara en person i databasen som heter Kajsa Kanon. Vad heter de skjutfält som hon varit på?
Svar:
SELECT Provtillfällen.Plats FROM Personer, Deltog, Provtillfällen WHERE Personer.Namn = 'Kajsa Kanon' AND Personer.Nummer = Deltog.Person AND Deltog.Provtillfälle = Provtillfällen.Nummer;
c) (2p) Vad heter de granattyper som är tyngre än Strids-bomb 2000?
Svar:
SELECT Tyngre.Namn FROM Granattyper AS SB2000, Granattyper AS Tyngre WHERE Tyngre.Vikt > SB2000.Vikt AND SB2000.Namn = 'Strids-bomb 2000';
Det kan vara enklare att använda nästlade frågor:
SELECT Namn FROM Granattyper WHERE Vikt > (SELECT Vikt FROM Granattyper WHERE Namn = 'Strids-bomb 2000');
d) (2p) Jag är ute och går på Villingsbergs skjutfält, och på marken hittar jag en granat som kommer från en provskjutning. Vilken typ av granat kan det vara?
Svar:
SELECT DISTINCT Granattyper.Namn FROM Provtillfällen, Avfyrningar, Granater, Granattyper WHERE Provtillfällen.Plats = 'Villingsbergs skjutfält' AND Provtillfällen.Nummer = Avfyrningar.Provtillfälle AND Avfyrningar.Granat = Granater.Nummer AND Granater.Typ = Granattyper.Nummer;
e) (3p) Vad heter den granattyp som vi avfyrat flest gånger?
Svar:
WITH AvfyrningarPerTyp AS (SELECT Granattyper.Namn AS Namn, COUNT(*) AS Antal FROM Avfyrningar, Granater, Granattyper WHERE Avfyrningar.Granat = Granater.Nummer AND Granater.Typ = Granattyper.Nummer GROUP BY Granattyper.Namn) SELECT Namn FROM AvfyrningarPerTyp WHERE Antal = (SELECT MAX(Antal) FROM AvfyrningarPerTyp);
f) (2p) Finns det några granattyper som vi aldrig avfyrat? Vi vill veta namnen på dem.
Svar:
SELECT Namn FROM Granattyper WHERE Nummer NOT IN (SELECT Typ FROM Granater WHERE Nummer IN (SELECT Granat FROM Avfyrningar));
a) Vilka index vi bör skapa för att sökningen i 4a ska gå snabbare?
Svar:
Avfyrningar.Granat
Granater.Nummer
Granater.Typ
b) Vilka index vi bör skapa för att sökningen i 4b ska gå snabbare?
Svar:
Deltog.Person
Deltog.Provtillfälle
Provtillfällen.Nummer
Svar:
En normalform är en regel för hur en tabell får utformas. Normalformen förbjuder vissa typer av dålig design som skulle kunna leda till problem när man ska lagra information och söka i databasen.
b) Ge ett exempel på en normalform som vi behandlat i kursen, och förklara vad den innebär.
Svar:
Vi tar första normalformen ("1NF")som exempel.
Första normalformen säger att alla värden som vi lagrar i tabellen måste vara enkla och atomära. Det betyder att en enskild ruta i tabellen bara får innehålla (högst) ett värde, inga listor eller sammansatta värden.
c) Vilket eller vilka problem är det som just denna normalform försöker förhindra? Visa med exempel!
Svar:
Annars skulle det bli besvärligt att arbeta med tabellen. Här är en tabell Personer, där varje person har nummer, namn och flera telefonnummer:
Personer | ||
---|---|---|
Nummer | Namn | Telefon |
1 | Anna | 1490, 2230, 1650 |
2 | Bodil | 1777 |
3 | Charlie | 2822, 1490 |
SQL är gjort för att jämföra värdet i en ruta med värdet i en annan, så med den här lösningen kan man inte söka fram om flera personer har samma telefonnummer utan att använda komplicerad programmering med strängfunktioner.
Antag att man i stället följer första normalformen och delar upp tabellen i två:
|
|
Nu är det lättare att söka fram att telefonnumret 1490 står på två ställen.
Svar:
En trigger är en "aktiv regel", dvs en regel med någon typ av åtgärd som utförs när en händelse sker i databasen, till exempel att en ny rad läggs till i en tabell. Till skillnad från if-satser i ett vanligt program, som man uttryckligen måste köra varje gång man vill utföra åtgärden, kommer triggern att utlösas automatiskt när händelsen sker i databasen.
b) Beskriv två olika användningsområden för triggers i databaser.
Svar:
a) Vad är det för saker man isolerar från varandra?
Svar:
Transaktioner. En transaktion är en följd av operationer i databasen (ändringar eller sökningar) som hör ihop som en enhet.
b) Vad innebär det att man isolerar dessa saker?
Svar:
Varje transaktion ska "uppleva" det som att den är ensam i databasen, och att inga andra transaktioner körs samtidigt. Under transaktionens gång får det inte ske några ändringar i databasen, som transaktionen kan se och som den inte gjort själv. (SQL-standarden anger flera olika isoleringsnivåer, så det går att tillåta en viss åtkomst mellan transaktioner.)
c) Databashanteraren Mimer använder det som brukar kallas för optimistiska metoder för att åstadkomma isolering. Det är lite ovanligt, och de flesta andra databashanterare använder vad man kan kalla pessimistiska metoder. Vad innebär dessa två sätt, och vilka är de viktigaste skillnaderna?
Svar:
Pessimistiska metoder betyder att man låser data i databasen, så att bara en transaktion åt gången kan komma åt dem. Då kan det inte uppstå några "krockar" mellan transaktionerna, så att två eller flera transaktioner gör motstridiga operationer i databasen.
Optimistiska metoder använder inte lås, utan i stället genomför varje transaktionen alla sina operationer, och sedan kontrollerar databashanteraren efteråt (vid commit) om det gick bra eller inte.