Archives

Multipass

Noen ganger så trenger man rett og slett bare flere datamaskiner. For meg så betyr det ofte at jeg ønsker et par Linux maskiner. Jeg har i flere år brukt VMware Workstation til å lage virtuelle maskiner (fra nå av bare kalt VM) som jeg kjører på min PC med Microsoft Windows. Dette fungerer alldeles utmerket, men det blir gjerne litt arbeid å holde VMene jeg trenger oppdatert med siste versjon av Linux (i dette innlegget så betyr Linux en Ubuntu distribusjon). I praksis så har jeg lastet ned siste versjon av Ubuntu Server, opprettet en VM (i VMware Workstation), installert og konfigurert OSet (operativsystem), lastet ned patcher og så var man klar. Dette kan fort ta litt tid og egentlig ikke det man ønsker å bruke tid på. Så hva hvis man hadde sin egen lille mini-sky på PCen (eller Mac for den del) med den siste versjonen av Ubuntu, og iløpet av minuter ha en eller flere VMer oppe og kjøre? Det er her Multipass kommer inn. Multipass for Microsoft Windows (kan lastes ned her) er i skrivende stund rett under 19MB og kan vel sies å være bitte liten. Siden jeg har Windows 10 Enterprise (gjelder også Pro) som er versjon 1803 eller senere så er Hyper-V en del av OSet (for de som har andre Windows-versjoner så trenger man Virtualbox). Installasjonen er gjort på et par minutter. Nå må dere ikke tro at du får noe fancy GUI (Graphical User Interface) eller grafisk brukergrensesnitt som det heter på norsk. Nei, vi snakker her om kommandolinje eller CLI (Command Line Interface) som det også kalles. For de som er vant til Linux så er jo dette elementært. Det eneste man trenger å gjøre er å starte et Windows PowerShell. Kommandoen man bruker heter ikke akkurat overraskende «multipass». For å starte en VM med siste versjon av Ubuntu LTS (Long Term Support) så skriver man følgende:

multipass launch

Siste versjon lastes ned og før man vet ordet av det så har man en VM kjørende på PCen. Ønsker man å kjøre en annen versjon så kan man få en liste over hva som er tilgjengelig ved å skrive:

multipass find

For å liste VMene som kjører skriver man følgende kommando:

multipass list

VMene som man oppretter får kule navn hvis man ikke spesifiserer navnet med parameteret «–name» (navnene må være unike for VMene). I eksemplene under heter en slik VM: «keen-yak». Ønsker man mer utvidet informasjon om en VM så kan man skrive:

multipass info keen-yak
Name:           keen-yak
State:          RUNNING
IPv4:           10.140.94.253
Release:        Ubuntu 18.04.1 LTS
Image hash:     d53116c67a41 (Ubuntu 18.04 LTS)
Load:           0.00 0.12 0.18
Disk usage:     1.1G out of 4.7G
Memory usage:   71.6M out of 985.4M

For å koble seg til en VM så kan man enten kjøre en kommando i PowerShell eller starte et Shell ved å høyreklikke på Multipass-ikonet i systemstatusfeltet og velge «Open Shell» på den aktuelle VMen. Dette åpner et nytt PowerShell-vindu og man er innlogget på VMen. Kommandoen for å starte et shell fra PowerShell er:

multipass shell keen-yak

Hvis man ikke har noen VMer kjørende og man trykker på «Open Shell» i GUIen eller skriver følgende kommando i PowerShell:

multipass shell

Så opprettes det en VM (siste Ubuntu LTS med standard CPU (Central Processing Unit), disk og minne) som får navnet «primary». Man ville fått det samme resultatet om man hadde kjørt følgende kommando:

multipass launch --name primary

Primary instansen har også automatisk «home mount» som det så fint heter. Det betyr at innholdet i Windows-katalogen «C:\Users\Rosabloggen» (Windows-brukeren heter her «Rosabloggen») er tilgjengelig på en katalog «Home» i VMen. Man kan da overføre filer mellom Windows og Linux på en enkel måte ved f.eks å bruke Linux-kommandoen «cp» (forkortelse for copy). Det er også mulig å koble andre mapper på andre VMer ved å bruke kommandoen «mount». Syntaksen er slik:

 multipass mount C:\mappe primary:/home/ubuntu/win_mappe

