Else Lervik 23.03.2004 Opphavsrett: Forfatter og Stiftelsen TISIP Lærestoffet er utviklet for faget LV192D Web-programmering med ASP 9. Resymé: I forrige leksjon så vi hvordan ASP kunne brukes til å vise fram innholdet i en databasetabell. I denne leksjonen skal vi se hvordan vi kan gjøre forandringer i en database. Innhold 9.1. DE FIRE DATABASEOPERASJONENE... 1 9.2. LÅSING... 2 9.3. VI GJØR ENDRINGENE I RECORDSET-OBJEKTET... 2 9.3.1. Innlegging av data... 2 9.3.2. Endring av data... 3 9.3.3. Sletting av data... 4 9.4. ET SAMMENHENGENDE EKSEMPEL... 4 Referanse til læreboka Leksjonen dekker kapittel 17 i boka. 9.1. De fire databaseoperasjonene Det er fire ting vi kan gjøre med en database: 1 Vise fram data. Dataene kan hentes fra en eller flere fysiske tabeller i databasen. Vanligvis viser vi fram et utvalg, for eksempel alle personer med navn som begynner på A og som bor i Trondheim. Dette utvalget kan gjerne være bestemt av brukeren. 2 Slette data. Man sletter hele rader i en tabell. Radene som skal slettes bør identifiseres med primærnøkkelen. 3 Legge inn nye data. Man legger alltid inn hele rader med data. Primærnøkkelen må alltid ha verdi. Øvrige felt kan ha verdi eller være tomme. Den som lager databasen kan angi at et felt er obligatorisk. Det vil ikke være tillatt å legge inn en rad med en primærnøkkelverdi som allerede eksisterer i tabellen. 4 Endre data. Man forandrer innholdet i en rad av gangen. Enkeltfelter som er blanke kan få verdi, og felter som har en verdi kan blankes ut (dersom de ikke er obligatoriske). Det er ikke god databaseskikk å endre primærnøkkelen. Da sletter man i stedet raden, og setter inn en ny.
Kravene om entydig primærnøkkel er tatt med foran. I tillegg er det krav som følger av at man i en tabell refererer til en annen tabell ved å bruke dennes primærnøkkel. Disse kravene berører både sletting, innsetting og endring, og de er dermed relativt kompliserte og ikke tatt med her. Vi skal se at vi kan utføre alle disse operasjonene direkte på Recordset-objektet. Vi husker at dette objektet er en direkte avspeiling av dataene i databasen, og dersom vi gjør endringer i dette objektet, vil databasen oppdateres umiddelbart. 9.2. Låsing Når vi nå skal begynne å forandre på dataene i databasen, må vi huske på at vi ikke er alene i verden. Vi ønsker spesielt at så mange som mulig skal bruke våre ASP-sider til å jobbe mot databasen vår. Dette har flere konsekvenser. Vi skal ta et minimum om dette i denne leksjonen, det blir mer i leksjon 10 og 11. Minimum er at når en rad i en tabell endres, så må ikke andre få lov til å endre denne raden samtidig. Dersom en rad slettes, så kan jo heller ikke andre få tilgang til den i den tidsperioden slettingen tar. Dette løses ved at den som utfører endringer på en rad, låser raden. Og er den låst, så er den låst. Andre kommer ikke til. Det er ikke så mye vi må passe på her, annet enn å sette en bestemt opsjon når vi åpner recordsettet. Resten passer databasesystemet på for oss. I forrige leksjon åpnet vi recordsettet på følgende måte: objresultat.open "person", objdbforbindelse Men, som det også ble nevnt da, Open-metoden har mange parametrer, se side 516. For at låsing skal tre i kraft må vi sette 4. parameter (locktype) lik adlockoptimistic: objresultat.open "person", objdbforbindelse,, adlockoptimistic adlockoptimistic er en konstant som har fått verdi i filen adovbc.inc. Som nevnt i forrige leksjon, denne filen inneholder mange konstanter til bruk i forbindelse med databaser, og om du ikke allerede har gjort det, bør du kopiere den til rotkatalogen for ASP ene (wwwroot). Du finner filen i katalogen \Program Files\Common Files\System\Ado (evt. søk etter filen). Dersom den ligger på wwwroot, får du tilgang til filen ved å inkludere den på følgende måte: <!-- #include virtual = "/adovbs.inc" --> 9.3. Vi gjør endringene i Recordset-objektet Vi holder oss til den kjedelige, men særdeles enkle databasen fra leksjon 8. 9.3.1. Innlegging av data La oss se på kildekode som legger inn data i person-tabellen vår: ' LeggTilPerson1.asp E.L. 2001-10-25 ' Denne filen aktiviseres av PersonForm.asp ' Option Explicit side 2 av 10
<HTML><HEAD><TITLE>Legge til data</title></head> <BODY BGCOLOR="wheat" TEXT="black" LINK="darkgreen" VLINK="steelblue" ALINK="darkblue"> <!-- #include virtual = "/adovbs.inc" --> Dim objdbforbindelse, objresultat, imaksnr, iidnr Set objdbforbindelse = Server.CreateObject("ADODB.Connection") objdbforbindelse.open "dsn=personer" Set objresultat = Server.CreateObject("ADODB.Recordset") objresultat.open "person", objdbforbindelse,, adlockoptimistic objresultat.addnew() objresultat("id") = 135 objresultat("fornavn") = "Anders" objresultat("etternavn") = "Hansen" objresultat.update() objresultat.close() objdbforbindelse.close() Set objresultat = Nothing Set objdbforbindelse = Nothing Response.Write("Nå er en person lagret i databasen") </BODY> </HTML> Kjør denne ASP en. Sjekk at Anders Hansen er lagt inn ved å bruke eksemplet fra forrige gang, eller ved å bruke Access. Hva skjer dersom du prøver å kjøre ASP en en gang til? Hva gjør vi her? 1. Først oppretter vi en ny rad i recordsettet: objresultat.addnew() 2. Deretter fyller vi denne raden med data. 3. Tilslutt ber vi om at oppdateringen gjøres gjeldende i databasen: objresultat.update() Merk at det ikke skjer endringer i databasen før trinn 3 utføres. 9.3.2. Endring av data La oss si at personen vi nettopp la inn forandrer etternavnet sitt til Haugen. Vi har recordsettet og skal forandre på raden med primærnøkkel 135. Hvordan finner vi den? Vi kan gå gjennom alle radene og sammenligne hvert enkelt id-nr med 135. Til slutt vil vi finne den, hvis den er der. Nå antar vi at vi har kjørt forrige eksempel, og da vet vi at raden er der. I stedet for at vi selv foretar søket etter person 135, kan vi la Recordset-objektet gjøre det. Dette objektet har en egenskap som lar oss filtrere ut data vi ønsker. Her ønsker vi kun den ene raden med id-nr lik 135. Vi skriver: objresultat.filter = ("id = 135") Vi kan sette opp mange ulike betingelser her. Operatorene som skal brukes er vist på side 583. Eksempler på betingelser: side 3 av 10
id > 300 and id < 500 etternavn = Hansen etternavn > 'Ols' Siste betingelse gir oss alle med etternavn som ligger etter Ols i alfabetet, for eksempel Olsen, Strand og Ås. Men tilbake til oppdateringen. Kodebiten som gjør oppdatering ser slik ut: objresultat.filter = ("id = 135") objresultat("etternavn") = "Haugen" objresultat.update() objresultat.filter = adfilternone vi nullstiller filteret for ordens skyld Låsingen av posten trer i kraft først i det Update() utføres. Fram til da er endringene bare skjedd i det lokale recordsettet. 9.3.3. Sletting av data På samme måte som for endring, må vi først finne den raden som skal slettes. Deretter utfører vi metoden Delete() på denne raden: objresultat.filter = ("ID = 135") objresultat.delete objresultat.filter = adfilternone 9.4. Et sammenhengende eksempel Det er selvfølgelig ikke videre praktisk å hardkode identifikasjonsnummeret til de radene som skal endres. Vi ønsker i stedet å la brukeren velge hvilket navn som skal endres eller slettes. For å få til dette er det enklest å bruke flere ASP-sider. For brukeren vil det nok imidlertid være mest praktisk å ha færre sider enn det vi bruker, men dette vil gi mer komplisert logikk for oss som skal programmere. Vi skal se på et sett med sider der førstesiden ser ut som følger: Figur 1: Alle registrerte personer side 4 av 10
Brukeren kan så velge om han/hun vil slette eller endre data. Da er det den valgte raden som blir berørt. Eventuelt kan data om en ny person legges inn. I tilfelle brukeren skal endre data kommer følgende vindu fram: Figur 2: Skjema for endring av den valgte personens navn Feltet for id-nr er låst, men navnet kan forandres. Dersom Lagre trykkes kommer et tredje vindu opp: Figur 3: Kvittering for endring Vi har tilsvarende ved sletting og ved innlegging av nye data. Vi skal nå gå gjennom ASPkoden som har generert sidene foran. Som øving denne gangen skal du legge inn resten av funksjonaliteten. Aller først bør du kjøre programmet foran. Du trenger følgende vedlagte filer: Personarkivet.asp - Figur 1 BehandleValg.asp - vises ikke i dette tilfellet, kun behandling av brukervalg PersonSkjema.asp - Figur 2 EndrePerson.asp - Figur 3 og du må, på grunn av include-setninger, legge dem på katalogen \wwwroot\leksjon9\dbeks\ side 5 av 10
Figur 4 viser sammenhengen mellom filene. La oss begynne med å gå gjennom førstesiden: Personarkivet.asp form action BehandleValg.asp iidnr = ikke definert strfornavn = stretternavn = behandlendefil = LeggTilPerson.asp ny include PersonSkjema.asp endre iidnr, strfornavn, stretternavn som gitt for personen behandlendefil = EndrePerson.asp include PersonSkjema.asp form action form action LeggTilPerson.asp EndrePerson.asp Figur 4: Sammenhengen mellom filene i databaseapplikasjonen. LeggTilPerson.asp skal du lage som del av øvingen. ' ' Personarkivet.asp E.L. 2001-10-24 ' Hovedside, vedlikehold av personregister Option Explicit <HTML><HEAD><TITLE>Personarkiv</TITLE></HEAD> <BODY BGCOLOR="wheat" TEXT="black" LINK="darkgreen" VLINK="steelblue" ALINK="darkblue"> <H1>Personarkiv</H1> <FORM ACTION = "BehandleValg.asp" METHOD = "post"> <!-- #include virtual = "/adovbs.inc" --> Dim objdbforbindelse, objresultat ' Oppretter forbindelse til databasen Set objdbforbindelse = Server.CreateObject("ADODB.Connection") objdbforbindelse.open "dsn=personer" ' Kopierer innholdet i tabellen person til "recordsettet" objresultat Set objresultat = Server.CreateObject("ADODB.Recordset") objresultat.open "select * from person order by id", _ objdbforbindelse,,, adcmdtext side 6 av 10
'Viser hele recordsettet i en listeboks If objresultat.eof Then Response.Write "Ingen data registrert" Else ' Første linje i listeboksen er standard valg Response.Write "<SELECT NAME = 'personliste' SIZE = 10>" Response.Write "<OPTION SELECTED>" & objresultat("id") & " " & _ objresultat("fornavn") & " " & objresultat("etternavn") objresultat.movenext() Do While Not objresultat.eof Response.Write "<OPTION>" & objresultat("id") & " " & _ objresultat("fornavn") & " " & objresultat("etternavn") objresultat.movenext() Loop Response.Write "</SELECT>" End If 'Lukker "recordsettet" og databaseforbindelsen objresultat.close() objdbforbindelse.close() Set objresultat = Nothing Set objdbforbindelse = Nothing <P> <INPUT NAME = "slett" TYPE = "submit" VALUE = "Slett"> <INPUT NAME = "ny" TYPE = "submit" VALUE = "Ny"> <INPUT NAME = "endre" TYPE = "submit" VALUE = "Endre"> </FORM> </BODY></HTML> Vi bruker en SQL-setning (se kapittel 6 i forrige leksjon) for å få recordsettet i sortert rekkefølge. Vi presenterer dataene i en listeboks der brukeren kan velge eksakt en linje. Som default setter vi at første rad i recordsettet er valgt. Nederst har vi laget en trykknapp for hver mulig operasjon. Vi har laget en egen ASP som finner ut hva brukeren har valgt og styrer videre sideframvisning etter dette: ' ' BehandleValg.asp E.L. 2001-10-25 ' Her håndterer vi det valget brukeren gjør i Personarkiv.asp Option Explicit <HTML><HEAD><TITLE>Behandler brukerens valg</title></head> <BODY BGCOLOR="wheat" TEXT="black" LINK="darkgreen" VLINK="steelblue" ALINK="darkblue"> <!-- #include virtual = "/adovbs.inc" --> Dim ipos, iidnr, ilengde Dim strvalgtperson, strfornavn, stretternavn, strbehandlendefil, arrord, iantord, iindeks Dim objdbforbindelse, objresultat side 7 av 10
' Sletter en person fra arkivet If Request.Form("slett") <> "" Then Response.Write "<STRONG>Dette er ikke implementert</strong>" End If ' Skal registrere en ny person If Request.Form("ny") <> "" Then Response.Write "<STRONG>Dette er ikke implementert</strong>" End If ' Skal endre navnet på en person If Request.Form("endre") <> "" Then strvalgtperson = Request.Form("personListe") ' Så må vi drive litt strenghåndtering for å ' skille ut idnr, etternavn og fornavn ' Vi forutsetter at disse feltene ikke er blanke ' (i samsvar med kravene i databasen) strvalgtperson = Trim(strValgtPerson) arrord = Split(strValgtPerson, " ") ' se sie 147 iidnr = arrord(0) iantord = UBound(arrOrd) strfornavn = arrord(1) For iindeks = 2 to iantord - 1 strfornavn = strfornavn & " " & arrord(iindex) Next stretternavn = arrord(iantord) ' Denne strengverdien brukes i PersonSkjema.asp strbehandlendefil = "EndrePerson.asp" <!--#include virtual = "leksjon9/dbeks/personskjema.asp" --> End If </BODY> </HTML> Sletting og innlegging av nye data er, som sagt, overlatt til deg. Vi skal se på operasjonen endring av data. Vi skal presentere eksisterende data for brukeren (figur 2). Disse dataene har vi i form av brukerens valg fra personliste: strvalgtperson = Request.Form("personListe") Her finner vi valget som en streng som består av id-nr, fornavn og etternavn, eksempel: 23 Anne Beate Vik. Vi begynner (for sikkerhets skyld) med å trimme teksten, det vil si at eventuelle blanke foran og bak fjernes. Deretter finner vi id-nummeret ved å søke etter første blanke forfra, og etternavnet ved å søke etter første blanke bakfra. Alt i mellom regner vi som fornavn, selv om noe av det kan være mellomnavn. Vi lagrer dette i variablene iidnr, strfornavn og stretternavn. Skjemaet på figur 2 bruker vi både ved innlegging av nye data og ved endring av data. Brukerne gjør sine editeringer, og skjemaet sendes til en annen ASP-fil for behandling, eksempel: side 8 av 10
<FORM ACTION="EndrePerson.asp" METHOD = "post"> Ettersom disse to operasjonene er vesensforskjellige, vil den behandlende filen ikke være den samme i de to tilfellene. Dette løser vi ved å legge navnet på denne filen i en variabel: strbehandlendefil = "EndrePerson.asp" Så inkluderer vi filen med personskjemaet, og kan dermed referere til denne variabelen der: <!--#include virtual = "leksjon9/dbeks/personskjema.asp" --> Vi bruker også variablene iidnr, strfornavn og stretternavn. Skjemaet ser slik ut: ' PersonSkjema.asp E.L. 2001-10-24 ' Denne filen inkluderes i BehandleValg.asp, dersom nye data skal ' registreres eller eksisterende data skal endres. ' ' Vi bruker ASP-variabler som er gitt verdi i BehandleValg.asp <BR><STRONG>Legg til/endre data</strong> <FORM ACTION="=strBehandlendeFil" METHOD = "post"> <TABLE> <TR> <TD ALIGN = LEFT>Id-nr:</TD> <TD ALIGN = LEFT><STRONG>=iIdnr</STRONG></TD> <INPUT TYPE = "hidden" NAME = "idnr" VALUE = "=iidnr"> </TR> <TR> <TD ALIGN = LEFT>Fornavn:</TD> <TD ALIGN = LEFT><INPUT TYPE = "text" NAME = "fornavn" SIZE = "20" VALUE = "=strfornavn"></td> </TR> <TR> <TD ALIGN = LEFT>Etternavn:</TD> <TD ALIGN = LEFT><INPUT TYPE = "text" NAME = "etternavn" SIZE = "20" VALUE = "=stretternavn"></td> </TD> </TABLE> <INPUT TYPE = "submit" NAME = "lagre" VALUE = "Lagre"> <INPUT TYPE = "reset" NAME = "reset" VALUE = "Ta bort endringer"> </FORM> Som vi ser, id-nummeret behandles litt spesielt. Det vises på skjermen, men ikke som felt, fordi brukeren skal ikke kunne forandre dette. Det trengs imidlertid i den behandlende filen, og vi overfører det dit via et skjult felt (TYPE = hidden ). Til slutt har vi filen EndrePerson.asp: ' EndrePerson.asp E.L. 2001-10-24 ' Denne filen aktiviseres av PersonForm.asp ' Option Explicit <HTML><HEAD><TITLE>Endre data</title></head> side 9 av 10
<BODY BGCOLOR="wheat" TEXT="black" LINK="darkgreen" VLINK="steelblue" ALINK="darkblue"> <!-- #include virtual = "/adovbs.inc" --> Dim objdbforbindelse, objresultat, iidnr Set objdbforbindelse = Server.CreateObject("ADODB.Connection") objdbforbindelse.open "dsn=personer" Set objresultat = Server.CreateObject("ADODB.Recordset") objresultat.open "person", objdbforbindelse,,adlockoptimistic iidnr = Request.Form("idNr") objresultat.filter = ("id = " & iidnr) objresultat("fornavn") = Request.Form("fornavn") objresultat("etternavn") = Request.Form("etternavn") objresultat.update() objresultat.filter = adfilternone objresultat.close() objdbforbindelse.close() Set objresultat = Nothing Set objdbforbindelse = Nothing <STRONG>Nå er navnet til personen nr =iidnr endret</strong> <P><A HREF = "Personarkivet.asp">Tilbake til hovedsiden</a> </BODY> </HTML> Vi slår opp på riktig person i databasen ved å filtrere ut personen med riktig id-nr. Vi legger inn det fornavnet og etternavnet som er sendt fra person-skjemaet, foretar oppdatering, nullstiller filteret og lukker databasen til slutt. side 10 av 10