Kapitel 5 Databaser og ASP

En af de mest udbredte anvendelser af ASP er til præsentation af data, der ligger i en database. I dette kapitel vil det blive beskrevet, hvordan man fra ASP kan tilgå data i en database. Databaseforespørgslerne er baseret på SQL, og kapitlet starter derfor med en kort introduktion til SQL-sproget.

Dernæst bliver det gennemgået, hvordan man opretter forbindelse til sin database fra ASP, hvorefter det beskrives, hvordan man læser oplysninger fra en database, og hvordan man gemmer oplysninger i en database.

I eksemplerne i denne bog bruges Microsoft Access 2000 som database, men fremgangsmåden er den samme uafhængigt af databasen. Microsoft Access 2000 er valgt, fordi den er let at bruge, forholdsvis udbredt og billig i forhold til større serverbaserede løsninger som Oracle og Microsoft SQL Server.

Du læser en gammel bog

Den bog, du læser her, er fra 1999, og mange ting kan have ændret sig siden da.
Vi håber, at du stadig kan finde relevant information i den.
Hvis du vil læse aktuelle oplysninger om den aktuelle version af ASP.NET, anbefaler vi
bogen Programming ASP.NET 4.0

Introduktion til SQL

Dette afsnit er en gennemgang af de grundlæggende kommandoer i SQL-sproget. Har man ikke i forvejen kendskab til SQL, kan afsnittet bruges til at lære de mest basale elementer af sproget. Kender man SQL i forvejen, kan man bruge dette afsnit til opslag, hvis man får behov for at få opfrisket sin hukommelse på enkelte punkter.

Gennemgangen er opbygget som en oversigt over de mest anvendte kommandoer. Det drejer sig om kommandoer til oprettelse af en tabel, indsættelse af data, søgning, opdatering og sletning. Der gives en kort beskrivelse af hver enkelt kommando og dens syntaks, ligesom det bliver gennemgået, hvilke parametre der kan bruges med den. Der bliver også givet et eksempel til hver enkelt kommando.

Fælles for alle kommandoerne er, at de består af nogle reserverede ord, som udgør selve kommandoen, og referencer til elementer i databasen – eksempelvis tabeller og kolonner.

Oprettelse af en tabel

Til at oprette en tabel bruges kommandoen CREATE TABLE. Syntaksen for denne kommando er

 

CREATE TABLE [bruger.]tabel ( {kolonne type [begrænsning]} [, {kolonne type [begrænsning]} ] . . .) [AS forespørgsel]

 

Parameteren bruger angiver den bruger, tabellen skal oprettes under. Tabel angiver navnet på tabellen. En tabel består af en række kolonner – for hver af disse kan man angive kolonnens navn, type og en eventuel begrænsning på de data, der kan indtastes. SQL-standarden definerer nedenstående typer, men de enkelte databaser kan anvende andre navne.

 

Type Beskrivelse
CHAR(n) En tekststreng med n tegn.
VARCHAR(n) En tekststreng med op til n tegn.
LONG VARCHAR(n) En tekststreng med op til n tegn.
DECIMAL(c,d) Et decimaltal med c cifre og d decimaler.
NUMERIC(c,d) Som DECIMAL
SMALLINT Et heltal på to byte.
INTEGER Et heltal på fire byte.
REAL Et decimaltal på fire byte.
FLOAT Et decimaltal på otte byte.

Tabel 5.1: Kolonnetyper i SQL.

 

For hver kolonne kan der angives eventuelle begrænsninger, som for eksempel at indholdet af kolonnen ikke må være null – det gøres ved at skrive NOT NULL.

Ved at tilføje ordet AS og en forespørgsel kan man oprette tabellen på baggrund af en forespørgsel. Forespørgsler bliver gennemgået senere i dette kapitel.

Nedenstående eksempel viser, hvordan man kan oprette en adresse-tabel.

 

CREATE TABLE adresse (

Navn      VARCHAR(30)  NOT NULL,

Adresse1  VARCHAR(50)  NOT NULL,

Adresse2  VARCHAR(50),

Postnr    CHAR(4)      NOT NULL,

Telefon   CHAR(8)

)

 

Indsættelse af data

Når man skal indsætte data i en tabel ved hjælp af SQL, bruger man kommandoen INSERT INTO. Denne kommando har følgende syntaks:

 

INSERT INTO [bruger].tabel [(kolonne [, kolonne] . . .)] { VALUES (værdi [, værdi]) | forespørgsel}

 

Ligesom ved CREATE TABLE-kommandoen angiver bruger.tabel navnet på den tabel, der skal arbejdes på. Hvis man kun ønsker at indsætte data i nogle af kolonnerne i tabellen, skal man angive navnene på kolonnerne i kommandoen. Man kan angive lige så mange kolonner, man vil, adskilt af komma.

Man kan enten selv angive de data, der skal indsættes i tabellen, eller generere dem ved hjælp af en forespørgsel. Forespørgsler bliver gennemgået senere i dette kapitel. Hvis man selv angiver dataene, skal man skrive dem i samme rækkefølge, som man har nævnt kolonnenavnene. Man skal være opmærksom på, at tekststrenge skal angives i apostroffer – eksempelvis ‘tekst’.

Nedenstående eksempel viser, hvordan man kan indsætte data i den tabel, der blev oprettet i afsnittet om oprettelse af tabel.

 

INSERT INTO adresse

(Navn, Adresse1, Postnr, Telefon)

VALUES (‘Egon Jensen’, ‘Svinget 3’, ‘9110’, ‘97123456’)

 

Forespørgsel på data

Forespørgsler kan bruges til mange ting i SQL. Man kan naturligvis bruge dem til at trække oplysninger ud af databasen, men man kan også bruge dem som inddata til oprettelse af tabeller, indsættelse af data med mere.