For å fjerne en kobling brukes kommandoen «umount».

multipass umount primary:Home

Man kan starte («start»), stoppe («stop»), slette («delete»), gjenopprette («recover») og permanent fjerne («purge») sletta VMer med følgende kommandoer:

multipass stop keen-yak
multipass start keen-yak
multipass delete keen-yak
multipass recover keen-yak
multipass purge

Ønsker man å spesifisere CPU, disk og minne så kan man bruke parametere til dette. F.eks en VM med 2 CPUer, 10GB lagring og 2GB med minne  så skriver man følgende:

multipass launch --cpus 2 --disk 10G --mem 2G

En standard VM har 1 CPU, 5GB disk og 1GB minne. For å liste alle parameterne så brukes «help»-kommandoen (dette gjelder forresten ikke bare «launch» men alle kommandoene) slik som dette:

multipass help launch

Da er det bare å hive seg rundt folkens og opprette VMer, men husk å stoppe de og rydde opp når du er ferdig for de liker å kose seg i bakgrunnen hvis du glemmer det. Just saying!

Julepoesi

Det er lenge siden jeg har glimta til med noe poesi på Rosabloggen så da tenkte jeg at det var på tide med et lite juledikt. Nå skal jeg ikke skryte på meg å ha skrevet dette mesterverket for det er nemlig larviksforfatteren Dagny Holm som har gjort. Nyyyt!

Jul

Julestri og julestrev,
julekort og julebrev,
julebakst og julehandel,
julegrøt med julemandel,
julenisse, julehelg,
julereinsdyr (ikke elg!)
juleglede, julerose,
julegodt i julepose,
julenek og juleved,
julelys på juletre,
julekveite, juletorsk,
juleribbe (typisk norsk),
julepynt og julestas,
julestress og julemas …
Men plutselig så er det jul,
og engler daler ned i skjul
med fred til store og til små,
for deilig er den himmel blå.
Så tennes lys i alle hjem.
Et barn er født i Betlehem.

The Griswolds Mark II

Da er det snart jul igjen og julelysa tennes i de tusen hjem. Vi her hjemme pleier å tenne julelysa på huset 1. advent, men i år var vi litt i stuss om vi skulle tenne lysa før. Det var overraskende mange som tente lysa sine tidligere (les: allerede i november). Jeg pleier å være blant de første som tenner i nabolaget, men i år ble jeg trolig en av de siste. Hva som er bakgrunnen for den premature tenninga vet jeg ikke, men jeg vet at psykolog og lykkeforsker Ragnhild Bang Nes kom med en oppfordring i november om å bare tenne julelysa (eller vinterlys som hun også kaller dem) når du føler for det. Jeg har lagt ved en link til artikkelen her. Jeg har før om åra brukt et astronomisk tidsur til å styre julelysa på huset. Du kan lese mer om denne løsninga i innlegget «The Griswolds«. I år så gjorde jeg en endring på styringa av lysa og erstatta det astronomiske tidsuret med et par Z-Wave+ Fibaro FGWPF-102 veggplugger som er styrt av min Athom Homey Pro (du finner et innlegg om den her). Bakgrunnen for at jeg byttet til en smarthusløsning er rett og slett den fleksibiliteten som dette gir. Jeg har nå på en enkel måte muligheten til å styre lysa slik jeg ønsker. Denne styringa er selvsagt helt uinteressant for de som lar lysa brenne døgnet rundt i en måned eller to. Jeg må være så ærlig at jeg slukker lysa når jeg ikke har noe glede av dem som når jeg f.eks. sover eller er på jobb. Det som smarthusløsningen tillater er at jeg nå kan styre når lysa lyser på den enkelte dag. Det er jo gjerne noen dager hvor man ønsker at lysa gjerne skal være på hele dagen. Jeg har klippet sammen et bilde av hvordan en slik flow i Homey’en kan se ut her. Denne flow’en her kjører hvert 15. minutt og der er ingen sjekker om julelysa allerede er på eller av. Der er sikkert noen flow-ninjaer som vet om en bedre måte å gjøre dette på, men den funker og det er godt nok for meg.

Teletype Network

