Tietokannat ja PHP

Demojen aiheena on tietokantojen käsittely PHP-kielellä.

Tietokannan luominen

Demoissa käytetään SQLite3-tietokantaa jota voidaan hallinnoida suoraan komentoriviltä käynnistyvällä työkalulla. Samaan tapaan toimii myös hienompien tietokannan hallintajärjestelmien hallinnointi (Postgresql, mysql).

  1. Ota SSH-yhteys people.cc.jyu.fi:hin
  2. Tee uusi www:ssä näkyvä kansio esim. demo7
  3. Kopioi itsellesi resepti.sql-tiedosto wget-komennolla:
    wget http://appro.mit.jyu.fi/sovellukset/demot/demo7/resepti.sql
  4. Luo uusi SQLite3-tietokanta komennolla:
    sqlite3 resepti

    SQLite luo nyt uuden resepti-tiedoston ja tekee siitä tietokannan

  5. Voit tutustua työkalun osaamiin komentoihin kirjoittamalla .help
  6. Luo varsinaisen tietokannan taulut komennolla:
    .read resepti.sql

    SQLite lukee resepti.sql-tiedoston ja suorittaa sen sisältämät SQL-komennot. Älä huolestu DROP TABLE-lauseiden virheilmoituksista.

  7. Tutki tietokantasi rakennetta seuraavilla komennoilla: .tables, .schema resepti ja .schema ruokalaji
  8. Tutki mitä taulut sisältävät yksinkertaisilla SQL-kyselyillä:
    SELECT * FROM Resepti;SELECT * FROM Ruokalaji;
    
  9. .quit-komennolla pääset takaisin unix-shelliin

Tietokantayhteys

Sovelluksen alussa pitää luoda tietokantaan yhteys jota käytetään koko suorituksen ajan. Yhteyden avaaminen on aina raskas prosessi joten turhaan yhteyttä ei pidä aukoa ja sulkea. Suurissa sovelluksissa tietokantayhteys pidetään auki pitempään ja samaa yhteyttä käytetään uudelleen ja uudelleen.

Kyselyt

Tietokantaan kohdistuvat kyselyt ovat jokaisen sovelluksen perusta. Jos SQL-kyselyiden kirjoittaminen tuottaa suuria hankaluuksia voit harjoitella niitä henkilökohtaisen tiedonhallinnan perusteet -kurssin demotehtävillä.

Lisääminen

Tietojen lisääminen tapahtuu valmisteltujen kyselyjen avulla aivan samaan tapaan kuin kyselyjenkin tekeminen:

Poistaminen

Poistetaan edellä lisätty resepti

$sql = $dbh->prepare('DELETE FROM resepti
	WHERE reseptiID = :id');

if ( !$sql ) print_r( $dbh->errorInfo() );

$reseptiID = 10;

$sql->bindParam( ":id", $reseptiID );

$ok = $sql->execute();

if ( !$ok ) print_r( $sql->errorInfo() );

Kokeile onnistuuko poistaminen

Yritä poistaa ruokalajeja. Onnistuuko se ilman ongelmia? Voitko vapaasti poistaa minkä tahansa ruokalajin?

Päivittäminen

Valmisteltujen kyselyjen edut tulevat esiin parhaiten kun samaa kyselyä joudutaan suorittamaan useaan kertaan. Päivitetään useaa reseptiä:

// kokeillaan muuttaa reseptien henkilomäärää
// käytetään toisenlaista prepare-muotoa ?-merkkien avulla
$sql = $dbh->prepare('UPDATE resepti
        SET henkilomaara = ?
        WHERE reseptiID = ?');

if ( !$sql ) print_r( $dbh->errorInfo() );

// sijoitetaan taulukkoon kaikki henkilomaarat ja
// reseptien tunnisteet jotka aiotaan muuttaa
$reseptit = array(1 => 1,
        2 => 2,
        3 => 4,
        4 => 3,
        5 => 2,
        6 => 3);

foreach ( $reseptit as $resepti => $maara) {
 // tehdään taulukko jossa on henkilomäärä ja reseptin tunniste
 print $resepti . " " . $maara . "\n";
 $arvot = array($maara, $resepti ) ;

 // bindParam-kutsua ei tarvita ollenkaan vaan sitominen
 // tapahtuu executen yhteydessä $arvot-taulukon arvoihin
 $ok = $sql->execute($arvot);
 if ( !$ok ) print_r( $sql->errorInfo() );

}

Monimutkaisemmat tulostukset

Kyselyjen kohdistuessa useampaan tauluun voi tulla kiusaus kirjoittaa silmukka, joka tekee useita hyvin samankaltaisia kyselyjä tietokantaan. Tietokanta menee kuitenkin helposti jumiin jos siihen kohdistuu kyselyjä hirvittävän nopealla tahdilla. Hyvänä perussääntönä voi pitää: minimoi tietokantaan kohdistuvien erillisten operaatioiden määrä. Yksittäisessä kyselyssä kannattaa kuitenkin tietokanta laittaa tekemään kaikki mahdolliset laskutoimitukset ja järjestämiset.

Oliot tietokantojen käsittelysssä

Tietokantataulut voidaan piilottaa olioiden taakse jolloin niiden käsittely yksinkertaistuu. Jokaista taulua kohti voi kirjoittaa oman luokan, käyttää valmista koodigeneraattoria joka tulkitsee tietokannan rakenteen ja luo valmiin koodin tai käyttää yhtä dynaamista luokkaa, joka mukautuu tarpeen mukaan. Seuraavassa tutustutaan yksinkertaiseen dynaamiseen luokaan.

Transaktiot

Transaktioiden avulla pystytään hallitsemaan tietokantaoperaatiokokonaisuuksia. Esim. Tietokantaan pitää syöttää useita tietueita peräkkäin ja jos yksikin lisäys epäonnistuu niin kaikki lisäykset pitää pystyä peruuttamaan. Transaktio varmistaa, että keskeneräisen transaktion vaikutukset tietokantaan eivät heijastu muille tietokannan käyttäjille kuin vasta transaktion hyväksymisen jälkeen.

Automaattiset avainkentät

Usein käytetään avaimina kenttiä joiden arvon keksiminen jätetään tietokannan harteille. Esim. reseptiID ja ruokalajiID ovat tällaisia kenttiä. Tähän saakka ne on keksitty itse mutta entäs jos tietokanta keksii ne:

Lisätietoa

Kannattaa tutustua Philip Greenspunin kirjaan: SQL for Web Nerds

Kurssimateriaalien käyttäminen kaupallisiin tarkoituksiin tai opetusmateriaalina ilman lupaa on ehdottomasti kielletty!
http://appro.mit.jyu.fi/sovellukset/demot/demo7/
© Jukka Mäntylä (jmantyla@mit.jyu.fi)< http://www.iki.fi/jmantyla/>
2006-04-10 12:33:48