I SQL foretages en forespørgsel med kommandoen SELECT. Denne kommando har følgende syntaks:

 

SELECT [ALL|DISTINCT] {* | tabel.* | kolonne [nyt navn]} [,{ tabel.* | kolonne [nyt navn]}] . . . FROM [bruger.]tabel [nyt navn] [,[bruger.]tabel [nyt navn] . . .]

[WHERE betingelse]

[CONNECT BY betingelse]

[START WITH betingelse]

[GROUP BY kolonne [, kolonne] . . .[HAVING betingelse}] ]

[{UNION|INTERSECT|MINUS forespørgsel} . . . ]

[ORDER BY {kolonne | position) [ASC|DESC] [, kolonne | position) [ASC|DESC] ] . . .

[FOR UPDATE OF kolonne [, kolonne] [NOWAIT] ]

 

Kommandoen ser umiddelbart forholdsvis kompliceret ud, men det skyldes blot, at den er overmåde fleksibel og har en lang række muligheder. Typisk bruger man kun en meget lille del af disse muligheder.

Det centrale i kommandoen er angivelse af den eller kolonner, der skal udvælges. Disse skrives efter SELECT. Hvis man eksempelvis vil udvælge kolonnerne navn og telefon, skriver man altså

 

SELECT navn, telefon

 

Herefter kan man vælge den eller de tabeller, dataene skal udvælges fra. I dette eksempel hedder tabellen adresse, og når dette tilføjes til kommandoen, kommer den til at se således ud:

 

SELECT navn, telefon

FROM adresse

 

Oftest vil man ikke udvælge samtlige poster i tabellen, og man har derfor mulighed for at stille nogle betingelser til de poster, der skal udvælges. Dette gøres efter ordet WHERE. Hvis betingelsen eksempelvis skal være, at postnummeret er 9110, kommer forespørgslen til at se således ud:

 

SELECT navn, telefon

FROM adresse

WHERE postnr=’9110′

 

Hvis man vil sortere resultatet, kan man benyttet ORDER BY-parametren. Denne parameter angiver den eller de kolonner, der skal sorteres efter, samt om sorteringen skal foretages i stigende eller faldende orden. ASC angiver stigende orden (ascending), mens DESC angiver faldende orden (descending). Nedenstående eksempel viser, hvordan man kan sortere resultatet efter navne.

 

SELECT navn, telefon

FROM adresse

WHERE postnr=’9110′

ORDER BY navn ASC

 

Egentlig er det ikke nødvendigt at tilføje ASC, da data som standard sorteres i stigende orden, hvis andet ikke er angivet.

SELECT-kommandoen giver også en række mere avancerede muligheder.

Ved at angive ALL eller DISTINCT kan man vælge, om alle data skal findes, eller om rækker, der optræder flere gange, kun skal optræde en enkelt gang i resultatet. Angiver man ikke DISTINCT bruges ALL.

CONNECT BY angiver, at der er tale om en hierarkisk forespørgsel, og man kan angive den forespørgsel, der skal forbinde forespørgslerne i hierarkiet.

START WITH angiver den eller de rækker, der skal være roden i en hierarkisk forespørgsel.

UNION, INTERSECT og MINUS kombinerer flere forespørgsler til én forespørgsel.

FOR UPDATE OF angiver, hvilke poster der kan blive opdateret. Derved vil disse poster blive låst. Angiver man desuden NOWAIT, vil forespørgslen ikke vente, hvis en eller flere af de ønskede poster ikke kan låses.

Hvis man ønsker det, kan man under forespørgslen vælge at give kolonner og tabeller nye navne, der gør dem lettere at referere til senere.

Opdatering af data

Hvis man vil ændre i eksisterende data, sker det ved hjælp af kommandoen UPDATE. Denne kommando har følgende syntaks.

 

UPDATE [bruger.]tabel SET kolonne = data [, kolonne = data] . . . [WHERE betingelse]

 

eller

 

UPDATE [bruger.]tabel SET (kolonne [, kolonne] . . .) = (forespørgsel) [, . . .] [WHERE betingelse]

 

Som det ses, kan man enten basere opdateringen på data, man selv indtaster eller på en forespørgsel. I begge tilfælde skal man dog angive den tabel, der skal foretages opdateringer i, samt de kolonner der skal opdateres. Angiver man selv dataene, skal man for hvert kolonnenavn angive den nye værdi, mens man ved en forespørgselsbaseret opdatering blot skal angive kolonnernes navne. Hvis man ikke ønsker at opdatere samtlige poster i databasen, kan man angive en betingelse, og det vil i så fald kun være de poster, som opfylder betingelsen, der vil blive ændret.

Nedenstående eksempel viser, hvordan man kan ændre et postnummer i databasen.

 

UPDATE adresse

SET postnr=’9111′

WHERE postnr=’9110′

 

Sletning af data

Til at slette poster fra en tabel i databasen bruges kommandoen DELETE. Syntaksen for denne kommando er som følger:

 

DELETE [FROM] [bruger.]tabel [WHERE betingelse]

 

Igen angiver bruger.tabel den tabel, der skal arbejdes på. Betingelse angiver den betingelse, poster skal opfylde, for at blive slettet.

Nedenstående eksempel viser, hvordan man kan slette alle personer med et bestemt navn.

 

DELETE FROM adresse

WHERE navn=’Anders And’

Installation af DSN

Den mest udbredte måde at lave forbindelse mellem ASP og en database er ODBC – Open Database Connectivity. ODBC er en standard defineret af Microsoft. Med ODBC er det muligt at tilgå flere forskellige databaser på samme måde. Det betyder, at de kommandoer, man bruger i ASP, er de samme, ligegyldigt hvilken database man benytter. Man behøver blot at angive navnet på databasen. For at web-serveren kan finde ud af, hvilken database man refererer til, skal man dog i operativsystemet angive sammenhængen mellem det navn, man angiver, og selve databasen. I Windows gøres dette i kontrolpanelet under punktet 32-bit ODBC.