Bare så det er sagt så blir dette en skikkelig «geek out«. Vi skal snakke om en gammel protokoll (RFC 15) fra 1969, utvidet i RFC 855 i 1983, og standardisert av Internet Engineering Task Force (IETF) i Internet Standard STD 8. Vi snakker om Telnet («teletype network»). Kort oppsummert så er det en toveis interaktiv tekstorientert (7-bit ASCII) klient-server protokoll som kommuniserer over Transmission Control Protocol (TCP) port 23. Opprinnelig så gikk trafikken over Network Control Program (NCP) protokollen som ble brukt av tidlig Advanced Research Projects Agency Network (ARPANET). Protokollen er ukryptert og er i dag på mange måter erstattet av Secure Shell (SSH) protokollen som først ble utgitt i 1995. Den eldre protokollen brukes i disse dager bare i sjeldne tilfeller hvor SSH eller andre moderne protokoller ikke støttes. Nå skal det sies at jeg fortsatt bruker telnet til feilsøk av for eksempel Simple Mail Transfer Protocol (SMTP). Nederst i Wikipedia-artikkelen ser man et eksempel på hvordan telnet kan brukes mot SMTP-porten (TCP port 25) på en e-postserver. En liten digresjon når vi snakker om feilsøk. Jeg hører stadig vekk at noen forsøker å «pinge» (telnet er forresten også er verb hvis man lurer på det) en maskin, men den svarer ikke så da er konklusjonen at den er av/død. Når folk snakker om ping så er det en applikasjon som benytter seg av Internet Control Message Protocol (ICMP) protokollen til å sende såkalte type 8 (Echo) «pakker». Det som er problemet er at mange brannvegger (også den lokale på maskinen) kan blokkere ICMP-trafikk og da oppleves det som at pakkene ikke kommer fram selv om maskinen er på lufta. Nok om ICMP. Telnet-klienten (programvaren) finner man stortsett på alle plattformer. I eldre Windows-versjoner så var telnet en standard DOS-kommando, men i nyere Windows-versjoner må denne installeres. Selv foretrekker jeg å bruke PuTTY som klient. PuTTY er også en SSH-klient hvis man skulle trenge noe slikt. For at denne artikkelen skal gi noe mening så må vi snakke litt om tegnsettet American Standard Code for Information Interchange (ASCII), eller rettere sagt ASCII-kunst. ASCII-kunst er kunst/tegninger laget av tegn i ASCII-tegnsettet. Under ser dere et eksempel på en hund jeg fant på nettsiden ASCII Art Archive.

  __      _
