Simpele Handleiding om met HTML-PHP-PostgreSQL een website te maken waarmee je informatie kunt beheren in een (PostgreSQL) Database en deze via HTML (en PHP) weer kunt tonen en kunt aanpassen.
Deze pagina laat zien hoe je een Web-Site kunt maken met HTML,
PHP en een PostgreSQL database-systeem.
We gaan een simpel systeem maken waarin je de volgende informatie
kunt bijhouden: Voornaam, Achternaam en E-mailadres.
Bezoekers van deze website zullen in staat zijn deze adresgegevens
toe te voegen en informatie uit dit systeem op te vragen, en te
wijzigen en ook weer te verwijderen (als u dat wilt).
De informatie in dit systeem zal worden opgeslagen in een PostgreSQL-Database.
Deze Database wordt bestuurt door PHP, welke op zijn beurt en
onderdeel is van uw HTML-Pagina waardoor de informatie zichtbaar
kan worden gemaakt aan de website bezoeker.
We gaan dit stap voor stap doen op een manier die het mogelijk maakt dat u als het ware mee doet en dus iets creeert wat ook zou werken. U gaat daadwerkelijk rechtstreeks werken op/met de computer (unix/linux (internet) webserver) waarop deze website moet gaan lopen.
In deze voorbeeld handleiding wordt een speciaal lettertype (en tekst kleur) gebruikt om aan te geven welke tekst de computer aan u op de terminal toont en hetgeen u dient in te typen (zie voorbeeld regel hieronder):
Dit is tekst dat de computer u toont: en dit moet u typen.
We gaan er van uit dat u toegang hebt tot een (unix/linux)
systeem met daarop een (apache) Webserver, PHP (scripttaal)en
PostgreSQL (databasesysteem).
U bezit dus een unix user-id en een bijbehorend wachtwoord.
(als voorbeeld gebruiken we als unix-User-id: uxuserid met wachtwoord:
uxwachtwoord.)
En u bent ook in het bezit van een PostgreSQL user-id en wachtwoord.
(als voorbeeld gebruiken we als PostgreSQL-User-id: pguserid met
wachtwoord: pgwachtwoord.)
Deze dient u dus te vervangen door uw eigen betreffen User-id's
en wachtwoorden.
In unix dient u na elke regel op de [Enter] of [Return] toets drukken om aan te geven dat deze regel gereed is (u dus klaar bent met typen). In dit voorbeeld geef ik niet aan waar u op Enter moet drukken, gewoon als de regel klaar is drukt u op Enter.
(het wachtwoord is niet zichtbaar als u het intypt):
Login: uxuserid uxuserid@mkux400's password: SSH: Access granted! ##################################################################### # # # Toegang alleen toegestaan voor ge-authoriseerde gebruikers # # welke alleen door de beheerder toegestaane werkzaamheden # # mogen uitvoeren. # # # # Niet ge-autoriseerde toegang zal worden bestraft !!! # # Toegang en uitgevoerde werkzaamheden worden gelogd!! # # # # Users who do not understand the Dutch language are not allowed !! # # # ##################################################################### uxuserid pts/1 Mon Apr 25 18:14 still logged in gateway.lan wtmp begins Fri Apr 1 16:24:47 2005 [uxuserid@mkux400 uxuserid]$
U bent nu aan unix aangelogd en unix is gereed om uw commando's uit te voeren.
Nu gaan we eerst de tabel maken waarin de informatie moet komen
te staan. Deze tabel komt onder het database-systeem te staan,
dus we gaan eerst hier aan aanloggen:
Op de shell-prompt (zie het $ - tekentje op het scherm) geeft
u het volgende commando: psql
(ook hier is het wachtwoord niet zichtbaar als u het intypt):
[uxuserid@mkux400 uxuserid]$ psql Password: Welcome to psql, the PostgreSQL interactive terminal. Type: \copyright for distribution terms \h for help with SQL commands \? for help on internal slash commands \g or terminate with semicolon to execute query \q to quit pguserid=>
Het systeem heeft (automatisch) aangenomen dat de unix-userid
gelijk is aan het PostgreSQL userid.
Indien u dit niet wilt kunt dit ook specificeren met: psql <database>
<userid>, waarbij u <database> vervangt door de gewenst
database-naam en <userid> door het userid waarmee u wilt
werken, zoals in ons geval:
[uxuserid@mkux400 uxuserid]$ psql pguserid pguserid Password:
U bent nu aan PostgreSQL aangelogd en PostgreSQL is gereed om uw commando's uit te voeren. (PostgreSQL heeft u een aantal handige commando's gegeven, ga hier eens me spelen om te zien wat er achter zit. U bevindt zich in uw eigen persoonlijke database (zeg maar een stuk schijfruimte) welke wordt beheerd door het database-systeem.
Als eerst kunt u het commando: \dt geven om te zien welke tabellen (dit kunt u vergelijken met kleine kaartenbakjes) er in uw persoonlijke database zijn:
pguserid=> \dt No relations found. pguserid=>
Als er geen tabellen zijn zag u het bovenstaande, zijn er wel tabellen aanwezig dan ziet u bv. dit:
pguserid=> \dt List of relations Name | Type | Owner --------------+-------+---------- deelnemers | table | pguserid organisator | table | pguserid verenigingen | table | pguserid (3 rows) pguserid=>
Nu gaan we de voorbeeld-tabel aanmaken. In deze tabel komt
dus de volgende informatie te staan:
Voornaam, Achternaam en e-mail adres.
Deze informatie als geheel noemen we in database-spreektaal een
record of row (rij).
Nu is het verstandig om elk record in een tabel een unieke identificatie te geven zodat we later een record uniek kunnen opvragen. Deze unieke identificatie kan bv. zijn PostCode + Huisnummer, of zoals in ons voorbeeld gewoon een nummer. Voor ons eigen gemak maken we gebruik van de mogelijkheid dat het database-systeem zelf een uniek nummer toekent aan elk record dat wordt toegevoegd (waarom het verstandig is om een veld (kolom) te gebruiken waarin een unieke code komt te staan zal verderop in een voorbeeld duidelijk worden gemaakt). U bent niet verplicht om een nummer als unieke identificatie te gebruiken. Wat u ook gebruikt, er moet een mogelijkheid zijn om elk record in de tabel uniek aan te kunnen wijzen. Het is ook mogelijk om een zogenaamde 'index' aan te maken die er voor zorgt dat de gespecificeerde velden in de tabel uniek blijven.
We hebben nu dus de volgende informatie nodig voor onze tabel:
uniek-nummer, voornaam, achternaam en e-mail-adres.
In database-termen worden deze informatie-eenheden 'fields' (velden
of kolommen) genoemd, en we zullen ze nu een handige naam moeten
geven, bv.
uniek-nummer wordt veld: nummer,
voornaam wordt veld: voornaam,
achternaam wordt veld: achternaam en
e-mail-adres wordt veld: e_mail.
We moeten ook nog aangeven wat voor velden het zijn, zoals
tekst velden, nummerieke velden enz.
Veld 'nummer' is een nummeriek veld (in ons geval een auto-increment of serial veld)
Veld 'voornaam' is een tekst veld met een lengte (maximaal) van 12 letters,
Veld 'achternaam' is een tekst veld met een lengte (maximaal) van 30 letters en
Veld 'e_mail' is een tekst veld met een lengte (maximaal) van 50 letters.
De naam van de tabel waarin we deze informatie gaan opslaan noemen we: voorbeeldtabel.
We hebben nu voldoende informatie om de tabel voorbeeldtabel te maken en daarin velden te definieren.
Dit gaat dmv. SQL-Commando's. Hiervan zijn er vele aanwezig. In de loop van dit voorbeeld-systeem zult u er
vele leren kennen en toepassen.
Het eerste SQL-Comando dat we gaan gebruiken is het CREATE TABLE commando.
(In SQL moet u een SQL-Commando afsluiten met een ';', hiermee geeft u aan dat het SQL-Commando nu gereed is om uit gevoerd te worden. Hierdoor is het mogelijk om zeer grote SQL-Commando's in te typen die meerdere regels lang zijn. Uw SQL Commando zal pas NA de ';' worden uitgevoerd.)
Het (volledige) SQL-commando wat we hier moeten gaan geven om de genoemde tabel aan te maken is:
create table voorbeeldtabel
(nummer serial ,
voornaam char(12) ,
achternaam char(30) ,
e_mail char(50)
);
Het volgende verschijnt:
pguserid=> create table voorbeeldtabel pguserid-> (nummer serial , pguserid(> voornaam char(12) , pguserid(> achternaam char(30) , pguserid(> e_mail char(50) pguserid(> ); NOTICE: CREATE TABLE will create implicit sequence 'voorbeeldtabel_nummer_seq' for SERIAL column 'voorbeeldtabel.nummer' NOTICE: CREATE TABLE / UNIQUE will create implicit index 'voorbeeldtabel_nummer_key' for table 'voorbeeldtabel' CREATE pguserid=>
Het commando \d (ipv. \dt) zal nu bv. het volgende laten zin:
pguserid=> \d List of relations Name | Type | Owner ---------------------------+----------+------- voorbeeldtabel | table | pguserid voorbeeldtabel_nummer_seq | sequence | pguserid (2 rows) pguserid=>
De tabel (sequence): voorbeeldtabel_nummer_seq
is een tabel die er voor zorgt dat het veld nummer altijd een unieke waarde bevat. U kunt deze (extra)
tabel verder vergeten in het normale gebruik, maar onthoudt dat hij er wel is, bv. als
u de tabel voorbeeldtabel weggooit zult u ook de voorbeeldtabel_nummer_seq
expliciet moeten weggooien.
Deze (Sequence) tabel: voorbeeldtabel_nummer_seq
bevat een index die er voor zorgt dat het veld 'nummer' altijd
unieke waarden bevat. Een dergelijke index kunt u ook zelf aanmaken.
We hebben nu een tabel met de naam voorbeeldtabel met daarin de genoemde velden. Maar is dit wel zo??,
we gaan eens opvragen wat er in de tabel voorbeeldtabel zit.
Hiertoe geven we een ander (ons tweede) SQL-Commando, en wel een commando dat in 90% van de gevallen
zal worden gebruikt, het SELECT-commando (om alles in een keer op te vragen typ: select * from voorbeeldtabel;):
pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+----------+------------+-------- (0 rows) pguserid=>
Wow, we hebben iets, maar verder ook niet.. (De kolomen zijn aanwezig, maar er is (nog) geen informatie aanwezig, we hadden alles op gevraagd en 0 rijen gekregen..)
Hieraan moeten we iets doen, we gaan een derde SQL-Commando gebruiken: het INSERT INTO commando.
We gaan de volgende informatie in de tabel opnemen:
uw voornaam, uw achternaam en uw e-mail adres.
Het SQL-commando hiervoor is:
insert into voorbeeldtabel (voornaam,achternaam,e_mail)
values('uw voornaam','uw achternaam','uw e-mail adres') ;
pguserid=> insert into voorbeeldtabel (voornaam,achternaam,e_mail) pguserid-> values('uw voornaam','uw achternaam','uw e-mail adres'); INSERT 24977 1 pguserid=>
Nadat u het insert-commando gaf kreeg u het volgende antwoord van PostgreSQL: INSERT 24977 1
Hiermee geeft PostgreSQL aan wat het effect van uw commando is geweest. Het was een INSERT-commando,
(het grote getal: 24977, welke alleen bij een INSERT wordt getoont, kunt u vergeten/overslaan),
en er werd 1 record toegevoegd (een commando kan namelijk ook tot gevolg hebben dat er veel meer dan
1 item tegelijk gewijzigd kan worden). Het grote getal kan soms met grote sprongen omhoog
gaan, dit komt omdat u niet de enige gebruiker van een PostgreSQL-database
bent, maar dat er ook andere gebruikers zijn die INSERT's uitvoeren.
Indien we nu weer alles gaan opvragen (middels het SQL-Commando: select * from voorbeeldtabel; ) zien we het volgende:
pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+--------------+--------------------------------+---------------------------------------------------- 1 | uw voornaam | uw achternaam | uw e-mail adres (1 row) pguserid=>
Zoals u kunt zien staat uw ingetype naam nu werkelijk in de tabel (uw database) en heeft het ook daadwerkelijk een nummer gekregen. Maar 1 rij is wel een beetje weinig vindt u ook niet, vandaar dat we er nog twee (als voorbeeld) gaan toevoegen. (U mag natuurlijk zelf naar hartelust meerdere namen (rijen/records) toevoegen, dit voorbeeldsysteem gaat echter in eerste instantie uit van deze 3 rijen):
insert into voorbeeldtabel (voornaam,achternaam,e_mail)
values('Martie','Krukkeland','martiekr@worldonline.nl') ;
insert into voorbeeldtabel (voornaam,achternaam,e_mail)
values('De Laatste','Derde Achternaam','En nog een E-mail adres')
;
pguserid=> insert into voorbeeldtabel (voornaam,achternaam,e_mail) pguserid-> values('Martie','Krukkeland','martiekr@worldonline.nl') ; INSERT 24978 1 pguserid=> insert into voorbeeldtabel (voornaam,achternaam,e_mail) pguserid-> values('De Laatste','Derde Achternaam','En nog een E-mail adres') ; INSERT 24979 1
Nu gaan we natuurlijk ook weer even kijken wat het inmiddels
is geworden
(weer met het SQL-Commando: select * from voorbeeldtabel; )
pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+--------------+--------------------------------+---------------------------------------------------- 1 | uw voornaam | uw achternaam | uw e-mail adres 2 | Martie | Krukkeland | martiekr@worldonline.nl 3 | De Laatste | Derde Achternaam | En nog een E-mail adres (3 rows) pguserid=>
Het commando ziet er ongeveer (simpel voorgestelt) zo uit:
INSERT INTO <TabelNaam>
(Veldenlijst, gescheiden door een komma)
VALUES(<de Waarden in de betreffende Velden>,<Ook gescheiden
door een Komma>) ;
Onze tabel heeft de volgende velden: voornaam,achternaam,e_mail , deze noemen
we dus in de Veldenlijst. U hoet ze niet allemaal op te noemen,
velden die u niet noemt krijgen geen waarde en zullen dus 'leeg'
zijn na het invoegen van de rij.
U mag ook elke willekeurige veldenvolgorde aanhouden, dit maakt
niets uit, echter bedenk wel dat de juiste data in het gewenste
veld komt..
Hierna komt de VALUES (waarden) opdacht die opgeeft bepaald welke
waarde er in het betreffende veld moet komen te staan. de waarden
voor teks-velden zet u ALTIJD tussen quotjes, nummerieke velden
zijn gewoon het getal. U kunt een getal plaatsen in een tekst-veld
door het dus tussen quotjes te zetten. Een tekst in een nummeriek
veld zetten gaat niet.
U mag SQL-Commando ook met een gerust hart over meerdere regels
uitschrijven, dit maakt PostgreSQL niets uit:
insert
into
voorbeeldtabel
(
voornaam,
achternaam,
e_mail
)
values
(
'aaaaa',
'bbbb',
'ccccc'
)
;
werkt ook, dus:
pguserid=> insert pguserid-> into pguserid-> voorbeeldtabel pguserid-> ( pguserid(> voornaam, pguserid(> achternaam, pguserid(> e_mail pguserid(> ) pguserid-> values pguserid-> ( pguserid(> 'aaaaa', pguserid(> 'bbbb', pguserid(> 'ccccc' pguserid(> ) pguserid-> ; INSERT 24980 1
is perfect, we hebben nu dus 4 records (rijen)..
pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+--------------+--------------------------------+---------------------------------------------------- 1 | uw voornaam | uw achternaam | uw e-mail adres 2 | Martie | Krukkeland | martiekr@worldonline.nl 3 | De Laatste | Derde Achternaam | En nog een E-mail adres 4 | aaaaa | bbbb | ccccc (4 rows) pguserid=>
Nu gaan we een beetje spelen met de SQL-Commando SELECT.
De SQL-SELECT Commano's noemen we Query's (Vragen aan een Database-Systeem).
SQL betekend: Structured Query Language. SQL is dus een Vraag-Taal..
We gaan eerst bv. opvragen welke voornamen er in onze tabel zitten,
dit doen we met: select voornaam from voorbeeldtabel ; )
pguserid=> select voornaam from voorbeeldtabel ; voornaam -------------- uw voornaam Martie De Laatste aaaaa (4 rows) pguserid=>
Nu hebben we ipv. het sterretje ('*') een veldnaam gevraagt,
hetgeen dus betekend dat een '*' ALLE velden tegelijk is.
Zou dit ook werken: select nummer,achternaam from voorbeeldtabel;
?
pguserid=> select nummer,achternaam from voorbeeldtabel ; nummer | achternaam --------+-------------------------------- 1 | uw achternaam 2 | Krukkeland 3 | Derde Achternaam 4 | bbbb (4 rows) pguserid=>
Ja dus, dit werkt ook. Nu gaan we nog een stap verder, ik wil
niet alles zien, maar ik wil alleen het e-mail adres zien van
'Martie' (=voornaam). Dit kan met het SQL-Commando: select e_mail
from voorbeeldtabel where voornaam = 'Martie' ;
het volgende kan natuurlijk ook om korte regels te houden en een
overzichtelijk SQL-Commando te krijgen:
select e_mail
from voorbeeldtabel
where voornaam = 'Martie' ;
pguserid=> select e_mail pguserid-> from voorbeeldtabel pguserid-> where voornaam = 'Martie' ; e_mail ---------------------------------------------------- martiekr@worldonline.nl (1 row) pguserid=>
Dit zijn nog maar enkele simpele voorbeelden, wist u dat een SQL-Commando meer honderden regels lang kan zijn, een dergelijk Commando zijn informatie uit meerdere tabellen tegelijk kan halen, en uiteindelijk berekent hoeveel winst er gemaakt??.
Hieronder staat een voorbeeld van een dergelijk groot SQL-SELECT Commando. Deze gebruik ik (Martie) in een Concours-Programma (om de organisatie van een paarden/ponies Concours-Hippique te kunnen automatiseren) om in een keer de Verenigingen-Lijst te kunnen afdrukken met alle relevante gegevens, gegroepeert per VerenigingNummer. Het maakt binnen de SELECT weer gebruik van Sub-Query's (die op zich zelf ook weer SQL-SELECT-Commando's zijn), een van deze sub-query's heet bv.: DressuurTweedeKosten, deze sub-query berekent bv. de kosten van de tweede dressuurproef van een bepaalde deelnemer. Tevens maakt het gebruik van 2 tabellen: Deelnemers en Verenigingen. De Sub-Query's zelf maken ook gebruik van een aantal andere tabellen oa.: VraagProgramma en Uitslagen (bevat ook starttijden) om de aanvullen informatie te kunnen leveren (Kosten en Starttijdstippen).
SELECT " & _ Deelnemers.CombiNr, Deelnemers.DeelnemerNr, Deelnemers.DoetMee, Deelnemers.DlnmrNaam , Deelnemers.RijdierNaam,Deelnemers.VerenigingNr, Deelnemers.EersteDressuurProef, Deelnemers.EersteDressuurProefSpec, Deelnemers.EersteDressuurRubriek, Deelnemers.TweedeDressuurProef, Deelnemers.TweedeDressuurProefSpec, Deelnemers.TweedeDressuurRubriek, Deelnemers.EersteSpringProef, Deelnemers.EersteSpringProefSpec, Deelnemers.EersteSpringRubriek, Deelnemers.TweedeSpringProef, Deelnemers.TweedeSpringProefSpec, Deelnemers.TweedeSpringRubriek, Deelnemers.OverigeKosten, Deelnemers.BetaaldBedrag, Deelnemers.ProefKosten, Deelnemers.CouponsIngeleverd , Deelnemers.Catagorie, Verenigingen.VerenigingNr as VerenigingNr, Verenigingen.Ver_Afk, Verenigingen.VerenigingNaam, Verenigingen.VerenigingPlaats, Verenigingen.ContactNaam, Verenigingen.ContactAdres, Verenigingen.ContactPostCode, Verenigingen.ContactPlaatsNaam, Verenigingen.KomtVanVer, DressuurEersteKosten.Proefnaam, DressuurEersteKosten.DeelnameKosten, DressuurTweedeKosten.Proefnaam, DressuurTweedeKosten.DeelnameKosten, SpringEersteKosten.Proefnaam, SpringEersteKosten.DeelnameKosten, SpringTweedeKosten.Proefnaam, SpringTweedeKosten.DeelnameKosten , iif(DressuurEersteKosten.DeelnameKosten>0,DressuurEersteKosten.DeelnameKosten,0) + iif(DressuurTweedeKosten.DeelnameKosten>0,DressuurTweedeKosten.DeelnameKosten,0) + iif(SpringEersteKosten.DeelnameKosten>0,SpringEersteKosten.DeelnameKosten,0) + iif(SpringTweedeKosten.DeelnameKosten>0,SpringTweedeKosten.DeelnameKosten,0) as DlnTot, DressuurEersteTijdstip.Tijdstip, DressuurTweedeTijdstip.Tijdstip, SpringEersteTijdstip.Tijdstip, SpringTweedeTijdstip.Tijdstip FROM (((((((( Deelnemers LEFT JOIN Verenigingen ON Deelnemers.VerenigingNr = Verenigingen.VerenigingNr) LEFT JOIN DressuurEersteKosten ON Deelnemers.EersteDressuurProef = DressuurEersteKosten.ProefNaam) LEFT JOIN DressuurTweedeKosten ON Deelnemers.TweedeDressuurProef = DressuurTweedeKosten.ProefNaam) LEFT JOIN SpringEersteKosten ON Deelnemers.EersteSpringProef = SpringEersteKosten.ProefNaam) LEFT JOIN SpringTweedeKosten ON Deelnemers.TweedeSpringProef = SpringTweedeKosten.ProefNaam) LEFT JOIN DressuurEersteTijdstip ON (Deelnemers.EersteDressuurRubriek = DressuurEersteTijdstip.Rubriek) AND (Deelnemers.DeelnemerNr = DressuurEersteTijdstip.DeelnemerNr)) LEFT JOIN DressuurTweedeTijdstip ON (Deelnemers.TweedeDressuurRubriek = DressuurTweedeTijdstip.Rubriek) AND (Deelnemers.DeelnemerNr = DressuurTweedeTijdstip.DeelnemerNr)) LEFT JOIN SpringEersteTijdstip ON (Deelnemers.EersteSpringRubriek = SpringEersteTijdstip.Rubriek) AND (Deelnemers.DeelnemerNr = SpringEersteTijdstip.DeelnemerNr)) LEFT JOIN SpringTweedeTijdstip ON (Deelnemers.TweedeSpringRubriek = SpringTweedeTijdstip.Rubriek) AND (Deelnemers.DeelnemerNr = SpringTweedeTijdstip.DeelnemerNr) WHERE DOETMEE;
Dit soort grote query's zult u waarschijnlijk nooit hoeven te maken, maar u kunt nu zien wat er mogelijk is. (Ik ga ook niet proberen om uit te leggen waarom dit SQL-Commando doet wat het moet doen, dit zou op zich al voldoende informatie opleveren om een boek te schrijven over het maken van SQL-Queries en die zijn wel te vinden in de bibliotheek. Bovenstaande query is trouwens gemaakt dmv. de SQL-Query-wizard in Ms-Access die de basis legde en daarna handmatig aangevult om bovenstaande te verkrijgen daar de Ms-Access (97) wizard niet krachtig genoeg is om dit te kunnen maken ..)
Zoals u hiervoor hebt kunnen lezen zou ik nog uitleggen waarom het zeer aan te bevelen is om elke tabel te
voorzien van een kolom waarin een waarde kan worden geze die elk record een unieke identificatie geeft.
Hiertoe gaan we eerst een record toevoegen die ongeveer lijkt op ons laatse record (4):
insert into voorbeeldtabel (voornaam,achternaam,e_mail) values('ababa','bbbb','ccccc');
pguserid=> insert into voorbeeldtabel (voornaam,achternaam,e_mail) values('ababa','bbbb','ccccc'); INSERT 33162 1 pguserid=>
Nu gaan we de records opvragen waarbij we bewust aannemen dat we geen unieker (nummer) kolom hebben. :
pguserid=> select voornaam,achternaam,e_mail from voorbeeldtabel; voornaam | achternaam | e_mail --------------+--------------------------------+---------------------------------------------------- uw voornaam | uw achternaam | uw e-mail adres Martie | Krukkeland | martiekr@worldonline.nl De Laatste | Derde Achternaam | En nog een E-mail adres aaaaa | bbbb | ccccc ababa | bbbb | ccccc (5 rows) pguserid=>
We hebben nu dus 5 records, en we doen net dat we een fout gaan verbeteren en nemen dus aan dat de
voornaam van 'aaaaa' had moeten zijn: 'ababa' en de het e_mail adres van 'ababa' moet 'ddddd' worden.
We geven dus de volgende SQL-Update commando's:
update voorbeeldtabel set voornaam='ababa' where voornaam='aaaaa';
update voorbeeldtabel set e_mail='ddddd' where voornaam='ababa';
pguserid=> update voorbeeldtabel set voornaam='ababa' where voornaam='aaaaa'; UPDATE 1 pguserid=> update voorbeeldtabel set e_mail='ddddd' where voornaam='ababa'; UPDATE 2 pguserid=> select voornaam,achternaam,e_mail from voorbeeldtabel; voornaam | achternaam | e_mail --------------+--------------------------------+---------------------------------------------------- uw voornaam | uw achternaam | uw e-mail adres Martie | Krukkeland | martiekr@worldonline.nl De Laatste | Derde Achternaam | En nog een E-mail adres ababa | bbbb | ddddd ababa | bbbb | ddddd (5 rows) pguserid=>
Bij de tweede update zag u al iets vreemd, er werden 2 records tegelijk gewijzigd, terwijl er dus maar 1 gewijzigd had moeten worden. Na de select is duidelijk waarom: de eerste Update veranderde de voornaam in 'ababa', waardoor er nu dus 2 voornamen 'ababa' in de tabel aanwezig zijn (de nieuwe en de oude) en de tweede update dus alle twee de records gebruikt om het e_mail adres te wijzigen. Hoe kunnen we er nu voor zorgen dat we bij SQL-Command's deze laatste 2 records (rijen) weer verschillend zijn?? Hiervoor is een truukje, met een aangepaste SQL-Opdracht kunt u regel dat u de wijzigingen/selects alleen op bv. het eerste record uitvoert, maar dit zou te ver voeren om te behandelen, wil je het weten, vraag het dan gewoon aan mij (er is bijvoorbeeld een SQL LIMIT parameter)..
Om dit soort problemen te voorkomen moet u dus een kolom in een tabel opnemen waarin een nunieke waarde komt te staan:
pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+--------------+--------------------------------+---------------------------------------------------- 1 | uw voornaam | uw achternaam | uw e-mail adres 2 | Martie | Krukkeland | martiekr@worldonline.nl 3 | De Laatste | Derde Achternaam | En nog een E-mail adres 5 | ababa | bbbb | ddddd 4 | ababa | bbbb | ddddd (5 rows) pguserid=>
Om te testen voegen we nog een record toe:
pguserid=> insert into voorbeeldtabel (voornaam,achternaam,e_mail) values('ababa','bbbb','ccccc'); INSERT 33163 1 pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+--------------+--------------------------------+---------------------------------------------------- 1 | uw voornaam | uw achternaam | uw e-mail adres 2 | Martie | Krukkeland | martiekr@worldonline.nl 3 | De Laatste | Derde Achternaam | En nog een E-mail adres 5 | ababa | bbbb | ddddd 4 | ababa | bbbb | ddddd 6 | ababa | bbbb | ccccc (6 rows) pguserid=>
Nu is het wel makkelijk, want de kolom 'nummer' is ALTIJD uniek, dus het simpel weggooien van de laatste rij doen we met: delete from voorbeeldtabel where nummer=6 ;
pguserid=> delete from voorbeeldtabel where nummer=6; DELETE 1 pguserid=>
En weer opvragen wat we nu over hebben:
pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+--------------+--------------------------------+---------------------------------------------------- 1 | uw voornaam | uw achternaam | uw e-mail adres 2 | Martie | Krukkeland | martiekr@worldonline.nl 3 | De Laatste | Derde Achternaam | En nog een E-mail adres 5 | ababa | bbbb | ddddd 4 | ababa | bbbb | ddddd (5 rows) pguserid=>
In bovenstaande voorbeelden hebben we ook al even kort gewerkt met de SQL-UPDATE en SQL-DELETE opdrachten.
Deze opdrachten brengen wijzigingen (UPDATE) aan in de tabel of verwijderen reocrds uit de tabel (DELETE).
Bij de UPDATE vertelt u welke velden welke nieuwe waarde moeten krijgen waarbij de WHERE vertelt welke records
(rijen) deze wijzigingen moeten krijgen.
Bij de DELETE vertelt u weer via de WHERE welke rijen er verwijderd moeten worden. Dus bij de SELECT,
UPDATE en DELETE is de WHERE heel belangrijk, hiermee geeft u aan welke rijen er betrokken moeten worden
bij het commando.
Als u zou besluiten de WHERE niet te gebruiken zou uw opdracht betrekking hebben op de gehele tabel!!
Het DELETE commando is het eenvoudigst: DELETE FROM<TabelNaam>
WHERE <Welke Records> ;
Of zoals we hierboven bv. al hebben gezien met het verwijderen van Record Nummer 6:
pguserid=> delete from voorbeeldtabel where nummer=6; DELETE 0 pguserid=>
"DELETE 0"?? Oh ja, we hadden hem al weggegooit, dus nu 0 records (rijen) verwijderd (Nummer 6 bestond al niet meer).
Bij een UPDATE gaan we dus eerste vertellen welke velden welke nieuwe waarde moeten krijgen, en daarna
weer de WHERE, dus een update is:
UPDATE <tabelNaam> SET <VeldNaam1>=<NieuweWaarde1>
WHERE <Welke Records>.
UPDATE <tabelNaam> SET <VeldNaam1>=<NieuweWaarde1>,<VeldNaam2>=<NieuweWaarde2>,
enz WHERE <Welke Records>.
Dus als we record nummer 5 willen updaten, zodat de VoorNaam wordt: 'aaaaa' en het e_mail adres moet
worden: 'ccccc', dan kunnen we dit met een UPDATE-commando doen of met twee UPDATE commando's, ik zal ze beide
laten zien, maar probeer met een UPDATE zoveel mogelijk velden in een keer te wijzigen:
De update met 2 Commando's (zoveel mogelijk voorkomen):
update voorbeeldtabel set voornaam = 'aaaaa' where nummer =
5 ;
update voorbeeldtabel set e_mail = 'ccccc' where nummer = 5 ;
of met een update commando, (de beste manier):
update voorbeeldtabel set voornaam = 'aaaaa', e_mail = 'ccccc' where nummer = 5 ;
Als we het nu ook nog mooi uitschrijven krijgen we het volgende:
pguserid=> update voorbeeldtabel pguserid-> set voornaam = 'aaaaa', e_mail = 'ccccc' pguserid-> where nummer = 5 ; UPDATE 1 pguserid=> select * from voorbeeldtabel; nummer | voornaam | achternaam | e_mail --------+--------------+--------------------------------+---------------------------------------------------- 1 | uw voornaam | uw achternaam | uw e-mail adres 2 | Martie | Krukkeland | martiekr@worldonline.nl 3 | De Laatste | Derde Achternaam | En nog een E-mail adres 4 | ababa | bbbb | ddddd 5 | aaaaa | bbbb | ccccc (5 rows) pguserid=>
En zie, de voornaam en het e_mail adres van record 5 zijn geworden zoals wij dat hadden gevraagd.
Nu mag u zelf proberen de laatse twee records (4 + 5) te verwijderen. Het kan met 2 DELETE commando's maar
ook met 1 DELETE commando (hint: achternaam is bij beide records het zelfde)..
Nu hebben we de basis vaardigheden van het Database(Tabel)Ontwerp en gebruik onder de knie. Probeer zelf ook eens Records toe te voegen, op te vragen, te wijzigen en weer te verwijderen, zodat u een gevoel krijgt hoe u met SQL uw informatie in een tabel kunt beheren. U dient altijd te eindigen met alleen de eerste 3 hierboven getoonde records, want het vervolg van dit voorbeeld is hierop gebasseerd.
Indien u er niet meer uit komt, kunt u met:
drop table voorbeeldtabel ;
drop sequence voorbeeldtabel_nummer_seq ;
uw 'rommel' op ruimen en weer van voren af aan beginnen (zie Eerste Commando's en Tabel Maken enz.)
We gaan nu het zichtbare deel van ons voorbeeldsysteem maken, de HTML-Pagina die in de browser zal
worden getoont na het intypen van ons web-adres.
(Een volledig voorbeeld van dit voorbeeldsysteen is hier te vinden: show.)
Deze eerste pagina heeft in de internet-wereld altijd de volgende naam: index. Als bestandsextentie
kunnen we bv. kiezen uit "htm", "html", "php", "asp" enz.
De extentie bepaald hoe er met het betreffende bestand om moet worden gegaan. 'HTML' geeft aan dat het om
een 'statische' pagina gaat, dwz. deze pagina zal er na 10 jaar nog steeds het zelfde uitzien. Wij gaan echter
een 'dynamische' pagina maken, een pagina die er dus iederen keer als we hem bekijken anders kan zijn (er
kunnen namelijk namen bij zijn gekomen, namen zijn veranderd of namen zijn verwijderd).
Ik kies hier voor de naam index.html. Bij het openen van de genoemde link zal dus het bestand: index.html
worden geopend. Hier merkt u niets van, dit wordt door de webserver gedaan van de unix-machine waar deze pagina
op staat. Verdop gaan ze deze van naam veranderen als we daadwerkelijk informatie uit onze database-tabel willen
gaan halen omdat we dan de pagina 'dynamisch' gaan maken.
We beginnen met het maken van de totaal-lijst van onze tabel.
Deze pagina ziet er zo uit (zonder data er in):
Voornaam | Achternaam | E-mail adres |
---|---|---|
Niet erg schokkend toch? De lege velden onder de kopregel gaan we later vullen met de namen vanuit onze
voorbeeld-database-tabel.
Hoe hebben we deze pagina gemaakt?, hieronder staat code om deze pagina te kunnen maken (deze code staat
dus in het 'index.html' bestand):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <META NAME="GENERATOR" CONTENT="Code-genie/Notepad"> <TITLE>Hoe maak ik een dynamische Website.</TITLE> </HEAD> <BODY> <H1>Informatie in onze Voorbeeld database:</H1> <TABLE border='1'> <TR> <TH>Voornaam</TH><TH>Achternaam</TH><TH>E-mail adres</TH> </TR> <TR> <TD> </TD><TD> </TD><TD> </TD> </TR> </TABLE> </BODY> </HTML>
Een html-pagina bestaat minimaal uit het volgende (zeg maar de basis) regels:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>Hoe maak ik een dynamische Website.</TITLE> </HEAD> <BODY> </BODY> </HTML>
De rest voegen we zelf toe om daadwerkelik iets te kunnen zien. In HTML draait alles om de zgn.
'TAG's'. TAG's zijn de woordjes met de '<' en de '>' er voor en er na. Deze bepalen hoe de tekst
moet worden getoont. Er zijn er een groot aantal van, op onze voorbeeld pagina ('index.html') staan
er al 20 (tel ze hierboven maar).
Was het je al opgevallen dat een groot aantal hiervan in 'paren' voorkomen: (zoals: <TH> en
</TH>)? Dit omdat tags bijna altijd een tekstblok omsluiten, je hebt dus een open-tag en een
sluit-tag. De TAG's mogen worden geschreven in hoofdletters en in kleine letters, dit maakt niet uit,
maar voor de leesbaarheid geef ik de voorkeur aan hoofdletters.
Bv. de volgende html-regel:
Dit is een html-regel met een <B>vette</B> en <I>schuine</I> tekst er in.
zal er zo uit komen te zien:
Dit is een html-regel met een vette en schuine tekst er in.
De TAG-paren: "<B>" en "</B>" zullen de tekst er tussen in vet
(=Bold) afdrukken en
de TAG-paren: "<I>" en "</I>" zullen de tekst er
tussen in schuin-schrift (=Italic) afdrukken.
Nu gaan we onze pagina 'index.html' hernoemen naar 'index.php' omdat we nu code gaan
inbouwen om informatie uit een database-tabel te kunnen halen.
Dit omdat we de programmeertaal 'PHP' gaan gebruiken om contact te leggen met onze voorbeeld-database en
daar informatie uit gaan halen. De programmeertaal 'PHP' staat gewoon als tekst in een HTMl-Pagina, en
ogenschijnlijk is er geen verschil. Echter omdat 'PHP' geen 'HTML' is hebben we het (index.html) bestand
een andere naam gegeven zodat we gelijk hennen zien dat we hier niet te maken hebben met een statische
HTML pagina maar met een dynamische pagina. Ook heeft dit het voordeel dat de webserver direct weet dat het
nu iets anders moet doen met de tekst die in deze pagina staat. Echter: bij een correct ingestelde
webserver zal ook deze geen probleem hebben met de naam en ook een 'html' pagina met php code
er in correct verwerken.
Omdat de html-code (zie hierboven) een ander doel heeft dan de code die we gaan toevoegen om de informatie uit een database-tabel te halen, ga ik deze in twee kleuren tonen. De HTML-code toon ik in ' donker-groen' en de PHP-Code toon ik in 'licht-paars'.
Als eerste gaan we een pagina maken die de verbinding met onze Database maakt. Hierin komt dus te staan:
het user-id en het wachtwoord van onze database-account (pguserid met het daarbij behorende wachtwoord).
Deze pagina geven de bijvoorbeeld de naam: xxConnect.php.
de inhoud van deze pagina ziet er zo uit:
<?php $pgConnection=pg_connect("host=localhost dbname=pguserid user=pguserid password=pgwachtwoord"); ?>
Nu zult u denken, maar het wachtwoord staat leesbaar in het bestand, dat is toch niet veilig??. Maar
probeert u maar eens dit bestand te openen in uw webbrowser, dan zult u zien dat het toch wel veilig is:
show/xxConnect.php
Het is gewoon een lege pagina, geen enkele informatie er in. Alleen al het feit dat u een lege pagina krijgt beteketn dat alle werkt zioals het zou moeten, zelfs de connect naar de database ging goed. probeert u maar een een foutief wachtwoord in het bestand te zetten en zie wat er dan gebeurt:
Warning: pg_connect() unable to connect to PostgreSQL server: FATAL 1: Password authentication failed for user "pguserid" in /var/www/html/martie/voorbeeld-systeem/show/xxConnect.php on line 2
Hieraan ziet u dat er wel degelijk iets is gebeurt bij het openen van dit bestand. Maar deze pagina hoort ook nooit op deze manier te worden geopent, dit alleen als test om te controleren of de database-connect werkt (en hij werkt dus).
Hoe ziet de webserver nu wat HTML-code is en wat PHP-code is? Wel: de truuk is: alles wat tussen de '<?php'
en de '?>' tags staat wordt behandeld als PHP-code.
vandaar ook dat onze xxConnect.php pagina deze twee tags heeft, standaard wordt elke pagina gezien als een
HTML-Pagina. Met deze twee TAG's geven we aan dat er ook een stuk PHP-Code verwerkt moet worden. Daarom zagen
we ook niets bij het rechtstreeks openen, er staat geen HTML-tekst in, alleen PHP-Code en dit wordt
nooit getoont.
Nu gaan we deze code opnemen in onze 'index.php' bestand en tegelijk alle records uit onze database ophalen
(we tonen ze nog niet!!).
Met het PHP 'require' commando kunnen we een andere HTML-Pagina invoegen in deze pagina. Na de 'require' hebben
we dus een connect met de database.
Het betreffende 'index.php' bestand ziet er dan zo uit.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <META NAME="GENERATOR" CONTENT="Code-genie/Notepad"> <TITLE>Hoe maak ik een dynamische Website.</TITLE> </HEAD> <BODY> <H1>Informatie in onze Voorbeeld database:</H1> <TABLE border='1'> <TR> <TH>Voornaam</TH><TH>Achternaam</TH><TH>E-mail adres</TH> </TR> <?php require("xxConnect.php"); $Query = "select * from voorbeeldtabel;"; $tabelinfo = pg_query($pgConnection, $Query ); for ($i = 0; $i < pg_num_rows($tabelinfo); $i++) { $row = pg_fetch_object($tabelinfo, $i); } ?> <TR> <TD> </TD><TD> </TD><TD> </TD> </TR> </TABLE> </BODY> </HTML>
Er is aan de werking nog steeds niets verandert, de browser stoont nog steeds ons vertrouwde beeld met de 3 lege velden. Maar (onzichtbaar) zijn alle records al opgehaalt. We hebben met een "Select * from voorbeeldtabel" werkelijk de alle records opgehaald (en ze in de 'for' lus 1 voor 1 bekeken). Met een 'for' lus kunnen we een bepaalde handeling (of handelingen) herhaaldelijk uitvoeren. De handelingen die wij hierboven hebben verricht is elk record (=pg_num_rows) 1 voor 1 'bekijken' (=pg_fetch_object), maar verder deden we nog niets. daar gaan we nu verandering in brengen, we geen de 'bekeken' records nu daadwerkelijk tonen.
Hiertoe passen we onze 'index.php' aan zodat het er nu zo uitziet:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <META NAME="GENERATOR" CONTENT="Code-genie/Notepad"> <TITLE>Hoe maak ik een dynamische Website.</TITLE> </HEAD> <BODY> <H1>Informatie in onze Voorbeeld database:</H1> <TABLE border='1'> <TR> <TH>Voornaam</TH><TH>Achternaam</TH><TH>E-mail adres</TH> </TR> <?php require("xxConnect.php"); $Query = "select * from voorbeeldtabel;"; $tabelinfo = pg_query($pgConnection, $Query ); for ($i = 0; $i < pg_num_rows($tabelinfo); $i++) { $row = pg_fetch_object($tabelinfo, $i); echo "<TR>\n"; echo " <TD>$row->voornaam</TD>\n"; echo " <TD>$row->achternaam</TD>\n"; echo " <TD>$row->e_mail</TD>\n"; echo "</TR>\n"; } ?> </TABLE> </BODY> </HTML>
Zoals u waarschijnlijk heeft gezien hebben we de HTML-TAG's <TR>,<TD>,</TD> en </TR> verplaatst naar binnen de 'for' lus. Wat we hier dus doen is de veld-informatie van elk 'bekeken' (=in $row) record tonen (met 'echo') binnen een HTML-Tag (<TD> en </TD>). U merkt waarschijnlijk op dat PHP dus feitelijk HTML-Code afdrukt. En dat is ook zo, alles wat u met het PHP commando 'echo' afdrukt wordt in uw browser als HTML-Code getoont.