Det man skal opsætte er et databasesystemnavn (DSN). Der findes tre forskellige former for DSN: Bruger-DSN, system-DSN og fil-DSN. En bruger-DSN er kun tilgængelig for den aktuelle bruger og kun på den lokale maskine. En system-DSN er derimod tilgængelig for alle brugere, og også for systemservices. En fil-DSN giver adgang til en database med en driver, og denne DSN kan deles af flere brugere, hvis alle brugere har den samme driver installeret. I forbindelse med ASP skal man bruge en system-DSN.

For at oprette en system-DSN skal man klikke på fanen System-DSN. Herefter skal man klikke på knappen Tilføj. Det næste billede viser en liste over de installerede databaser. I dette eksempel vælges Access-databasen.

 

Figur 5.1: Valg af database.

 

 

 

 

 

 

Når man har valgt den ønskede database, klikker man på udfør. Man vil herefter blive præsenteret for et vindue, hvor man kan indtaste de oplysninger, der skal bruges for at identificere databasen. Anvender man en Access-database, ser vinduet ud som i figur 5.2.

 

Figur 5.2: Identifikation af database.

 

 

 

 

 

Man skal naturligvis angive det navn, man gerne vil bruge til at tilgå databasen fra ASP. Dette navn kan man selv vælge. Man kan også vælge at lave en beskrivelse af databasen – dette er ikke nødvendigt, men det gør det lettere at skelne mellem databaserne, hvis man har flere forskellige. I dialogboksen skal man også angive, hvilken Access-fil der skal knyttes til det angivne navn. Ved at klikke på knappen Vælg får man vist en dialogboks, hvor man kan vælge mellem alle de Access-filer, der ligger på computeren.

Installationen af DSN’en er nu færdig. Når man klikker på OK, vender man tilbage til installationsvinduet. Som det ses af nedenstående figur 5.3, er den nye DSN nu blevet tilføjet listen. Hvis man senere vil foretage ændringer i de oplysninger, man angav under installationen, kan man vælge at redigere dem fra dette vindue.

 

Figur 5.3: Oversigt over installerede DSN.

 

 

 

 

 

 

 

Som nævnt bliver der i eksemplerne i denne bog arbejdet på en Access-database. Selvom Access er en udmærket database, skal man dog være opmærksom på, at programmet har nogle ulemper. Eksempelvis bliver poster, der bliver slettet i databasen, ikke slettet fra filen. Det betyder, at filen bliver større og større. For at formindske filen igen, skal man vælge at komprimere den. Dette kan man gøre ved at vælge Komprimer fra installationsvinduet.

Når man har færdiggjort installationen af en system-DSN, kan man begynde at bruge databasen fra ASP.

Databaseobjekter

Databaseadgang er ikke indbygget i de scriptsprog, man kan bruge sammen med ASP. For at råde bod på dette, er der indbygget nogle objekter, som man kan bruge til at tilgå databaser. Disse objekter er baseret på ADO (ActiveX Data Object), som også bruges i andre sammenhænge.

I ASP er der flere objekter, der repræsenterer ADO. Det centrale af disse objekter er Connection-objektet, som håndterer forbindelsen til databasen. Man opretter et Connection-objekt ved at skrive

 

Connection = Server.CreateObject(“ADODB.Connection”);

 

Som nævnt er Connection-objektet det centrale i arbejdet med databaser. Objekter indeholder derfor en lang række metoder og variabler. Disse bliver alle kort beskrevet i nedenstående tabeller og gennemgået dybere i resten af dette kapitel.

 

Metode Beskrivelse
BeginTrans Starter en transaktion.
Close Lukker forbindelsen til databasen.
CommitTrans Udfører en transaktion.
Execute Udfører en forespørgsel.
Open Åbner en forbindelse til databasen.
OpenSchema Åbner et databaseskema.
RollbackTrans Ruller en transaktion tilbage.

Tabel 5.2: Metoder i Connection-objektet.

 

Variabel Beskrivelse
Attributes Angiver om en ny transaktion skal startes, når en transaktion er fuldført.
CommandTimeout Angive antallet af sekunder, en kommando har til at blive udført.
ConnectionString Angiver de oplysninger, der er brugt til at lave forbindelse til databasen.
ConnectionTimeout Angiver antallet af sekunder, der må bruges på at skabe forbindelse til databasen.
CursorLocation Angiver om markøren findes på serveren eller på klienten.
DefaultDatabase Angiver den database, der som standard bruges til forbindelse.
IsolationLevel Angiver isolationsniveauet for transaktioner.
Mode Angiver udbyderens adgangsrettigheder.
Provider Angiver udbyderens navn.
State Angiver om forbindelsen er åben eller lukket.
Version Angiver hvilken version af ADO, der bruges.

Tabel 5.3: Variable i Connection-objektet.

 

Når man har oprettet en Connection, skal man være opmærksom på, at den endnu ikke refererer til  noget. Derfor skal man åbne den, før man kan bruge den. Databaseforbindelsen åbnes ved at kalde metoden Open. Denne metoder tager op til tre parametre. Den første er en forbindelsesstreng, der specificerer, hvilken database der skal åbnes. De to yderligere parametre er henholdsvis brugernavn og adgangskode til databasen. Hvis der ikke kræves brugernavn og kodeord for at tilgå databasen, kan man undlade disse.