o'')}____//
 `_/      )
 (_(_/-(_/

Og nå kommer vi til sakens kjerne og hva denne artikkelen faktisk handler om og det er Star Wars og konkret episode IV – A new hope fra 1977. Noen har laget filmen (riktig nok ikke hele filmen enda) i ASCII og det eneste man trenger å gjøre for å se den er å telnete inn på towel.blinkenlights.nl (kommandoen er: telnet towel.blinkenlights.nl). Enjoy!

This entry was posted on 7. november 2020, in Blogg and tagged .

Gresskar anno Domini 2020

Among Us

Det ble en annerledes Halloween-feiring for oss som det ble for veldig mange andre i år. Nabolaget ble enig om at den vanlig vandringa fra dør til dør skulle avlyses. Det sier litt om hvilke tider vi lever i når man sier til ungene, som har gledet seg et år siden sist Halloween, at det ikke blir noe vanlig feiring på grunn av smittevern, og de bare svarer OK. Nok om korona og pandemi for dette innlegget skal egentlig handle om det som etterhvert har blitt en aldri så liten tradisjon. Jeg må innrømme at jeg var inne på tanken å droppe gresskaret i år på grunn av feiringens art, men da fikk jeg opplyst fra flere hold at det blir ikke Halloween uten gresskar så da var det bare å hive seg rundt. Når jeg spurte om innspill om hva som er hippt i år fikk jeg til svar «Impostor» fra dataspillet «Among Us». For de som ikke kjenner spillet så har jeg en link til utgiveren her. Jeg kjente til spillet fra før og min umiddelbare tanke var at dette blir for enkelt på grunn av grafikken i spillet er veldig enkel, og for en som har hatt et gradvis økning i vanskelighetsgrad fra år til år så føltes dette som et steg i feil retning. Etter en lenger tenkepause kom jeg opp med at jeg skulle prøve meg på en Baby Yoda fra Disneys superserie The Mandalorian som blant annet sendes på Disney+. Jeg kom av ulike grunner litt vel seint i gang med skjæringen på Halloween så resultatet lider litt under det, men jeg må si meg jevnt over fornøyd med resultatet. Trykk på bildet av gresskaret og nyt!

SITRAP fra ødemarka

I dag er det 4 måneder siden jeg forlot alle sosiale media og tok steget ut i den digitale ødemarka. Hvis noen skulle være i tvil så definerer jeg ikke Rosabloggen som SoMe (sosiale media) da den er en monologisk kommunikasjonsplattform. Ja, man kan vel heller kategorisere den som «uSoMe» – usosiale media. Så hvordan har det gått? Det har vært helt strålende! Jeg har ikke savnet Face, Snap eller Insta i det hele tatt. En bieffekt av å droppe SoMe er at volumet på innlegg på Rosabloggen har økt en del ettersom den blir eneste utløpsted for GPP (Generelt Pisspreik). Jeg hadde et par forbehold når jeg vurderte om jeg skulle droppe SoMe eller ikke, og de var: 1. jeg går glipp av for mye. Med det mener jeg arrangementer og invitasjoner. 2. utfordringer relatert til logistikk. Skoler, speider osv. poster en del praktisk informasjon på Facebook-grupper. Jeg har ikke opplevd at de to har vært et spesielt stort problem. Jeg har faktisk ikke gått glipp av noe som jeg vet om. Det er i seg selv en ganske befriende tanke; å slippe å ta stilling til ting hele tiden. Skolen kommuniserer nå og spesielt i disse koronatider bedre på andre plattformer som e-post og applikasjoner som skolen bruker i undervisningen (f.eks. Microsoft Teams og Showbie). Digitaliseringen i skolen har tatt et kvantesteg i riktig retning. I de tilfeller det er noe spesielt som skjer på Facebook så fanger fruen det opp, men det er det lite av. En liten kuriositet ved å droppe Facebook er at det er forbausende få som husker å sende deg bursdagshilsen, men den så jeg vel komme. Konklusjonen er at jeg i skrivende stund ikke har noen planer om å forlate den digitale ødemarka og returnere til SoMe.

Relasjoner – OSS

Etter at jeg la ut serien med innlegg om relasjonsdatabaser her på Rosabloggen har jeg fått en del spørsmål, og jeg tenkte at det kunne være greit å samle de ofte stilte spørsmåla i et eget innlegg.

«Hva hvis en pasient har flere leger?». Det det spørres om her kalles en mange-til-mange-relasjon. I praksis betyr det at en lege kan ha mange pasienter, og en pasient kan ha mange leger. Jeg skal nå vise hvordan dette kan løses i lege/pasient-databasen vår. For at man skal ivareta normaliseringen må det innføres det som kalles en koblingstabell. For å gjøre det oversiktlig for meg selv så pleier jeg å navngi koblingstabellene med et navn som viser hvilke to tabeller jeg knytter sammen. I dette tilfellet er det tabellene «lege» og «pasient» som skal knyttes sammen i en koblingstabell, og gir den derfor enkelt og greit navnet: «lege_pasient». Koblingstabellen «lege_pasient» har det som kalles en sammensatt primærnøkkel. Den består av de to primærnøklene til tabellene «lege» og «pasient». Siden man nå ikke lenger trenger fremmednøkkelen «l_id» i tabellen «pasient» så kan denne slettes. Denne ble kun brukt til å knytte en pasient til en lege, og har derfor ingen funksjon lenger. De 3 involverte tabellene i databasen ser nå slik ut:

Under er SQL-spørringa for å hente ute en liste som viser pasienter knyttet mot leger.

SELECT pasient.navn AS pasient,
       lege.navn AS lege
  FROM pasient
  INNER JOIN lege_pasient on lege_pasient.personnr = pasient.personnr
  INNER JOIN lege on lege.l_id = lege_pasient.l_id;

Resultatet av spørringa ser slik ut:

Ser man på tabellen over så har hver lege 2 pasienter hver, og «Gunnar Åm» han har 2 leger. Nå kan det kanskje virke litt søkt at en pasient har flere leger, men mange-til-mange-relasjoner er ganske vanlig. La oss ta et enkelt ordresystem. Vi har en ordretabell og en produkttabell. Dette er en mange-til-mange-relasjon da en ordre kan inneholde mange produkter, og et produkt kan være på mange ordrer. Koblingstabellen «ordre_produkt» (et bedre navn hadde kanskje vært «ordrelinjer») vil også gjerne inneholde antallet av de respektive produktene.

«Hvordan legger jeg inn leder til en ansatt?». Der er flere måter å løse dette på. Man kunne brukt en avdelingstabell som de ansatte knyttes mot, og de ulike avdelingene har en leder knyttet mot seg. Men nå skal vi gjøre ting enklere enn som så. Problemet kan løses ved hjelp av rekursive forhold. Enkelt forklart så har man en fremmednøkkel som peker til primærnøkkelen i en og samme tabell. Jeg har laget et enkelt organisasjonskart med 10 ansatte for den fiktive bedriften Rakett AS.

Jeg har laget en enkel tabell «ansatt» for alle de ansatte. Ansattnummeret er unikt for alle ansatte i bedriften og blir primærnøkkelen «ansattnr» i tabellen «ansatt». Videre så har vi navnet og stillingen til de ansatte, og til slutt fremmednøkkelen «leder» som peker til primærnøkkelen «ansattnr» i samme tabell. Tabellen ser slik ut:

Som man ser av tabellen (og av organisasjonskart) så har alle en leder bortsett fra daglig leder. Verdien NULL betyr at der ikke eksisterer en fremmednøkkel. Skal man hente ut en liste over ledere og sine ansatte så kan SQL-spørringa skrives slik:

SELECT leder.navn AS leder,
       medarbeider.navn AS ansatt 
FROM ansatt medarbeider
INNER JOIN ansatt leder ON leder.ansattnr = medarbeider.leder;

SQL-spørringa over kalles gjerne en «self join». Man kan se på en «self join» som om at man slår sammen to kopier av samme tabell, men tabellen er selvsagt ikke kopiert. «medarbeider» og «leder» er alias til tabellen «ansatt» og navnene på de to «kopiene». Resultatet av spørringa blir som dette:

Relasjoner – SQL

Når man skal hente, legge til, oppdatere eller slette data fra en relasjonsdatabase så er det naturlig å snakke om SQL. SQL står for Structured Query Language og er et spørrespråk for databaser. Nå skal ikke dette innlegget være noe SQL-kurs for sånt finner man mye bra av på nett. Jeg tenkte heller at jeg skulle vise hvordan noe spørringer vil se ut mot en SQLite-versjon av lege/pasient-databasen fra innlegget «Relasjoner – Normalisering«. Jeg brukte forresten SQLiteStudio til å opprette databasen, til å legge data inn i tabellene og for å kjøre de aktuelle spørringene. Her er den første og den enkleste SQL-spørringa:

SELECT navn, tlf FROM pasient;

SQL-spørringa over henter enkelt og greit navnet og telefonnummeret til alle pasientene. SQL-spørringer avsluttes med semikolon. Resultatet er som følger:

Vi skal nå kikke på en mer avansert spørring hvor vi henter data fra flere tabeller.

SELECT pasient.personnr AS personnr,
       pasient.navn AS navn,
       pasient.adresse AS adresse,
       pasient.postnr AS postnr,
       poststed.poststed AS poststed,
       pasient.tlf AS telefon,
       lege.navn AS lege
  FROM pasient
  INNER JOIN poststed on poststed.postnr = pasient.postnr
  INNER JOIN lege on lege.l_id = pasient.l_id;

Vi tar en stegvis gjennomgang av SQL-spørringa over.

  1. «SELECT pasient.personnr AS personnr,» betyr hent personnummeret til pasienten. I spørringer som dette som involverer flere tabeller (her: pasient, lege og poststed) så spesifiserer man gjerne tabellnavnet for feltet. Altså betyr «pasient.personnr» personnr-feltet fra tabellen pasient. «AS» betyr gi kolonneoverskrifta i utlistingen navnet «personnr».
  2. «pasient.navn AS navn,» er en fortsettelse fra linja før (legg merke til kommaet i slutten av linje 1) og betyr hent navnet til pasienten og kall kolonna «navn».
  3. «pasient.postnr AS postnr,» er postnummeret til pasienten og kall kolonnna «postnr».
  4. «poststed.poststed AS poststed,». Her henter man poststedet fra tabellen «poststed» og kaller kolonna ikke uventet «poststed».
  5. «pasient.tlf AS telefon,» som betyr telefonnummeret til pasienten og kall kolonna «telefon».
  6. «lege.navn AS lege» gir navnet til legen fra tabellen «lege» og kolonneoverskrifta blir «lege».
  7. «FROM pasient» betyr at dataene hentes fra tabellen «pasient».
  8. «INNER JOIN poststed on poststed.postnr = pasient.postnr» betyr at man henter data fra tabellen «poststed» hvor postnummeret (postnr) er likt i tabellene «poststed» og «pasient». Til informasjon så finnes flere typer med «JOINs». «poststed.postnr» er primærnøkkel i tabellen «poststed» og «pasient.postnr» er fremmednøkkel i tabellen «pasient».
  9. «INNER JOIN lege on lege.l_id = pasient.l_id;» henter data fra tabellen «lege» hvor ID-nummeret (l_id) er likt i tabellene «lege» og «pasient». «lege.l_id» er primærnøkkel i tabellen «lege» og «pasient.l_id» er fremmednøkkel i tabellen «pasient». SQL-spørringa avsluttes med et semikolon.

Resultatet som listes ut av spørringa blir slik:

Spørring nummer 3 skal hente ute en adresseliste, som inneholder navn, adresse, postnummer og poststed, for alle pasientene til legen «Petter Olsen».

SELECT pasient.navn AS navn,
       pasient.adresse AS adresse,
       pasient.postnr AS postnr,
       poststed.poststed AS poststed
  FROM pasient
  INNER JOIN poststed on poststed.postnr = pasient.postnr
  INNER JOIN lege on lege.l_id = pasient.l_id
  WHERE lege.navn = 'Petter Olsen';

SQL-spørringa over er ganske lik spørring nummer 2 så jeg går ikke i detalj gjennom hver linje, men den har fått en ny linje på slutten av spørringa. «WHERE lege.navn = ‘Petter Olsen’;» betyr enkelt og greit at spørringa skal begrenses til bare å inneholde pasientene til legen «Petter Olsen».

Legg merke til at navnet til legen ikke er med i utlistinga. Skulle det vært med så måtte man lagt «lege.navn AS lege» til i spørringa før «FROM pasient». Pass på at man har kommaene på rett plass. For de som nå fikk litt panikk så finnes det verktøy med fine grafiske grensesnitt hvor man kan bruke mer eller mindre «dra og slipp»-funksjoner (f.eks. Microsoft Access) for å generere SQL-spørringene.

Relasjoner – Verktøy

I innlegget «Relasjoner – Normalisering» gikk jeg gjennom en del av teorien bak design av en relasjonsdatabase. Vi skal nå kjapt kikke på noen systemer og applikasjoner man gjerne kommer borti i forbindelse med relasjonsdatabaser. Vi begynner med en applikasjon som kanskje mange allerede har på PCen gjennom Office-pakken. Microsoft Access er en applikasjon hvor det er mulig å lage relasjonsdatabaser. Microsoft Access har veldig mange muligheter og en del av de overlapper med Excel. Det er vanlig å bruke Access-databaser som datakilder til Excel, Power BI og for den del Word (f.eks. en adressedatabase for fletting av brev). Microsoft Access har noen begrensninger (maksgrense på 2GB og 32.768 objekter i databasen.), men for de fleste er dette ikke noe problem. De som er vant til Office-pakken og klassiske Microsoft arbeidsflater vil kjenne seg godt igjen. Applikasjonen har gode veivisere og designverktøy. Som sagt for de som allerede har denne applikasjonen så er dette et bra sted å begynne. Siden vi snakker om Micrsoft så må man nevne Microsoft SQL Server Express. Systemet som kjører som en egen tjeneste har en begrensning på databasen på 10GB, maksimalt minne på 1.4GB og kjører på 1 socket eller 4 kjerner. Det kan være at noen allerede har en Microsoft SQL Server Express installert da den gjerne installeres som databasesystem i andre applikasjoner. Det finnes en rekke andre versjoner av Microsoft SQL Server men de blir gjerne altfor kostbare for privat bruk. Det er komplett umulig å ikke nevne MySQL (uttalt ˌmaɪˌɛsˌkjuːˈɛl) når man snakker om databasesystemer. MySQL er lisensiert som åpen kildekode (GPL-lisens). Det skal sies at det har vært en del diskusjon rundt lisensieringen og Oracle som vedlikeholder MySQL i dag. Dette resulterte i 2009 at kodegrunnlaget til MySQL ble tatt videre til MariaDB i bekymring av at Oracle kjøpte Sun Microsystems som eide MySQL. MySQL er svært utbredt og brukes av veldig mange også store selskaper som Airbnb, Uber, Netflix og Dropbox. Rosabloggen kjører WordPress med nettopp MySQL i bunnen. Personlig så er dette det databasesystemet jeg har mest kunnskaper om utenom Microsoft SQL Server. Hvis man ikke har noen spesielle preferanser til MySQL så anbefaler jeg at man kikker på MariaDB som på mange måter er lik MySQL, men er gratis og garantert å forbli åpen kildekode. Selskap som Google, Wikipedia og WordPress.com bruker MariaDB. Jeg nevnte selskapet Oracle (egentlig heter det Oracle Corporation). Oracle er et gammelt selskap (grunnlagt i 1977) med titusenvis av ansatte. Selskapet er regnet som en kjempe i databasemiljøene med sitt system som har det ikke overraskende navnet Oracle Database eller bare Oracle. Det er lite trolig at man kommer borti Oracle systemer uten at man er del av et større driftsmiljø. Det er også en kjensgjerning at en del firma migrerer til andre systemer pga. kostnadene knyttet til det å ha en Oracle installasjon. Videre må jeg også nevne PostgreSQL. Utvikligen av dette systemet startet på 1980-tallet og er i dag et åpen kildekode-prosjekt, med en svært liberal lisens. Denne gjør at PostgreSQL kan brukes, modifiseres og distribueres av såvel private som kommersielle foretak uten noen som helst økonomisk kompensasjon til de originale utviklerne. Til slutt skal jeg si noen ord om SQLite. SQLite er kanskje verdens mest utbredte databasemotor. Den kjører på de fleste mobiler og datamaskiner. Den er del av utallige apper/applikasjoner som folk bruker hver dag. Vi snakker om hundrevis av milliarder av SQLite databaser i verden. Dette burde være en indikasjon på at kanskje SQLite er en god plass å begynne. Nå er ikke SQLite direkte sammenlignbart med klient/server systemer som MySQL, MarieDB, Oracle, PostgreSQL, Microsoft SQL Server osv. som egentlig skal løse litt andre problemstillinger, men for «hjemmebruk» er SQLite helt genialt. Når man laster ned SQLite fra nettsiden så bør man også laste ned pakken med kommandolinje-verktøy hvis man ikke velger et tredjepartsverktøy som SQLiteStudio. Jeg bruker selv SQLiteStudio og er veldig godt fornøyd med det. Jeg oppfordrer å donere noen kroner til utvikleren hvis man bestemmer seg for å bruke programmet. Noe av det fine med SQLite er at man kan flytte databasen mellom ulike datamaskinarkitekturer. Jeg har f.eks. tatt en SQLite database fra en Raspberry Pi og jobbet med den på en Microsoft Windows PC. Da er det bare å bestemme seg for hvilket teknisk nivå man vil legge seg på og laste ned et databasesystem.

Relasjoner – Normalisering

I innlegget «Relasjoner – Intro» ble ordet «normaliseringsformer» brukt i forbindelse med databasedesign. Teorien og spesielt ordlyden bak normalisering kan fort bli tung og vanskelig å forstå så jeg vil i dette innlegget forklare hva det er gjennom bruk av eksempler. Dessverre så vil der være noen ord og uttrykk vi ikke kommer rundt så det er bare å bite tenna sammen. Vi begynner med noen data i en tabell. Vi kaller den «universalrelasjonen». Universalrelasjonen har ingen spesielle regler utover at man har rader og kolonner. Under har jeg et eksempel på en universalrelasjon. På grunn av plassmangel har jeg brukt en del forkortelser i kolonnene overskriftene. «l_» står for «lege_». «l_navn» blir da «lege_navn». «p_» står for «pasient_» og da er f.eks. «p_navn» det samme som «pasient_navn». Til informasjon så er primærnøkler merket med grønt i kolonneoverskrifta. Universalrelasjonen viser 2 leger som har 3 pasienter og en del annen informasjon.

For å oppfylle 1. normalform (1NF) så kan tabellen ikke inneholde ikke-atomære verdier eller repeterende grupper. Med «ikke-atomære verdier» menes verdier som inneholder flere delverdier. Tabellen inneholder ikke-atomære verdier i feltene «l_adr» og «p_adr» som består av gateadresse, postnr og poststed. Med «repeterende grupper» menes at det finnes mer enn en verdi i krysset mellom rad og kolonne. De repeterende gruppene i tabellen er: «p_personnr», «p_navn», «p_adr» og «p_tlf». Når man deler opp «l_adr» og «p_adr» i sine respektive kolonner («l_adr», «l_postnr», «l_poststed» og «p_adr», «p_postnr», «p_poststed»), og legger den ekstra pasienten i den repeterende gruppa på en egen rad så oppfyller man 1NF. Tabellen under viser hvordan det vil se ut. Legg merke til at «l_id» og «p_personnr» nå er primærnøkkel siden man ikke unikt kan identifisere den riktige raden for en pasient basert på «l_id» alene.

I 2. normalform (2NF) må alle verdier være fullt funksjonelt avhengig av primærnøkkelen. Med «full funksjonell avhengighet» menes at man ikke har noen partielle avhengigheter. Partiell avhengighet betyr at en verdi er avhengig av kun deler av primærnøkkelen (i tabellen over består primærnøkkelen i grønt av «l_id» og «p_personnummer»). «l_navn» er partiell avhengig av «l_id», men ikke «p_personnummer». På samme måte er «p_navn» partiell avhengig av «p_personnummer», men ikke «l_id». For å fikse dette må tabellen splittes i to. Jeg har kalt tabellene «lege» og «pasient». Legg merke til kolonnen «l_id» i tabellen «pasient». Dette er en fremmednøkkel og brukes til å koble pasientene mot riktig lege.

For at en tabell skal kunne være i 3. normalform (3NF) så kan man ikke ha noen transitive avhengigheter. Transitiv avhengighet betyr at en verdi er avhengig av en annen ikke-primærnøkkel-verdi. I de to tabellene over så er «l_poststed» transitivt avhengig av «l_postnr» og «p_poststed» transitivt avhengig av «p_postnr», men verken «l_postnr» eller «p_postnr» er noen primærnøkkel. For å fikse dette så flyttes poststedene ut i en egen tabell (poststed) hvor postnr er primærnøkkelen. Tabellene under oppfyller nå 3NF.

Til slutt skal vi se på Boyce-Codd normalform som også omtales som BCNF eller 3.5NF. For at en tabell skal kunne være i Boyse-Codd normalform, må alle determinanter være kandidatnøkler. En determinant er en attributt eller gruppe attributter som en annen attributt er fullt funksjonelt avhengig av. Et eller flere attributter som sammen identifiserer en entitet unikt kalles en «supernøkkel». Minimalistiske supernøkler, dvs. at man kan fjerne et attributt fra en supernøkkel og så er det fortsatt unikt kalles en kandidatnøkkel. Kandidatnøkler er sikre identifikatorer for en rad, og kan brukes som primærnøkler og som referanser for fremmednøkler. I vår tabell er det ingen brudd på Boyce-Codd normalform. Determinantene er: personnr(pasient), postnr(poststed) og l_id(lege). Kandidatnøklene er: personnr(pasient), postnr(poststed) og l_id(lege). Dersom en tabell er normalisert til 3NF, vil den i de fleste tilfeller også innfri kravene til BCNF. Brudd på BCNF er sjeldne og litt vanskelige å håndtere på en god måte, så derfor stopper man ofte normaliseringen når tabellen er på 3NF. Da har vi vært gjennom den tyngste og viktigste teorien når man skal lage en relasjonsdatabase. Men hvor skal man lage en relasjonsdatabase? Innlegget «Relasjoner – Verktøy» vil kunne gi noen svar på det.