NTNU IME IDI

SIF8007/8/9 Informasjonsteknologi Grunnkurs, Høsten 2002

[Hovedside] [Faginfo] [Grupper] [Øvinger] [Tilbakemelding] [Forelesningsfoiler] [Ordliste]
[Eksamen] [Spørsmål og svar] [JSP-feil] [MySQL] [Datasalres.] [CD-utlån] [Lenker] [Notater] [Søk]

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


Ansvarlig for innhold: undass-sif8001@idi.ntnu.no  
Teknisk ansvarlig: teknisk-sif8001@idi.ntnu.no  
Teller (angir totalt antall requests for fagsidene, ikke antall unike besøkende:)