Forbindelsesstrengen kan være navnet på en systemdatakilde (DSN), som er registreret i ODBC. Dette er klart den letteste fremgangsmåde, men ikke den eneste. Man kan også opbygge sin forbindelsesstreng manuelt ved at udpege den database, man vil bruge. For at gøre dette skal man angive en række oplysninger, der skal bruges af databasen. Disse oplysninger varierer fra database til database.

Hvis man vil åbne en database, der er registreret med systemdatakildenavnet webbase, skriver man

 

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“webbase”);

 

Variablen ConnectionString afspejler den forbindelsesstreng, man angiver. Før man åbner forbindelsen kan man bruge variablen til at angive, hvilken forbindelsesstreng der skal bruges. Når forbindelsen er åbnet, kan man ikke længere ændre ConnectionString, men man kan  læse indholdet af den og på den måde finde den forbindelsesstreng, der blev brugt til at åbne databaseforbindelsen. Ved at anvende ConnectionString-variablen kan man omskrive ovenstående eksempel til følgende:

 

connection = Server.CreateObject(“ADODB.Connection”);

connection.ConnectionString=”webbase”;

connection.open();

 

I dette eksempel er der ingen fordel ved at bruge denne fremgangsmåde, men hvis man skal opbygge forbindelsesstrengen af en lang række variable, eller hvis forbindelsesstrengen afhænger af ydre omstændigheder, kan det være en fordel at sætte ConnectionString-variablen, før man åbner databaseforbindelsen.

Når man har et Connection-objekt, kan man bruge dette til at udføre SQL-forespørgsler. Man kan dog også vælge at bruge et Command-objekt. Når man bruger et Command-objekt, behøver man ikke åbne en databaseforbindelse. Dette gør Command-objektet automatisk. Fordelen ved dette, er at man ikke behøver håndtere åbning og lukning af databaseforbindelsen, men ulempen er, at man åbner og lukker forbindelsen for hver forespørgsel. Man bør derfor kun bruge Command-objektet, hvis man kun foretager en enkelt forespørgsel.

Command-komponenten hedder ADODB.Command, og man kan lave et objekt af denne komponent ved at skrive

 

command = Server.CreateObject(“ADODB.Command”);

 

Command-objektet indeholder en række metoder og variabler, der er beskrevet i nedenstående tabeller.

 

Metode Beskrivelse
CreateParameter Tilføjer en parameter til parameter-samlingen, der beskrives senere.
Execute Udfører kommandoen.

Tabel 5.4: Metoder i Command-objektet.

 

Variabel Beskrivelse
ActiveConnection Angiver den databaseforbindelse, der skal bruges.
CommandText Teksten til den SQL-forespørgsel, der skal udføres.
CommandTimeout Angiver hvor mange sekunder en kommando har til at blive udført.
CommandType Angiver typen på den kommando, CommandText angiver.
Name Angiver kommandoens navn.
Prepared Angiver, om der skal oprettes et forberedt udtryk (prepared statement) for forespørgslen udføres.
State Angiver om kommandoen er åben eller lukket. Er kommandoen åben, returneres adStateOpen, mens adStateClosed returneres, hvis kommandoen er lukket.

Tabel 5.5: Variable i Command-objektet.

 

For at skabe forbindelse til databasen med navnet webbase ved hjælp af et Command-objekt skal man skrive

 

command = Server.CreateObject(“ADODB.Command”);

command.ActiveConnection = “webbase”;

 

Som nævnt kan både Command-objekter og Connection-objekter bruges til at udføre SQL-forespørgsler. I begge tilfælde er det metoden execute, der skal bruges. Nedenstående eksempel viser, hvordan man kan bruge Connection-objektet til at udføre SQL-forespørgsler.

 

<% @language=javascript %>

 

<%

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

 

connection.execute(“INSERT INTO tabel VALUES (‘connection’)”);

Response.write(“Data indsat.”);

%>

 

For at afvikle ovenstående eksempel kræves en database registreret med navnet eksempel. Denne database skal indeholde en tabel ved navn tabel.

Eksemplet kan forholdsvis nemt omskrives til at bruge et Command-objekt. Det omskrevne eksempel ses herunder.

 

<% @language=javascript %>

 

<%

command = Server.createObject(“ADODB.Command”);

command.ActiveConnection = “eksempel”;

command.CommandText=”INSERT INTO tabel VALUES (‘command’)”;

 

command.execute();

Response.write(“Data indsat.”);

%>

 

Den grundlæggende teori bag databaser er nu blevet gennemgået, ligesom de elementære objekter er blevet forklaret. De næste afsnit i dette kapitel vil beskrive, hvordan man i praksis kan bruge databaser sammen med ASP.

Selektion fra en database

En hyppig anvendelse af en database i forbindelse med web-applikationer er som opbevaring af information, som brugeren kan søge i. Dette kan dreje sig om prislister, ordbøger, leksika, adresseoplysninger og meget andet. Eksemplerne i dette afsnit vil tage udgangspunkt i en – meget lille – dansk-engelsk ordbog. Ordbogen ligger i en database, der er registreret med DSN eksempel i en tabel ved navn ordbog. Tabellen indeholder kolonnerne dansk og engelsk, der henholdsvis indeholder det danske og det engelske ord.

I introduktionen til SQL blev det nævnt, at det er kommandoen SELECT, der bruges til at forespørge på data i en SQL-database.  Hvis man eksempelvis vil udtrække det engelske ord svarende til det danske ord bog, bliver SQL-forespørgslen SELECT engelsk FROM ordbog WHERE dansk=’bog’.

Det foregående afsnit beskrev, hvordan man opretter databaseforbindelser. Forbindelsen til eksempel-databasen oprettes således:

 

<% @language=javascript %>

 

<%

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

%>

 

