MySQL-Tutorial
Innholdsfortegnelse
Oppsett
I år er det MySQL som skal brukes som databaseprogram. MySQL er,
som infoweb så fint sier det, en ekte flerbruker, multithreaded
SQL database server. For de som måtte ha lekt med Access på
videregående vil det være mye av det samme, men allikevel en del
nytt. For det første ligger ikke databasen på hjemmeområdet
eller på lokalmaskina, men derimot på en ekstern server,
mysql.stud.ntnu.no.
På http://sif8001.idi.ntnu.no/mysql.php
ligger det et grafisk webbasert brukergrensesnitt for å bruke en
database på mysql.stud.ntnu.no. Men først må du lage deg en
bruker og en database. Til det må du logge deg på med en
ssh-klient (som når du leser mail via pine) og følge
fremgangsmåten gitt på siden over.
En "Database" er her akkurat det samme som en
databasefil i access - en samling med tabeller til et formål.
"Brukere" er de som har lov til å leke med databasen
din, f.eks kan du la naboen legge inn data i dine tabeller med
sin bruker ved å gi hans MySQL-brukernavn rettigheter til det.
Typisk vil du egentlig bare gi deg selv rettigheter til å endre
databasen din.
Mere lesestoff angående opprettelse av MySQL-databaser og brukere på
Infoweb.
Denne siden er ment som en kjapp tutorial til enkel bruk av enda
enklere SQL-setninger. "Hvorfor lære SQL når vi har et
grafisk brukergrensesnitt?" kan du spørre. Vel. Forrutenom
at "dette er pensum" og dermed sikkert hyggelig å lære
er det jo både tøft og gøy. Dessuten kommer man ikke utenom
SQL-setninger når man skal kjøre spørringer mot databaser.
For å logge på en MySQL-server via kommandolinjen, følg
fremgangsmåten på siden gitt øverst. Du bør nå se teksten
mysql> på en egen linje. Det betyr
at programmet venter på en SQL-setning. Alt du skriver inn,
inklusive linjeskift, vil de ta som en SQL-setning. For å
presisere at du nå er ferdig med SQL-setningen avslutter du med
et semikolon. SQL-setningen vil da kjøres, og forhåpentligvis
vil det ikke være noe feil.
Det er også mulig å skrive SQL-setninger rett inn i webinterfacet.
Til de som vil ha begge deler er dette sikkert et fint alternativ.
Eksemplene under kommer til å være noe forenklet, det er mer til
dem enn øyet møter her, men i praksis bruker man sjelden mer enn
det opplistet på denne siden.
Lage tabell, vise tabell
Fra web:
For å lage en tabell i webgrensesnittet logg inn og finn teksten
"Opprett ny tabell i database [databasenavn]", skriv
inn navnet på din nye tabell og hvor mange felter du vil ha. På
neste skjermbilde, fyll ut feltene, felttype, parametere og hva
som er nøkler. Voila, ny tabell.
Fra server
For å lage en tabell, skriver man CREATE TABLE. Syntaksen er:
CREATE TABLE tabellnavn (
idfeltnavn felttype NOT NULL AUTO_INCREMENT,
feltnavn1 felttype,
feltnavn2 felttype,
....
feltnavnN felttype,
PRIMARY KEY (idfeltnavn)
);
Merk at semikolonet til slutt bare forteller MySQL at nå er det
ferdig. Semikolonet er egentlig ikke en del av SQL-setningen, og
i alle andre tilfeller hvor du skriver SQL (f.eks en mulig
eksamensoppgave ;) - skal semikolonet ikke være med. Merk også
at du ikke må ha komma etter det siste del av setningen, dvs. der
du spesifiserer primærnøkler, ellers blir det kluss.
NOT NULL og AUTO_INCREMENT er to flagg
du kan sette på et hvilket som helst felt. NOT NULL
betyr at feltet ikke har lov til å være NULL (dvs
helt tomt). Siden ID-nøkler ikke har lov til å være helt tomme
MÅ dette flagget være satt på id-nøklene.
AUTO_INCREMENT fungerer som autonummer i access
(dvs den finner automatisk et nytt og fint tall hvis du ikke
oppgir ett når du lager en ny post i tabellen), men fungerer
bare sammen med felttyper som er heltall. Det er helt frivillig
å legge til denne i nøkkelfeltene. Begge disse flaggene kan
legges til på ikke-nøkkelfelt og, men det er bare tillatt med ett
AUTO_INCREMENT-felt i hver tabell.
Litt om felttyper:
Det er en hel del felttyper i MySQL, men ikke alle er like intressante.
De mest vanlige er heltall og tekststrenger.
| Feltnavn |
Beskrivelse |
varchar(n) |
varchar(n) er et enkelt tekstfelt med maks lengde n.
Bytt ut n med et passende stort tall, men n kan ikke være større
enn 255. Til større tekstfelter, bruk heller text.
|
text |
text er et stort tekstfelt. Det er veldig treigt å
søke på tekstfelt og de bør unngås der de kan unngås. Men, hvis
man skal lagre større mengder data er de veien å gå.
|
int unsigned |
Et heltall som ikke kan ha negative verdier. Maksverdi ligger
på ca 4.2 milliarder.
|
int |
Et heltall mellom ca -2.1 milliarder og +2.1 milliarder |
|
Hvis det klør i fingrene etter å bruke flere felttyper enn dette, se på
http://www.mysql.com/doc/C/o/Column_types.html for litt dypere innsikt.
Et eksempel:
CREATE TABLE venner (
id int unsigned AUTO_INCREMENT NOT NULL,
fornavn varchar(32),
etternavn varchar(32),
tlf int unsigned,
PRIMARY KEY (id)
);
For å se din nye tabell kan du kjøre MySQL-kommandoen
DESCRIBE tabellnavn;
Sette data inn i tabell
Fra web:
I webgrensesnittet er dette enkelt. Trykk på tabellen du vil sette inn i, velg
"sett inn"-linken og fyll ut en ny post. Resten ordner seg selv.
Fra server:
I SQL bruker man INSERT. Syntaksen er:
INSERT INTO tabellnavn
VALUES(verdi1,verdi2,verdi3.....);
eller
INSERT INTO tabellnavn(feltnavn1,feltnavn2,...,feltnavnN)
VALUES(verdi1,verdi2,...,verdiN);
Tanken er at man har en tabell med noen felt og setter en verdi
til hvert felt i den nye posten. I det første tilfellet setter
man en verdi inn i alle feltene. I det andre tilfellet setter
man en verdi inn i de feltene man oppgir. De feltene som ikke
oppgis vil få en automatisk tildfelt verdi, vanligvis helt tom
(AUTO_INCREMENT, f.eks, kan gjøre sitt for å
hjelpe på det). Den andre parantesen inneholder verdiene du har
lyst å sette inn i den nye posten. Rekkefølgen på disse er den
samme som oppgitt i den første parantesen, eller i tilfelle
ingen parantes etter tabellnavn, rekkefølgen feltene har i
tabellen (dvs den rekkefølgen du lagde dem i).
....kort sagt, verdi 1 til felt 1, verdi 2 til felt 2 etc..
Hvis et felt ikke får tildelt en verdi, og ikke har
AUTO_INCREMENT satt, vil feltet bli tomt. Hvis
feltet har NOT NULL satt, vil dette føre til at hele setningen
feiler, ingen post blir lagt til i tabellen.
Når du skriver verdiene, må tekststrenger oppgis med hermetegn
rundt seg. Hvis det er hermetegn inne i teksttrengen skjærer
ting seg fort. Det kan løses med å sette en backslash, \, foran
hermetegnet inne i tekststrengen. Da vil det hermetegnet anses
som et vanlig tegn og ikke som avslutter på tekststrengen.
Et eksempel:
Vi bruker tabellen fra foregående eksempel.
INSERT INTO venner(fornavn,etternavn)
VALUES('Arne','And');
Merk at her vil tlf og id-feltet bli tomt. Det er derimot lovlig
og i orden siden det tlf-feltet ikke er satt NOT NULL,
og id-feltet har AUTO_INCREMENT satt.
For å se hva som ligger i tabellen, trenger vi en ny SQLspørring:
Hente ut data fra tabeller
Fra web:
Igjen veldig enkelt. Velg tabell i venstre frame og trykk på
"vis"-linken i høyre frame. Feltene kan sorteres på
felttype, stigende og synkende, ved å trykke på feltnavnet.
Mer er det ikke å si om den saken.
Fra Server:
Den mest brukte SQL-setningen må være SELECT.
SELECT går igjennom databasen og henter ut alle
felter som matcher dine kriterier, og returnerer dem i en
2-dimensjonal array, en matrise. Syntaksen er:
SELECT feltnavn1,feltnavn2,...,feltnavnN
FROM tabellnavn
WHERE feltnavn1=verdi1
AND feltnavn2=verdi2
...
AND feltnavnN=verdiN;
Det select gjør er at den velger ut noen felter fra en tabell
og lister alle disse. Hvis du vil ha alle feltene kan du bare
skrive en stjerne i stedet for feltnavn. Rekkefølgen på
feltene i utskrften er igjen avgjort av rekkefølgen på
feltnavnene i spørringen, hvis stjerneløsningen velges kommer
de i den rekkefølgen du lagde tabellen i.
Linje 2-4 i syntaksen tar seg for betingelser og er helt
valgfrie å ta med. Sett at du bare var intressert i delter
der fornavnet var 'Arne', eller en idnøkkel var større enn
74, eller datoen før 1.jan.1954. Da kan man bruke betingelser
for å begrense søket. Typisk brukes denne for å hente ut kun
en post med id-nøkkel lik et eller annet, men det er lov å
være kreativ :)
Sortering
For å sortere datasettet du returnerer kan du legge til en
liten linje i slutten av SELECT-setningen:
ORDER BY feltnavn1,feltnavn2,...feltnavnN
Det denne vil gjøre er å sortere alle postene du har etter
først feltnavn1, så feltnavn2, etc. Du kan oppgi så mange
feltnavn du vil, men typisk bruker man bare ett. Eksempel følger.
Et par eksempler:
Hente ut alle felter i tabellen venner:
SELECT * FROM venner;
Hente ut etternavnet til alle som heter 'Arne' til fornavn:
SELECT etternavn FROM venner WHERE fornavn='Arne';
Hente ut navnet til de som bor på studentby (der telefonnummeret starter med 738):
SELECT fornavn,etternavn FROM venner WHERE tlf>=73800000 AND tlf>73900000;
Hente ut alle poster, sortert på etternavn:
SELECT * FROM venner ORDER BY etternavn;
Hente ut en telefonkatalog, sortert etter etternavn, så fornavn:
SELECT etternavn,fornavn,tlf FROM venner ORDER BY etternavn,fornavn;
Endre på innholdet i poster
Fra web:
Når du ser på innholdet i en tabell, velg "endre" på
ønsket post. Foreta de nødvendige endringer i skjemaet som kommer
opp og lagre.
Fra server:
Av og til har man lyst til å endre på innholdet i ett eller flere
felter i en eller flere poster i en tabell. For eksempel kan det
være å oppdatere data om en person, eller kanskje gjøre større
endringer. Uansett, for å endre på innholdet i allerede eksisterende
poster bruker man UPDATE. Syntaksen er:
UPDATE tabellnavn
SET feltnavn1 = verdi1,
feltnavn2 = verdi2,
...
feltnavnN = verdiN
WHERE feltnavnA = verdiA
AND feltnavnB = verdiB
...
AND feltnavnM = verdiM
Så... Hva gjør den monstersetningen? Du velger en tabell å oppdatere.
I den tabellen kan du nå endre verdien på et felt i ALLE postene. For
eksempel kunne du tatt utgangspunkt i lånekassens studielånstabell og sagt
UPDATE utlaanstabell SET laanebeloep=0
Og alle studenter i dette land ville da hatt 0 i studielån. Hvis nå for
eksempel politikerene innfrir litt valgflesk og senker studielånet til
alle med 50 tusen kroner kunne man bare skrevet
UPDATE utlaanstabell SET laanebeloep = laanebeloep - 50000
og da hadde man i en håndvending trukket fra 50 tusenlapper på alle
studielån i norge. Dette kunne jo forsåvidt ført til at noen fikk et
negativt lån. Og det er jo ikke helt bra. Derfor kan vi legge på
betingelser, som begrenser hvem som update-setningen gjelder. For eksempel vil
UPDATE utlaanstabell SET laanebeloep = laanebeloep - 50000
WHERE laanebeloep >= 50000
kun ta vekk 50 tusen på de som faktisk har mer (eller likt) det i lån.
(og så kan man eventuellt kjøre en ny setning som setter lånet til 0
for de under 50000)
Typisk vil man dog kun endre på en post i slengen. Da oppgir, man gjerne
nøkkelfelt = nøkkelverdi som betingelse og forsikrer seg dermed
om at det kun er den posten du vil endre på som blir endret.
Et siste eksempel, hvis man finner ut at Arne (med id=2) EGENTLIG heter Per:
UPDATE venner SET fornavn='Per' WHERE id=2
Og Arne vil da endre navn til Per. Setningen
UPDATE venner SET fornavn='Per' WHERE fornavn='Arne'
vil derimot endre navnet på ALLE i tabellen som heter Arne.
Slette poster fra tabellene
Fra Web:
Når du ser på innholdet i en tabell, velg "slett" ved de aktuelle postene.
Fra Server:
Vi har DELETE til å slette poster. Syntaksen er:
DELETE FROM tabellnavn
WHERE feltnavn1 = verdi1
AND feltnavn2 = verdi2
...
AND feltnavnN = verdiN;
DELETE sletter poster fra tabellen du oppgir der
betingelsene stemmer. Typisk ber man om å slette fra tabellen
der idnøkkel = rettverdi, hvis man vil spesifiere en bestemt
post å slette.
Et eksempel:
DELETE FROM venner WHERE id=2;
vil slette posten der id = 2.
Slette tabeller
Fra web:
Fra hovedsiden du starter på når du logger inn, velg slett på den
aktuelle tabellen.
Fra server:
For å slette tabeller bruker man DROP. Syntaksen er enkel:
DROP table tabellnavn;
Dette vil da slette tabellnavn. Tror ikke noe eksempel behøves ;)
Endre på tabeller
Med ett så oppstår behovet for å endre på en tabell. Plutselig vil man
legge til et felt, endre på et felt eller slette det. Da er det veldig
slitsomt å slette tabellen, lage ny tabell og registrere alt på nytt.
Til å hjelpe på har man ALTER table SQL-setningen.
Legge til et felt:
ALTER TABLE tabellnavn
ADD feltnavn felttype;
Denne funker mye på samme måten som den gjorde i CREATE
table. Bare oppgi tabellnavn og legg til feltnavn og felttype etter
de samme reglene som i CREATE. Mer er det ikke å si om
saken.
Fjerne felt fra tabell:
ALTER TABLE tabellnavn
DROP feltnavn;
Denne fjerner feltet feltnavn fra tabellen oppgitt. Skulle
være greit det og.
Endre på et felt:
ALTER TABLE tabellnavn
CHANGE feltnavn
nyttfeltnavn nyfelttype nyeflagg;
Det denne vil gjøre er å endre på felttypen til et felt. Fordelen
med denne er at MySQL vil forsøke å bevare dataene som ligger i
feltet (såfremt dette er mulig) i alle postene som ligger i tabellen
allerede. Typisk vil man bruke denne hvis man finner ut at f.eks.
tekstfeltet man opprettet er for lite. Den nederste linjen i
syntaksen tilsvarer syntaksen for feltdefinisjon i CREATE
TABLE.
Eksempel for å øke størrelsen på et tekstfelt:
ALTER TABLE minTabell CHANGE mittTekstfelt
mittTekstfelt varchar(255)
Mer avanserte SQL-operasjoner
Linking av tabeller via SELECT
Som nevnt i avsnittet "hente data ut fra tabeller" brukte
man SELECT for å nettopp hente ut data fra tabeller.
Men select kan også brukes til en simpel form for å linke sammen to
tabeller. Med litt utvidet syntaks fra tidligere avsnitt:
SELECT felter FROM tabell1,tabell2,....,tabellN
WHERE felt1=felt2
AND felt3=felt4
...
AND feltN=feltM
Kort fortalt kan man legge på flere tabeller etter FROM
(separert med komma), og man kan dermed hente ut felter fra alle
tabellene som er nevnt, fra alle mulige kombinasjoner mellom postene
i tabellene. Hvis man har feltnavn som er like i de forskjellige
tabellene må man skille dem med tabellnavn.feltnavn, ellers vet ikke
MySQL hvilken tabell du tenker på.
Et eksempel? Okay! Anta at vi har en tabell med en person og en tabell
med postnr/poststed. Persontabellen har disse feltene:
| Person |
| Feltnavn |
Felttype |
id |
int unsigned (primærnøkkel) |
navn |
varchar(40) |
postnr |
int unsigned (her ligger postnummeret til personen lagret) |
|
I feltrekkefølge, la oss anta at det ligger to poster i denne tabellen.
| id |
navn |
postnr |
| 1 |
Knut |
7000 |
| 2 |
Ole |
5000 |
|
Poststedtbellen har disse feltene:
| Poststed |
| Feltnavn |
Felttype |
postnr |
int unsigned (primærnøkkel) |
poststed |
varchar(30) |
|
... og disse to postene....
| Postnr |
Poststed |
| 5000 |
Bergen |
| 7000 |
Trondheim |
|
Vår SQL-spøring kan da se slik ut:
SELECT person.*,poststed.poststed
FROM person,poststed;
Det denne vil gjøre er å kombinere alle postene i person og
poststed-tabellen på alle mulige måter og returnere de
kombinasjonene. Dette resultatsettet vil se omtrent slik ut
(bortsett fra poststed.postnr som bare er med for å vise
sakene bedre):
| Person.id |
Person.navn |
Person.postnr |
Poststed.postnr |
Poststed.poststed |
| 1 |
Knut |
7000 |
5000 |
Bergen |
| 1 |
Knut |
7000 |
7000 |
Trondheim |
| 2 |
Ole |
5000 |
5000 |
Bergen |
| 2 |
Ole |
5000 |
7000 |
Trondheim |
|
Dette er naturligvis ikke den ønskede måten å koble sammen de to
tabellene på. Det riktige ville vært å bare tatt med de radene
hvor postnr er det samme både i person- og poststed-tabellen. For
å få til det, kan spørringen utvides slik:
SELECT person.*,poststed.poststed
FROM person,poststed
WHERE person.postnr = poststed.postnr;
Nå vil kun rad 2 og 3 fra tabellen over bli med, og personen som
har 7000 som postnummer blir knyttet til Trondheim, og ikke til
Bergen, som jo har 5000 som postnummer. Hvis dette virket
forvirrende, sett deg ned og tenk litt på dette, det er egentlig
veldig logisk. Og man får noe som tilsvarer en relasjon, i dette
tilfellet en en-til-mange-relasjon..
Bruk av alias:
Noen ganger har man behov for å sammenligne data fra forskjellige
rader i samme tabell. (Man sammenligner attributtene til to
entiteter av samme entitetsklasse.) Hva som menes med dette
illustreres best ved et eksempel. Det vi trenger er alias.
Vi har tabellen kjaeledyr(id, navn, art, eier).
Vi ønsker å hente ut alle eiere fra denne tabellen som eier både
hund og katt. For å få til dette må vi lete etter rader i
kjaeledyr-tabellen som har samme eier, og der den
ene raden har 'Katt' som art og den andre har 'Hund' som art. En
SQL-spørring som gjør dette er:
SELECT DISTINCT K.eier FROM kjaeledyr AS K, kjaeledyr AS H
WHERE K.art = 'Katt' AND H.art = 'Hund' AND K.eier = H.eier;
Som dere ser, gjør vi her ei spørring mot to eksemplarer av samme
tabell, og gir de to tabellene hvert sitt alias slik at vi
skal kunne spesifisere hvilken av de to tabellene sine felter vi
til en hver tid snakker om. Nøkkelordet
DISTINCT betyr at
vi ikke er interessert i identiske rader i resultatet av spørringen,
derfor vil hver eier kun listes opp en gang selv om han eier mange
hunder eller katter.
Hvis man synes det gjør ting lettere å forstå kan man se på alias
som et verktøy man trenger for å linke en tabell til seg selv. I
eksempelet over er K.eier = H.eier
sammenføyningsbetingelsen, mens K.art
= 'Katt' AND H.art = 'Hund'
er en seleksjon av katte-hundepar fra denne sammenføyningen.
Til slutt....
Det er en fullstendig tutorial på
http://www.mysql.com/doc/ som forklarer alt for de som måtte
være overivrige i å lære mer om SQL :)
Tilbake til notater

|