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.

ER-modellering

Konceptuella datamodeller

Om man ska skapa en databas som beskriver en del av verkligheten, t ex ett företag, brukar man börja med att göra en beskrivning av hur den delen av verkligheten ser ut och fungerar. Denna beskrivning på hög nivå kan kallas en konceptuell eller begreppsmässig beskrivning. I stället för beskrivning säger man ofta schema.

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.

Grunderna för hur man ritar ER-diagram

En vanlig konceptuell datamodell är den så kallade ER-modellen. "ER" står för "Entity-Relationship", dvs ungefär "saker" och "samband".

Gör så här:

Rita upp de typer av saker som finns i databasen. De kallas entitetstyper, och ritas som fyrkantiga lådor:

Ett ER-diagram med bara två entitetstyper

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:

Ett ER-diagram med två entitetstyper och en sambandstyp

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.

Hur många personer bor i varje hus?

Man kan också rita ut mer exakt vad det är för sorts sambandstyp:

Ett ER-diagram med ett många-till-ett-samband

"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/.

Flera sambandstyper mellan samma entitetstyper

Det går bra att ha flera olika sambandstyper som binder ihop samma entitetstyper. Till exempel kan personer kanske bo i husen precis som tidigare, men de kan också äga husen:

Ett ER-diagram med två sambandstyper

Hus kan ägas gemensamt av flera personer, och varje person kan vara med och äga flera hus.

Fullständigt deltagande

Om varje person som är med i databasen måste bo i ett hus, kan man rita ut det villkoret med ett dubbelstreck mellan Person och Bor i:

En sambandstyp med fullständigt deltagande på ena sidan

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.

Ett ER-diagram med ett ett-till-många-samband

Attribut

Om sakerna eller sambanden har egenskaper, så kallar man dem attribut, och ritar dem som ovaler:

Ett ER-diagram med utritade attribut

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:

Ett ER-diagram med ett samband som har ett attribut

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:

Skilj på schema och data

ER-diagrammet är ett schema, och beskriver vilka data som kan lagras. Det är inte en avbildning av datat.

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:

Ett ER-diagram som säger att personer är vänner med 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:

Instanser för vän-databasen som beskrivs av ER-diagrammet

Skilj på ER-diagram och tabeller

Även om man ofta översätter ER-diagram till tabeller, för att kunna lagra sin databas i en relationsdatabashanterare, så har ER-diagrammet i sig inget med tabeller att göra.

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.

Ett vanligt fel

Nybörjare på ER-diagram gör ibland följande fel. Om de får uppgiften att rita ett ER-diagram för sin skola, så börjar de med att rita en ruta:

Ett ER-diagram med entitetstypen SKOLA

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.

Ovanstående är grunderna om ER-diagram. Här nedan går vi igenom ytterligare några saker som man har nytta av när man ska rita ett ER-diagram. (Men även om du är lat, dum och ointresserad och därför slutar läsa här, så bör du läsa avsnitten på slutet av det här kapitlet, som bland annat handlar om varför man inte ska skapa tabeller direkt.)

Sammansatta attribut

Ibland kan ett attribut vara sammansatt av flera delar, som hör ihop men som man även vill behandla var för sig. Då kan man rita det som ett sammansatt attribut:

Ett ER-diagram med ett sammansatt attribut

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),

Flervärda attribut

Attributen ovan är "enkla" i betydelsen att varje enskild entitet ("entitetsinstans") har högst ett värde på attributet. Varje person har ett namn, ett personnummer och ett telefonnummer. Ibland räcker inte det. Till exempel kanske man vill kunna lagra flera telefonnummer som hör till en person. Då kan man rita det som ett flervärt attribut (även kallat multipelt attribut) genom att använda en dubbelellips runt attributnamnet:

Ett ER-diagram med ett flervärt attribut

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.

Härledda attribut

En del attribut vill man kanske inte lagra i databasen, utan man kan räkna ut dem utifrån andra data som redan finns i databasen. Sådana härledda attribut markeras med en streckad oval:

Ett ER-diagram med ett härlett attribut

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.

Svaga entitetstyper

Ibland vill man ha med saker som det är svårt att prata om som självständiga saker, utan de hör alltid ihop med en annan sak. Ta till exempel rummen i en lägenhet: köket, vardagsrummet badrummet, med flera. Om vi bara ska lagra data om en enda lägenhet i databasen så räcker det att säga "köket", för då finns det bara ett kök att välja på. Men om vi har många lägenheter, till exempel i en databas för ett bostadsföretag, så räcker det inte med "köket". Man vet inte vilket kök man menar, utan man måste alltid precisera sig med till exempel "köket i min lägenhet" eller "köket i lägenhet nummer 86".

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:

Ett ER-diagram med 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.

Objektifiering av sambandstyper

Ibland kan man välja mellan att använda sig av en sambandstyp eller en entitetstyp. Att använda en entitetstyp i stället för en sambandstyp betyder att man betraktar kopplingen som en egen sak, och inte bara som en koppling mellan två andra saker. Det kallas ibland objektifiering.

Till exempel kan vi göra om Bor i-sambandet till en egen entitetstyp, som vi kallar Boende:

Ett ER-diagram med entitetstypen 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:

En sambandstyp som Bor i-sambandet ovan är en koppling mellan en person och ett hus. Man kan bara ha en sådan koppling mellan en viss person och ett visst hus. Antingen bor man i huset, eller också inte. Det gäller alla sambandstyper. Det går inte att ha flera instanser av samma sambandstyp mellan samma entitetstyper.

Antag att vi ska rita ett ER-diagram som modellerar att personer har sett filmer:

Ett ER-diagram med sambandstypen SETT

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:

Ett ER-diagram med entitetstypen SETT

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).

Flervägssamband

Bor i-sambandet mellan personer och hus ovan kallas ett tvåvägssamband, eftersom det binder ihop två entitetstyper. Man kan också ha sambandstyper som binder ihop fler entitetstyper, till exempel tre.

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 SpindelmannenRigoletto 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.

Ett ER-diagram med ett trevägssamband

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:

Ett ER-diagram med ett tre tvåvägssamband

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:

Ett ER-diagram med ett trevägssamband objektifierat till en entitetstyp

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:

Ett ER-diagram med ett trevägssamband objektifierat till en entitetstyp

Kort om utvidgade ER-diagram (EER)

Erfarenhet från objektorienterad datamodellering visar att det ofta är praktiskt att låta en klass ärva egenskaper från en annan. Därför har man konstruerat en utvidgad ER-modell, den så kallade EER-modellen. "EER" står för "Enhanced Entity-Relationship", där "enhanced" betyder ungefär "förbättrad".

EER-modellen har en notation med flera olika typer av arv, men vi börjar med en enda: enkelt klass/subklass-samband:

Ett EER-diagram med flera subklasser

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:

Ett ER-diagram med utritade attribut

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:

Ett EER-diagram med enkelt arv

Om vi vill ange samma sak utan att ange arv, skulle vi bli tvungna att rita något i den här stilen:

Samma EER-diagram som ett ER-diagram utan arv

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.

Översättning till relationsmodellen

Om man ritat ett ER-diagram, och vill lagra sin databas i en databashanterare, måste man normalt översätta ER-diagrammet till en datamodell som databashanteraren förstår. Det kan vara till exempel en objektorienterad databashanterare, men det allra vanligaste är att man vill arbeta med en relationsdatabashanterare. ER-diagrammet ska alltså översättas till tabeller. Läs mer i avsnittet Översättning från ER-modellen till relationsmodellen.

Varför inte tabeller från början?

När man arbetar med tabeller krävs vissa speciallösningar som visserligen är enkla när man kan dem, men som ändå gör att man inte kan koncentrera sig helt på den del av världen som man vill avbilda i databasen, och hur den fungerar. I stället måste man tänka på "tabelldetaljer", som till exempel att man ibland behöver införa extra hjälptabeller.

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.

Varför inte ER-diagram hela vägen?

Det finns objektorienterade och objektrelationella databaser, som använder en datamodell ("sätt att beskriva världen") som är ganska lik ER-modellen. Det finns också åtminstone någon enstaka databashanterare där man kan mata in ER-diagram direkt. Men de allra flesta databashanterare kräver att man översätter sitt ER-diagram till något annat format. För det mesta använder man en relationsdatabashanterare, vilket betyder att data lagras i form av tabeller.

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.

Alternativa notationer

Som vi nämnde ovan kan ER-diagram ritas på flera olika sätt, och det gäller särskilt hur man anger kardinalitetstförhållanden (1:N, N:M osv).

Här är några olika sätt att rita samma 1:N-samband mellan personer och hus som vi sett ovan:

Olika sätt att rita ER-diagram

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.

De viktigaste begreppen

De viktigaste begreppen från det här avsnittet finns också med i ordlistan:

ER-modellen, ER-diagram, entitetstyp, sambandstyp, kardinalitetsförhållande, fullständigt deltagande, attribut, schema, data, svag entitetstyp, den utvidgade ER-modellen (EER)

Litteratur


Webbkursen om databaser av Thomas Padron-McCarthy.