Til at udføre en SQL-forespørgsel bruges som nævnt tidligere metoden execute. Tidligere var det nok blot at kalde execute-metoden med den SQL-forespørgsel, der skulle udføres – det er det ikke i dette tilfælde. Når der forespørges efter data, skal man jo have resultatet af forespørgslen tilbage. Resultatet af forespørgslen returneres i en samling af poster – et RecordSet. Dette vil blive gennemgået senere. Nedenstående kodelinie viser, hvordan man udfører forespørgslen og modtager resultatet.

 

res = connection.execute(“SELECT engelsk FROM ordbog WHERE dansk=’bog'”);

 

RecordSet-objektet, der returneres af execute-metoden, indeholder en række metoder og variable, der gennemgås i følgende to tabeller.

 

Metode Beskrivelse
AddNew Tilføjer et ny post til sættet, hvis sættet kan opdateres.
CancelBatch Annullerer en batch-opdatering.
CancelUpdate Annullerer ændringer i den aktuelle post eller nye poster.
Clone Opretter en kopi af det eksisterende RecordSet.
Close Lukker sættet.
Delete Sletter den aktuelle post i sættet, hvis sættet er åbent.
GetRows Overfører en del af rækkerne i sættet til et array.
Move Skifter den aktuelle post.
MoveFirst Gør den første post til den aktuelle post.
MoveLast Gør den sidste post til den aktuelle post.
MoveNext Gør den næste post til den aktuelle post.
MovePrevious Gør den forrige post til den aktuelle post.
NextRecordSet Går videre til det næste RecordSet, hvis forespørgslen har returneret flere sæt.
Open Åbner det aktuelle sæt.
Requery Opdaterer sættet ved at udføre forespørgslen igen.
Resync Opdaterer sættet, men udfører ikke forespørgslen igen. Dette opdaterer de eksisterende rækker, men tilføjer ikke eventuelle nye rækker.
Supports Undersøger om sættet understøtter specifikke funktioner.
Update Gemmer eventuelle ændringer i den aktuelle post.
UpdateBatch Skriver alle ventende opdateringer til disken.

Tabel 5.6: Metoder i RecordSet-objektet.

 

Variabel Beskrivelse
AbsolutePage Angiver positionen af den aktuelle side.
AbsolutePosition Angiver positionen af den aktuelle post.
ActiveConnection Angiver det connection-objekt, der er brugt til at oprette sættet.
BOF Angiver om den aktuelle post er før den første.
Bookmark Returnerer et bogmærke, der identificerer den nuværende position i sættet.
CacheSize Angiver antallet af poster i hukommelsen.
CursorLocation Angiver om markøren er på klienten eller på serveren. Hvis markøren er på klienten, returneres adUseClient, ellers returneres adUseServer.
EditMode Angiver den aktuelle posts redigeringstilstand.
EOF Angiver om markøren er efter den sidste post.
Filter Angiver et filter for sættet.
LockType Angiver hvilken type låse, der bruges til at låse posterne under redigering.
MarshalOptions Angiver hvilke poster, der skal sendes tilbage til serveren, når man bruger et resultatsæt på klienten.
MaxRecords Angiver det maksimale antal poster, der skal returneres.
PageCount Angiver antallet af sider i sættet.
PageSize Angiver sidestørrelsen i poster.
RecordCount Angiver antallet af poster i sættet.
Source Angiver kildeteksten på den forespørgsel, der resulterede i sættet.
State Angiver om sættet er åbent eller lukket.
Status Angiver status på den aktuelle post.

Tabel 5.7: Variable i RecordSet-objektet.

 

Udover de metoder og variabler, der er gennemgået i ovenstående tabeller, indeholder RecordSet-objektet en samling ved navn Fields. Denne samling består af indholdet af kolonnerne i den aktuelle post. De enkelte celler kan tilgås på to forskellige måder: enten ved angive navnet på kolonnen eller ved at angive kolonnens placering i resultatsættet.

Hvordan man vælger at tilgå cellerne afhænger af den applikation, man er ved at lave. Hvis man tilgår cellerne ved hjælp af kolonnens placering, gør man applikationen uafhængig af navnene på kolonnerne – dette vil typisk være mere generelt end at bruge kolonnenavnene. At bruge kolonnenavnene har til gengæld den fordel, at man ikke får problemer, hvis man tilføjer eller fjerner en kolonne, så kolonnenumrene ændres. Det er også lettere at forstå kildeteksten, hvis kolonnernes navne står der i stedet for blot numrene.

For at vise resultatet af det eksempel, der blev gennemgået tidligere i dette afsnit, kan man bruge følgende kode:

 

<html>

<body>

 

Det danske ord <b>Bog</b> hedder <b><%= res.Fields(“engelsk”)%></b> på engelsk.

 

</body>

</html>

 

Eksemplet viser, hvordan man kan tilgå kolonnen ved hjælp af dens navn. Som nævnt kan man også bruge kolonnens position til at tilgå dataene. Det viser nedenstående eksempel:

 

<html>

<body>

 

Det danske ord <b>Bog</b> hedder <b><%= res.Fields(0)%></b> på engelsk.

 

</body>

</html>

 

Udover at kunne bruges til at tilgå data med, kan Fields-samlingen også bruges til at få oplysninger om antallet af felter i posten. Det sker med count-variablen. Samlingen indeholder en samling ved navn Item – det er faktisk denne samling, der indeholder dataene fra posten. Når man bruger Fields-samlingen til at tilgå data i den aktuelle post, udnytter man, at Item-samlingen er standardsamlingen i Fields-samlingen – derfor kan man nøjes med at skrive Fields(navn) for at tilgå cellerne.

I ovenstående ekstempel indeholdt resultatet kun en enkelt post, men et RecordSet kan bestå af en lang række poster. Til at angive hvilken post man ønsker at arbejde på, bruges en markør. Hvis man forestiller sig resultatet som en liste af poster, kan man forestille sig markøren som en pil, der peger på den aktuelle post – det viser nedenstående figur:

 

Post1

Post2

Post3 ß markør

Post4

Post5

 

Hvis man udfører en metode på sættet, som arbejder på en enkelt post, vil den arbejde på den post, markøren peger på. Som det fremgår af metoderne i RecordSet-objektet, kan man bevæge markøren til at pege på den post, man ønsker at arbejde på. Man kan bruge variablen EOF til at se, om markøren er placeret efter den sidste post. Nedenstående eksempel viser, hvordan man ved hjælp af MoveNext og EOF kan gennemgå et sæt.

 

while (!res.EOF) {

// behandl den aktuelle post

res.MoveNext();

}

 

I eksemplet fra før kunne man forestille sig, at man vil vide, hvad ordet skat hedder på engelsk. Her er der flere forskellige muligheder, og det er ASP-siden naturligvis nødt til at håndtere. Nedenstående eksempel viser, hvordan det kan gøres:

 

<% @language=javascript %>

 

<%

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

 

res = connection.execute(“SELECT engelsk FROM ordbog WHERE dansk=’skat'”);

 

%>

 

<html>

<body>

 

Det danske ord <b>Skat</b> kan på engelsk hedde:

<ol>

 

<%

while (!res.EOF) {

%>

 

<li><b><%=res.Fields(“engelsk”)%></b></li>

 

<%

res.MoveNext();

}

%>

</ol>

</body>

</html>

 

Sortering

Hvis man skal vise mange oplysninger ad gangen, er det som regel en god idé at sortere dem. Selvom JavaScript er et forholdsvis begrænset sprog, er det muligt at implementere de fleste sorteringsalgoritmer i det, men når man arbejder med databaser, kan det ikke anbefales. Dels er det omfattende at skrive algoritmerne i JavaScript, og dels er det også forholdsvis langsomt at afvikle. Det er meget lettere og væsentligt mere effektivt at bruge sorteringsmulighederne i SQL.

Som det blev beskrevet i introduktionen til SQL, kan man i en SELECT-forespørgsel angive, hvilken orden dataene skal sorteres i. Dette sker ved at føje ORDER BY til forespørgslen.

Hvis man for eksempel vil vise indholdet af hele ordbogen i eksemplet fra før, er det nok en god idé at sortere ordene. Nedenstående eksempel viser, hvordan man kan vise ordene i alfabetisk orden. I eksemplet har brugeren selv mulighed for at vælge, om det skal være de danske eller de engelske ord, der skal sorteres. Sorteringen ændres ved at klikke på overskriften.

 

<% @language=javascript %>

 

<%

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

 

sql = “SELECT * FROM ordbog ORDER BY “;

if (Request.QueryString(“sprog”) == “engelsk”) {

sql += “engelsk”;

} else {

sql += “dansk”;

}

res = connection.execute(sql);

 

%>

 

<html>

<body>

<table>

<thead>

<th><a href=ordbog.asp?sprog=dansk>Dansk</a></th>

<th><a href=ordbog.asp?sprog=engelsk>Engelsk</a></th>

</thead>

<tbody>

 

<%

while (!res.EOF) {

%>

 

<tr>

<td><%=res.Fields(“dansk”)%></td>

<td><%=res.Fields(“engelsk”)%></td>

</tr>

 

<%

res.MoveNext();

}

%>

 

</body>

</html>

 

Figur 5.4: Indholdet af ordbogen.

 

 

 

 

 

 

 

 

 

 

 

 

 

Eksemplet kontrollerer, om parameteren sprog er sat til engelsk. Hvis dette er tilfældet, betyder det, at oversigten skal sorteres efter de engelske ord. Er den ikke sat til engelsk, betyder det enten, at parameteren slet ikke er sat, eller at den er sat til dansk; i begge tilfælde skal oversigten sorteres efter de danske ord.

 

Lad brugeren vælge

Det forrige eksempel tog hul på emnet at lade brugeren vælge. For det er naturligvis oftest brugeren, der direkte eller indirekte bestemmer, hvilke data der skal forespørges på i databasen.

Når det er en bruger af web-stedet, der er med til at bestemme forespørgslen, er der en række ting, man skal tage højde for. Man kan for eksempel ikke være sikker på, at der bliver fundet poster, ligesom man skal kontrollere, at brugeren har indtastet noget gyldigt. Forventer databasen eksempelvis en numerisk værdi, nytter det ikke meget, at man giver den en tekst, blot fordi brugeren har indtastet bogstaver i stedet for tal.

I dette afsnit vil ordbogseksemplet blive udvidet, så brugeren får mulighed for at indtaste, hvilket ord der skal slås op, og vælge hvilket sprog opslaget skal foretages på. Eksemplet består af en HTML-side, der indeholder den formular, brugeren udfylder, og en ASP-side, der genererer svaret.

Kildeteksten til HTML -dokumentet ser således ud:

 

<html>

<body>

<b>Online ordbog</b><br>

<form action=opslag.asp method=get>

 

<table>

<tr>

<td>Vælg måde</td>

<td>Indtast ord</td>

</tr>

 

<tr>

<td>

<select name = sprog>

<option value=dansk>Fra dansk til engelsk</option>

<option value=engelsk>Fra engelsk til dansk</option>

</td>

 

<td>

<input type=text name=ord>

</td>

</tr>

<tr>

<td colspan=2 align=center>

<input type=submit value=”Slå op”>

</td>

</tr>

</table>

</form>

</body>

</html>

 

Ovenstående HTML-kode giver et billede svarende til figur5.5.

Figur 5.5: Online-ordbog.

 

 

 

 

 

 

 

 

 

 

 

 

 

Siden kalder opslag.asp med to parametre: parameteren sprog kan enten være dansk eller engelsk. Parameteren ord angiver det ord, der skal slås op på det pågældende sprog.

Kildeteksten til opslag.asp ser således ud:

 

<% @language=JavaScript %>

 

<html>

<body>

 

<%

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

 

if (Request.QueryString(“sprog”) == “dansk”) {

sql = “SELECT engelsk FROM ordbog WHERE dansk ='” + Request.QueryString(“ord”) + “‘”;

} else {

sql = “SELECT dansk FROM ordbog WHERE engelsk ='” + Request.QueryString(“ord”) + “‘”;

}

 

res = connection.Execute(sql);

 

%>

 

Ordet <b><%=Request.QueryString(“ord”)%></b> kan betyde

<ol>

 

<%

while (!res.EOF) {

%>

 

<li><b><%= res.Fields(0)%></b></li>

 

<%

res.MoveNext();

}

%>

</ol>

<p>

<a href = opslag.html>Tilbage</a>

</body>

</html>

 

I denne form håndterer siden ikke nogen af de problemer, der kan opstå, hvis brugeren indtaster anden data, end ASP-siden forventer. Hvis brugeren indtaster et ord, der ikke findes, vil der blive vist en side, der ser ret uheldig ud.

Hvis man vil kontrollere, om en forespørgsel giver et resultat, kan man kontrollere, om EOF er sand umiddelbart efter forespørgslen er foretaget. Hvis denne ændring skal indføres i forrige eksempel, kommer kildeteksten til at se således ud:

 

<% @language=JavaScript %>

 

<html>

<body>

 

<%

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

 

if (Request.QueryString(“sprog”) == “dansk”) {

sql = “SELECT engelsk FROM ordbog WHERE dansk ='” + Request.QueryString(“ord”) + “‘”;

} else {

sql = “SELECT dansk FROM ordbog WHERE engelsk ='” + Request.QueryString(“ord”) + “‘”;

}

 

res = connection.Execute(sql);

 

if (res.EOF) {

%>

Ordet <b><%=Request.QueryString(“ord”)%></b> kunne desværre ikke findes i ordbogen.

 

<%

} else {

%>

 

Ordet <b><%=Request.QueryString(“ord”)%></b> kan betyde

<ol>

 

<%

while (!res.EOF) {

%>

 

<li><b><%= res.Fields(0)%></b></li>

 

<%

res.MoveNext();

}

}

%>

</ol>

<p>

<a href = opslag.html>Tilbage</a>

</body>

</html>

 

Der er også et andet problem, der skal håndteres. Det er brugerens indtastninger. I dette eksempel er det ikke nødvendigt at kontrollere, om det er tal eller bogstaver, der bliver indtastet – systemet kan håndtere begge dele. Der er dog et problem, hvis brugeren eksempelvis indtaster en apostrof (‘). Apostroffer er en del af SQL-syntaksen, og må derfor ikke indgå i den tekst, der skal søges efter. Derfor er det en god ide med en metode, der fjerner eventuelle apostroffer fra opslagsordet. Denne funktionalitet kan implementeres på mange forskellige måder – nedenstående metode er blot et eksempel på, hvordan funktionaliteten kan implementeres:

 

function checkInput(s) {

t = “”;

s = “” + s;

for (i = 0; i < s.length; i++) {

if (s.charAt(i) != “‘”) {

t += s.charAt(i);

}

 

}

return t;

}

Publicering til databasen

At hente oplysninger ud af databasen er naturligvis kun en del af at bruge databaser. Det ville jo være rart, hvis man også kunne tilføje oplysninger til databasen fra web-stedet. Det kan man blandt andet bruge til selv at opdatere databasen via web-stedet, og man kan også bruge teknikken til at lade besøgende på web-stedet indsende oplysninger, der kan gemmes i databasen.

I dette eksempel vil det både blive gennemgået, hvordan man gemmer en formular i databasen, og hvordan man laver statistik over web-stedet.

 

Statistik

En statistik på et web-sted kan registrere en lang række ting. Det kan eksempelvis være oplysninger om de besøgendes IP-adresser, besøgstidspunkter, brugernavn og lignende. I dette eksempel vil der for simpelhedens skyld kun blive registreret, hvilke sider brugeren besøger.

Statistiksystemet opbygges omkring en funktion, der registrerer et besøg på en given side. Denne funktion skal indeholde en identifikation af siden. I dette eksempel vil det være adressen på siden. Statistikfunktionen skal kaldes fra alle sider på web-stedet.

Statistikfunktionen registrerer besøget i databasen. Databasen indeholder en tabel, der har en post for hver side på web-stedet.

Den funktion, der registrerer besøgende på web-stedet, kan se således ud:

 

<% @language=javascript %>

 

<%

function stat(id) {

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

 

res = connection.Execute(“SELECT antal FROM statistik WHERE side = ‘” + id + “‘”);

 

antal = res.fields(“antal”);

antal++;

 

connection.Execute(“UPDATE statistik SET antal=” + antal + ” WHERE side = ‘” + id + “‘”);

return antal;

}

%>

 

Funktionen starter med at læse, hvor mange gange siden allerede er blevet besøgt. Dette gøres ved at tage indholdet af antal-kolonnen i databasen i den række, hvor siden svarer til det id, der er givet med som parameter til funktionen. Dernæst tælles antallet op, og indholdet af databasen bliver opdateret. Metoden returnerer det aktuelle antal besøgende på siden, så man har mulighed for at arbejde videre med tallet og eventuelt vise det til de besøgende.

Nedenstående kildetekst viser, hvordan kaldet til statistik-funktionen kan implementeres i et ASP-dokument:

 

<html>

<body>

Denne side er blevet besøgt <%= stat(“statistik.asp”)%> gange.

</body>

</html>

 

At indsamle oplysningerne til statistikken er imidlertid kun halvdelen af arbejdet. Oplysningerne skal også kunne vises. Typisk vil man kunne sortere og gruppere statistikken efter alle de oplysninger, der er indsamlet. I dette eksempel er det imidlertid ikke nødvendigt, da der som nævnt kun indsamles en enkelt oplysning. Siden til at vise statistikken giver derfor kun mulighed for at vise antal besøgende pr. side, samt en total optælling.

 

<% @language = javascript %>

 

<html>

<body>

 

<h1>Statistik</h1>

 

<table>

<thead>

<th align=left>Side</th>

<th align=right>Antal besøgende</th>

</thead>

 

<%

connection = Server.CreateObject(“ADODB.Connection”);

connection.open(“eksempel”);

 

res = connection.Execute(“SELECT * FROM statistik ORDER BY antal DESC”);

 

while (!res.EOF) {

%>

 

<tr>

<td><%=res.fields(“side”)%></td>

<td align=right><%=res.fields(“antal”)%></td>

</tr>

 

<%

res.MoveNext();

}

%>

 

</table>

</body>

</html>

 

ASP-siden forespørger på indholdet af statistik-tabellen og præsenterer indholdet i en tabel sorteret, så den side med flest besøgende vises øverst på listen.

 

At gemme en formular

Man vil ofte have brug for at lade web-stedets gæster indsende oplysninger, der gemmes i databasen. Det kan eksempelvis være tilmelding til en mailingliste, bestilling af varer eller oplysninger eller noget helt andet. I dette afsnit vil der blive taget udgangspunkt i et ASP-program, der simulerer en gæstebog, som brugeren kan indtaste oplysninger i.

Når man designer databasen og den HTML-formular, dens oplysninger skal indtastes i, bør man tænke på, at de to dele skal arbejde sammen. Hvis man bruger forskellige navne til oplysninger i formularen og i databasen, skal man i ASP-siden konvertere mellem de to navne. Derfor kan man med fordel bruge det samme navn begge steder.

Tabellen i dette eksempel indeholder felterne navn, email, overskrift og tekst. Disse oplysninger skal brugeren indtaste for at skrive i gæstebogen. Nedenstående kildetekst viser, hvordan HTML-siden til indtastning af oplysninger kan laves.

 

<html>

<body>

<h1>Skriv i gæstebogen</h1>

For at skrive i gæstebogen skal du indtaste følgende oplysninger:

 

<form action=guest.asp method=post>

<table>

 

<tr>

<td>Dit navn</td>

<td><input type=text name=navn size=50></td>

</tr>

 

<tr>

<td>Din e-mail-adresse</td>

<td><input type=text name=email size=50></td>

</tr>

 

<tr>

<td>Overskrift</td>

<td><input type=text name=overskrift size=50></td>

</tr>

 

<tr>

<td valign=top>Besked</td>

<td><textarea name=tekst cols=50 rows=10></textarea></td>

</tr>

 

<tr>

<td colspan=2 align=center><input type=submit value=”Indsend”></td>

</tr>

 

</table>

</form>

 

</body>

</html>

 

Ovenstående kildetekst giver en HTML-side som den i figur 5.6.

 

Figur 5.6: HTML-side til indtastning af oplysninger til gæstebog.

 

 

 

 

 

 

 

 

Der skal naturligvis en ASP-side til at håndtere de indsendte oplysninger. I dette tilfælde hedder siden guest.asp, og i kildeteksten til siden kan man se fordelen ved at bruge de samme navne i HTML-formularen og tabellen. Kildeteksten ser således ud:

 

<html>

<body>

<h1>Skriv i gæstebogen</h1>

For at skrive i gæstebogen skal du indtaste følgende oplysninger:

 

<form action=guest.asp method=post>

<table>

 

<tr>

<td>Dit navn</td>

<td><input type=text name=navn size=50></td>

</tr>

 

<tr>

<td>Din e-mail-adresse</td>

<td><input type=text name=email size=50></td>

</tr>

 

<tr>

<td>Overskrift</td>

<td><input type=text name=overskrift size=50></td>

</tr>

 

<tr>

<td valign=top>Besked</td>

<td><textarea name=tekst cols=50 rows=10></textarea></td>

</tr>

 

<tr>

<td colspan=2 align=center><input type=submit value=”Indsend”></td>

</tr>

 

</table>

</form>

 

</body>

</html>

 

Som nævnt tidligere udnytter ASP-siden, at navnene i formularen og tabellen er ens. ASP-siden behøver derfor slet ikke have kendskab til navnene – den behøver blot at opdatere tabellen med de felter, siden modtager som parametre.

Rent praktisk gøres dette ved hjælp af en Enumeration, som kan bruges til at gå igennem alle de parametre, der gives til siden. Disse bruges til at bygge den SQL-forespørgsel, der tilføjer oplysningerne til databasen.

Sammenfatning

I dette kapitel er databaseadgang fra ASP blevet gennemgået. Før man begynder at bruge databaser, er det imidlertid en god idé at have et kendskab til SQL, og derfor indledtes dette kapitel med en kort introduktion til SQL.

Dernæst blev det beskrevet, hvordan man sætter serveren op til at kunne tilgå en database ved hjælp af ODBC.

Da det grundlæggende var på plads, blev det gennemgået, hvordan man skriver databaseprogrammer i ASP. Det blev både gennemgået, hvordan man udvælger data fra en database, og hvordan man indsætter data.

Du læser en gammel bog

Den bog, du læser her, er fra 1999, og mange ting kan have ændret sig siden da.
Vi håber, at du stadig kan finde relevant information i den.
Hvis du vil læse aktuelle oplysninger om den aktuelle version af ASP.NET, anbefaler vi
bogen Programming ASP.NET 4.0

Comments are closed.