Det här är ett avsnitt i en
webbkurs om databaser
som finns fritt tillgänglig på adressen
http://www.databasteknik.se/webbkursen/.
Senaste ändring:
18 juli 2005.
Av Thomas Padron-McCarthy. Copyright, alla rättigheter reserverade, osv. Skicka gärna kommentarer till webbkursen@databasteknik.se.
|
Det konceptuella schemat behöver egentligen inte ha någonting med datorer att göra, utan är bara en beskrivning av verkligheten som lika gärna skulle kunna användas t ex av någon som vill analysera hur företaget fungerar. Om man vill skapa en databas måste det konceptuella schemat översättas till ett schema som går att mata in i en databashanterare. Om man använder en relationsdatabashanterare så består det schemat av en eller flera tabeller.
Faktaruta:
Tänk på att ett schema beskriver vilka data
man kan lagra i en viss databas, medan en datamodell
beskriver hur scheman kan se ut.
Som exempel kan vi ta en relationsdatabas,
dvs en databas där data lagras i tabeller.
Databasens schema utgörs av vilka tabeller
som finns i databasen, och vilka kolumner de har,
medan datamodellen är själva det faktum att
databasen byggs upp av tabeller.
De data som man sen verkligen lagrar i tabellerna kallas, förstås, data. Tänk också på att det finns en del språkförbistring: Ibland används ordet "datamodell" för att beteckna det som vi här kallar för "schema". |
Den konceptuella beskrivningen görs med hjälp av en konceptuell datamodell, och resulterar i ett schema i den modellen.
Gör så här:
Rita upp de typer av saker som finns i databasen. De kallas entitetstyper, och ritas som fyrkantiga lådor:
Rita sen upp de samband som finns mellan de olika typerna av saker. De kallas sambandstyper, och ritas som diamanter mellan de fyrkantiga lådorna:
Det här ER-diagrammet betyder alltså att det finns personer, det finns hus, och personerna bor i husen. (ER-diagrammet säger dock inget om hur många personer och hus det är, eller vilka, och vilka personer som bor i vilka hus. Allt det där är data, och ER-diagrammet är ett schema.)
"Sambandstyp" heter "relationship type" på engelska, och "samband" heter "relationship", men undvik att kalla dem för "relation" eller "relationstyp" på svenska. I databassammanhang är en relation en tabell i relationsmodellen.
"N" betyder att det kan bo flera personer i varje hus, och "1" betyder att varje person bara kan bo i ett hus. Det kallas ett många-till-ett-samband.
"Många" betyder i det här sammanhanget noll, ett eller flera. Det kan finnas hus som det inte bor någon i, det kan finnas hus som det bara bor en person i, och det kan finnas hus som det bor en miljon personer i.
Sambandstyper kan vara av tre olika slag, så kallade kardinalitetsförhållanden:
Faktaruta: ER-diagram kan ritas på flera olika sätt. Det som brukar skilja mest är just hur man ritar sambandstyper, och hur man då anger kardinalitetsförhållandena (till exempel ett-till-många). |
En helt annan faktaruta: På svenska får sammansatta ord inte skrivas isär. Alltså heter det exempelvis "ett-till-många-samband", och inte "ett-till-många samband" eller "ett till många samband". Det heter "ER-diagram" och inte "ER diagram". Det heter "databas" och inte "data bas". Alla sammansatta ord skrivs ihop. Det är lätt. Gör inte fel. Läs mer på http://www.skrivihop.nu/. |
Hus kan ägas gemensamt av flera personer, och varje person kan vara med och äga flera hus.
Det kallas fullständigt deltagande: alla personer som finns med i databasen måste delta i ett boendesamband. En sambandstyp kan ha fullständigt deltagande på ena sidan, på båda sidorna, eller inte på någon sida.
Ett annat exempel. Genom att ändra lite i figuren, säger vi i stället att en person kan bo i flera olika hus, men alla personer behöver inte bo någonstans, och i varje hus bor det bara en person. Det finns inga hus som det inte bor någon person i.
Att Personnummer är understruket betyder att personnummer är unika, dvs två personer kan inte ha samma personnummer. Personnumret kan alltså användas som nyckel. Samma sak med Husnummer.
Även sambandstyper kan ha egenskaper:
Inflyttningsår anger vilket år en person flyttade in i det hus hon bor i. I det här fallet skulle man också kunna sätta attributet Inflyttningsår på personen, eftersom varje person bor i exakt ett hus, och alltså har exakt ett inflyttningsår, men det är nog naturligare att låta inflyttningsåret höra till Bor i-sambandet.
Det finns också fall när det är nödvändigt att ha attributet på sambandstypen:
Det här ER-diagrammet säger alltså inte att det finns en person som är vän med sig själv, utan det säger att personer kan vara vänner med andra personer:
Om "person" alltså är en entitetstyp, så brukar man kalla de enskilda personerna för entitetsinstanser. (Ja, egentligen är det ju inte personerna, utan deras representation i databasen.) Man kan också kalla personerna för entiteter, men det kan vara förvirrande eftersom den benämningen ibland används även för entitetstyperna. På samma sätt talar man om sambandsinstanser.
Så här skulle det kunna se ut om man ritade upp instanserna i en databas med ER-schemat ovan:
Det man ritar ut i ett ER-diagram är alltså inte tabeller och kopplingarna mellan dem, även om en del (men inte alla) av entitetstyperna sen kan översättas till tabeller, och en del (men inte alla) av sambandstyperna kan översättas till kopplingar mellan tabeller.
Det här är förstås galet, eftersom det här ER-diagrammet säger att det finns en entitetstyp som heter "skola", och alltså kommer databasen att innehålla ett antal skolor (entitetsinstanser av entitetstypen "skola"). "Skola" hade passat som rubrik till hela ER-diagrammet, men inte som en entitetstyp.
|
Telefonnummer kan ju behandlas som en enhet (070-7347013), men om man ofta vill dela upp personerna i databasen efter riktnummer är det kanske bättre att dela upp numren i två delar (070 och 7347013),
Att telefonnummer är ett flervärt attribut innebär att en person kan ha hur många telefonnummer som helst: noll, ett, två eller kanske en miljard.
I det här fallet ska man alltså inte lagra antal boende för varje hus, utan man räknar ut det på nytt varje gång man behöver värdet, helt enkelt genom att räkna hur många instanser det finns av "bor i"-sambandet som hör ihop med just det huset.
Bostadsföretagets olika rum har alltså ingen egen nyckel. En nyckel i databassammanhang är något som man kan använda för att identifiera en viss sak, till exempel personnummer för personer. Personnumret 631211-1658 identifierar en viss person, men rumsnamnet köket räcker inte för att veta vilket kök man menar.
Om man ändå vill lagra rum i databasen, så kan man förstås hitta på en särskild nyckel för varje rum. Köket i min lägenhet kan till exempel heta kök 17, och köket i din lägenhet kan heta kök 42. Badrummet i min lägenhet kanske heter badrum 203, och ditt badrum heter badrum 65. Eller så ger man bara alla rum varsitt nummer: mitt kök är rum nummer 828, och mitt badrum är rum nummer 703.
Det kan vara lite opraktiskt, och det vore nog naturligare att fortfarande säga köket och badrummet, men dessutom tala om vilken lägenhet som det hör till. Då kan man använda en svag entitetstyp:
Det här ER-diagrammet säger att det finns lägenheter, som var och en har ett eget nummer. Lägenheterna innehåller rum, men rummen har bara namn, som inte är unika för hela databasen. Däremot är de unika inom en viss lägenhet: om man vet ett rumsnamn, och numret på den lägenhet som rummet hör till, så räcker det för att unikt identifiera rummet i hela databasen.
Vi har ritat Rum med en dubbel fyrkant, för att ange att det är en svag entitetstyp. Rumsnamnet Namn kallas partiell nyckel, och ritas understruket med ett (hmmm...) streckat streck. Sambandstypen Innehåller, som används för att identifiera vilken lägenhet ett rum tillhör, kallas identifierande sambandstyp, och ritas som en dubbel diamantbox. Entitetstypen Lägenhet kallas identifierande entitetstyp. Naturligtvis kan vi inte ha några lösa rum, som inte tillhör någon lägenhet, så vi ritar ut ett fullständigt deltagande med hjälp av ett dubbelstreck mellan Rum och Innehåller. Sambandstypen blir 1:N, eftersom varje rum hör till en lägenhet, och en lägenhet kan innehålla flera rum.
Ibland säger man att den identifierande entitetstypen äger den svaga: en lägenhet "äger" de rum som den innehåller. Om man tar bort en viss lägenhet i databasen, vill man också ta bort rummen som den innehåller.
Till exempel kan vi göra om Bor i-sambandet till en egen entitetstyp, som vi kallar Boende:
Nu ser vi inte längre ett boende som en sambandstyp som knyter ihop en person och ett hus, utan nu är ett boende en egen sak. Varje boende-entitet hör ihop med en person (den som bor) och med ett hus (huset hon bor i).
Det finns två anledningar till att man ibland vill objektifiera en sambandstyp:
Antag att vi ska rita ett ER-diagram som modellerar att personer har sett filmer:
N:M-sambandet betyder att en person kan ha sett flera filmer, och att en film kan ha setts av flera personer. Men vi kan inte ange att en person sett samma film flera gånger.
(Jo, vi skulle kunna lägga på ett attribut Antal på sambandstypen, eller ett flervärt attribut Datum som anger alla datum som personen sett filmen. Men som det ser ut nu så har personen antingen sett filmen, eller också har hon inte sett den.)
Om vi i stället betraktar en filmtittning som en egen sak, och inte bara en typ av samband mellan personer och filmer, så kan vi ha flera olika tittningar där en viss person sett en viss film:
Nu har jag inte ritat ut några attribut, men vi måste hitta på en nyckel till den nya entitetstypen, ett "tittningsnummer" som inte behövdes för sambandet.
Om man har ett flervägssamband, dvs ett samband som binder ihop fler än två entitetstyper, är det ofta bättre att objektifiera det (se nedan).
Kanske vill vi än en gång hålla reda på vilka personer som har sett vilka filmer, men vi vill dessutom veta vilka biografer de sett filmerna på. Jag har kanske sett Spindelmannen på Rigoletto och på Filmstaden, så jag kan uttala mig om hur upplevelsen är av att se just den filmen där. Däremot kan jag inte säga något om hur bra Spindelmannen passar ihop med ljudsystemet på Röda kvarn, för jag har inte sett den filmen på den biografen.
Det här ER-diagrammet visar att personer har sett filmer på biografer. Ett Sett-samband ("en instans av sambandstypen Sett") binder alltså ihop en person, en film och en biograf.
Ett trevägssamband går normalt inte att byta ut mot tre tvåvägssamband. Jämför med det här ER-diagrammet:
I en databas med det här schemat kan vi lagra att jag har sett sett Spindelmannen, att jag har besökt Rigoletto, och att Spindelmannen visats på Rigoletto, men inte att jag såg Spindelmannen just på Rigoletto. Jag kanske såg någon annan film när jag var på den biografen.
Det kan vara lite lurigt att rita ut kardinalitetsförhållandena i ett flervägssamband. Det är lättare om man låter Sett vara en entitetstyp i stället för en sambandstyp, dvs att man objektifierar Sett-sambandet:
Här ser vi alltså inte filmseende som en sambandstyp som knyter ihop en person, en film och en biograf, utan nu är filmseendet en egen sak. Varje filmtittningsentitet hör ihop med en person (vem), en film (vad) och en biograf (var).
ER-diagrammet med den nya entitetstypen Tittning säger inte rktigt samma sak som trevägssambandet, för nu kan vi lagra samma kombination av person, film och biograf flera gånger. Dessutom ska vi hitta på en nyckel till den nya entitetstypen. I stället kan man skapa en svag entitetstyp med tre identifierande samband. Då säger man samma sak som med trevägssambandet:
EER-modellen har en notation med flera olika typer av arv, men vi börjar med en enda: enkelt klass/subklass-samband:
Det här säger att databasen innehåller personer. En del av de personerna är (förutom att de är personer) studenter, en del är lärare, och en del är astronauter.
En student har alla egenskaper som en person har, till exempel att hon har ett personnummer och bor i ett hus. för en student är ju en person. Man säger att entitetstypen Student ärver entitetstypen Person. Sen kan studenter ha ytterligare egenskaper, förutom personegenskaperna, till exempel att de kan läsa kurser. Precis som i objektorienterade sammanhang kallar vi Student för en subklass eller härledd klass, och Person för en superklass eller basklass. Strecket med "gaffelsymbolen" anger att Student är en subklass till Person, och att Student alltså ärver alla egenskaper som Person har. Man kan också se det som en delmängdssymbol: mängden studenter är en delmängd av mängden personer.
Låt oss gå tillbaka till vårt tidigare exempel med personer som bor i hus:
Vi antar nu att en del av personerna är studenter. En student har, precis som alla andra personer, ett namn och ett personnummer, och hon bor i ett hus. Men en student har dessutom ett medelbetyg, och hon läser kurser:
Om vi vill ange samma sak utan att ange arv, skulle vi bli tvungna att rita något i den här stilen:
Notera att entitetstypen Student, har samma attribut och deltar i samma sambandstyper som Person, plus egna attribut och sambandstyper, De gemensamma attributen och sambandstyperna skulle vi bli tvungna att rita två gånger. Dessutom har vi tappat bort informationen om att alla studenter är personer.
EER-modellen tar upp ytterligare saker som vi inte går igenom här, till exempel hur man anger att alla instanser av en klass också måste tillhöra någon av dess subklasser ("total specialisering"), och hur man anger om en instans av en klass kan vara med i flera subklasser på en gång. Men det viktigaste är det enkla klass/subklass-samband, med arv, som vi sett ovan.
ER-diagram är därför lättare att jobba med, i synnerhet för den som är ovan vid tabeller. Det brukar leda till en bättre design i slutänden om man börjar med att rita ER-diagram, och sedan översätter till tabeller, i stället för att försöka konstruera tabeller direkt.
Att pussla ihop tabeller redan från början ger oftare problem med normaliseringen av databasen.
Orsakerna till det är dels tradition, och dels att man har lång erfarenhet av hur man bygger relationsdatabashanterare så att de blir snabba, kraftfulla och lättanvända.
Det finns också en del val som man kan göra när man översätter från ER-diagrammet till hur saker ska lagras internt i databashanteraren, som det kanske är bättre att låta en människa göra, än att databashanteraren väljer en standardlösning. En standardlösning skulle kunna leda till att en del databaser blir onödigt stora, eller att en del sökningar går onödigt långsamt.
Ytterligare ett skäl är att det finns bra och etablerade frågespråk (främst SQL) för relationsdatabaser, och man har ännu inte kommit lika långt med hur man gör sökningar i grafiska beskrivningar som ER-diagram.
Här är några olika sätt att rita samma 1:N-samband mellan personer och hus som vi sett ovan:
Det första alternativet är vårt vanliga skrivsätt. I det andra anger man hur många sambandsinstanser varje entitetsinstans kan delta i: en person kan delta i exakt ett Bor i-samband, och ett hus kan delta i noll till hur många som helst. (Det blir alltså lite bakvänt jämfört med det första.) Pilen i det tredje alternativet liksom pekar ut det enda hus som en person bor i. Det fjärde alternativet är vanligt i Sverige och kallas för en "infologisk modell". "Gaffeln" ska illustrera att ett hus hör ihop med flera personer.
Det sista exemplet är ritat med UML, som egentligen inte är ett sätt att rita ER-diagram, utan ett objektorienterat modelleringsspråk. UML är ganska likt ER-modellen, men i UML kan man också modellera beteende, inte bara data.
ER-modellen, ER-diagram, entitetstyp, sambandstyp, kardinalitetsförhållande, fullständigt deltagande, attribut, schema, data, svag entitetstyp, den utvidgade ER-modellen (EER)