Luku 5

Viittausten toteutus

Ohjelmoinnissa olion sisällä voi olla viittaus toiseen olioon, ja vastaavasti tietokannan taulun rivillä voi olla viittaus toiseen riviin. Tavallinen tapa toteuttaa viittaukset tietokannassa on antaa jokaiselle riville id-numero (pääavain), jolla voimme viitata siihen muualta.

Yksi moneen -suhde

Tarkastellaan tilannetta, jossa tallennamme tietokantaan kursseja ja opettajia. Taulujen välillä on yksi moneen -suhde: jokaisella kurssilla on yksi opettaja, kun taas yhdellä opettajalla voi olla monta kurssia. Javassa voimme luoda tarvittavat luokat seuraavasti:

public class Opettaja {
    private String nimi;
    
    public class Opettaja(String nimi) {
        this.nimi = nimi;
    }
}

public class Kurssi {
    private String nimi;
    private Opettaja opettaja;
    
    public class Kurssi(String nimi, Opettaja opettaja) {
        this.nimi = nimi;
        this.opettaja = opettaja;
    }
}

Vastaavasti voimme luoda tietokannan taulut näin:

CREATE TABLE Opettajat (id INTEGER PRIMARY KEY, nimi TEXT);
CREATE TABLE Kurssit (id INTEGER PRIMARY KEY, nimi TEXT, opettaja INTEGER REFERENCES Opettajat);

Taulussa Kurssit sarake opettaja viittaa tauluun Opettajat, eli siinä on jonkin opettajan id-numero. Ilmaisemme viittauksen REFERENCES-määreellä, joka kertoo, että sarakkeessa oleva kokonaisluku viittaa nimenomaan tauluun Opettajat.

Voisimme laittaa tauluihin tietoa vaikkapa seuraavasti:

INSERT INTO Opettajat (nimi) VALUES ('Kaila');
INSERT INTO Opettajat (nimi) VALUES ('Kivinen');
INSERT INTO Opettajat (nimi) VALUES ('Laaksonen');
INSERT INTO Kurssit (nimi, opettaja) VALUES ('Ohjelmoinnin perusteet',1);
INSERT INTO Kurssit (nimi, opettaja) VALUES ('Ohjelmoinnin jatkokurssi',1);
INSERT INTO Kurssit (nimi, opettaja) VALUES ('Tietokantojen perusteet',3);
INSERT INTO Kurssit (nimi, opettaja) VALUES ('Tietorakenteet ja algoritmit',2);

Monta moneen -suhde

Tarkastellaan sitten tilannetta, jossa useampi opettaja voi järjestää kurssin yhteisesti. Tällöin kyseessä on monta moneen -suhde, koska kurssilla voi olla monta opettajaa ja opettajalla voi olla monta kurssia.

Javassa voisimme toteuttaa tämän muutoksen helposti muuttamalla luokkaa Kurssi niin, että siinä on yhden opettajan sijasta lista opettajista:

public class Kurssi {
    private String nimi;
    private ArrayList<Opettaja> opettaja;
    
    public class Kurssi(String nimi) {
        this.nimi = nimi;
        this.opettaja = new ArrayList<>();
    }
}

Tietokannoissa tilanne on kuitenkin toinen, koska emme voi tallentaa järkevästi taulun sarakkeeseen listaa viittauksista. Tämän sijasta meidän täytyy luoda uusi taulu viittauksille:

CREATE TABLE Opettajat (id INTEGER PRIMARY KEY, nimi TEXT);
CREATE TABLE Kurssit (id INTEGER PRIMARY KEY, nimi TEXT);
CREATE TABLE KurssinOpettajat (kurssi_id INTEGER REFERENCES Kurssit,
                               opettaja_id INTEGER REFERENCES Opettaja);

Muutoksena on, että taulussa Kurssit ei ole enää viittausta tauluun Opettajat, mutta sen sijaan tietokannassa on uusi taulu KurssinOpettajat, joka viittaa kumpaankin tauluun. Jokainen rivi tässä rivissä kuvaa yhden suhteen muotoa "kurssilla x opettaa opettaja y".

Esimerkiksi voisimme ilmaista näin, että kurssilla on kaksi opettajaa:

INSERT INTO Opettajat (nimi) VALUES ('Kivinen');
INSERT INTO Opettajat (nimi) VALUES ('Laaksonen');
INSERT INTO Kurssit (nimi) VALUES ('Tietorakenteet ja algoritmit');
INSERT INTO KurssinOpettajat VALUES (1,1);
INSERT INTO KurssinOpettajat VALUES (1,2);

Huomaa, että voisimme käyttää tätä ratkaisua myös aiemmassa tilanteessa, jossa kurssilla on aina tasan yksi opettaja, joskin tietokannassa olisi silloin tavallaan turha taulu.

Jatka tästä seuraavaan osaan: