Just nu i M3-nätverket
Gå till innehåll

Ingen som kunde??


Miljarder

Rekommendera Poster

Miljarder

Var det inte nån som kunde lösa mitt grymma problem om hur man kan göra visa 6 poster ur databasen? Följ koden och läs de gamla inläggen om du vill veta mer..

_________________________________________________

"Det är när det går långsamt som man förlorar sekunder!"

Länk till kommentar
Dela på andra webbplatser

För att visa 6 st poster så väljer du TOP 6 i SQL-satsen

 

/JANspeed

 

 

 

 

Länk till kommentar
Dela på andra webbplatser

Miljarder

Det är inte riktigt så enkelt.. jag vill visa post 4 till och med post 8 om det finns så många poster.. läs den förra tråden!

 

//Tomas

 

 

_________________________________________________

"Det är när det går långsamt som man förlorar sekunder!"

 

 

Länk till kommentar
Dela på andra webbplatser

Magnus Ahlkvist

Jag har en lösning, som jag dock är för lat för att omsätta till ditt exempel, använder därför istället ett eget exempel, men principen är likadan.

<%

dim conn

dim rs

dim iOffset

set conn=server.CreateObject("adodb.connection")

iOffset=request("offset")

if iOffset="" then iOffset=1

iOffset=cint(iOffset)

set rs=server.CreateObject("adodb.recordset")

 

rs.Open "select * from statusChanges order by statusid",conn,1,1

rs.PageSize=9

Response.Write "Showing page " & iOffset & " of " & rs.PageCount & "<br>"

if rs.PageCount<iOffset then

Response.Write "No more pages"

rs.Close

conn.Close

Response.End

end if

rs.AbsolutePage=iOffset

 

for i=1 to 9

if rs.EOF then exit for

Response.Write rs("statusID") & " " & rs("newstatusid") & " " & rs("permissionid") & "<br>"

rs.Movenext

next

if iOffset<rs.PageCount then Response.Write "<a href='dbtest.asp?offset=" & iOffset+1 & "'>Nästa</a><br>"

if iOffset>1 then Response.Write "<a href='dbtest.asp?offset=" & iOffset-1 & "'>Föregående</a>"

rs.Close

conn.Close

%>

 

 

--

En röst talade till mig och sade:

"Le och var glad, ty det kunde vara värre".

Så jag log, och jag var glad.

Och det blev värre.

 

Länk till kommentar
Dela på andra webbplatser

Var det nått sånt här du tänkte dig?

 

Har skrivit det från huvudet så är inte helt säker på att allt är rätt men i princip borde det funka.

 

'Connection, SQL och annat...

 

Set rs = Conn.Execute(SQL)

 

Count = 0

Do Until rs.EOF

Count = Count + 1

rs.movenext

Loop

 

rs.MoveFirst

 

If Count > 8 Then

 

For I to 4

rs.movenext

Next

 

For I to 6

Response.Write rs("Post") & "<br>"

rs.movenext

Next

 

Else

 

Do until rs.EOF

Response.Write rs("Post")

rs.movenext

Loop

 

End If

 

 

/JANspeed

 

Länk till kommentar
Dela på andra webbplatser

Miljarder

Såhär såg min kod ut men den packar ihop om det inte finns 8 poster i databasen.. går det att ändra den lite snabbt? Annars så tar jag din..

 

<%

Dim Tala

Do until Tala < 9 AND not Recset.EOF

IF Tala <=9 And Tala >= 3 then

 

%>

<table width="400" border="0" cellspacing="0" cellpadding="0">

<tr>

<td align="left"><font color="#333366" face="Verdana, Arial, Helvetica, sans-serif" size="1"><B>-[<%=Recset("Datum")%>]-</B></font>

</td>

</tr>

<TR>

<td align="left" valign="top"><font color="#333366" face="Verdana, Arial, Helvetica, sans-serif" size="1"><BR><B><%=Recset("Nyhet")%><BR><BR><BR><BR></B></font>

</td>

</tr>

<% End IF %>

<%

Tala = Tala + 1

Recset.MoveNext

Loop

%>

 

 

 

//Tomas

 

_________________________________________________

"Det är när det går långsamt som man förlorar sekunder!"

 

 

Länk till kommentar
Dela på andra webbplatser

Magnus Nilsson

Baggis..

 

Ok, när du har öppnat RS:et så använd GetRows för att flytta datan till en array.

Ex:

Dim oRS, aPoster, iMax, iCounter

 

[öppna oRS som vanligt]

 

aPoster = oRS.GetRows

'oRS behövs inte längre:

Set oRS = Nothing

'Bäst att kolla så att det är en array:

If IsArray(aPoster) Then

iMax = UBound(aPoster, 2)

If iMax > 7 Then iMax = 7

For iCounter = 3 To iMax

Response.Write aPoster(0, iCounter)

Next

End If

 

I ovanstående exempel skriver du ut post 4 till och med post 8, eftersom arrayen är 0-based. Slarvigt nog så har jag ingen koll om det överhuvudtaget finns fyra poster i arrayen, vilket du naturligtvis får lägga till, annars blir det fel.

 

Länk till kommentar
Dela på andra webbplatser

Magnus Ahlkvist
Ok, när du har öppnat RS:et så använd GetRows för att flytta datan till en array.

 

What?!

 

Ta ALLT data, flytta över det i en array, och skriv sen ut en delmängd.

I min värld är både CPU-kraft, minne och bandbredd mellan databasserver och

webbserver något man ska vara sparsam med när man utvecklar.

 

--

En röst talade till mig och sade:

"Le och var glad, ty det kunde vara värre".

Så jag log, och jag var glad.

Och det blev värre.

 

Länk till kommentar
Dela på andra webbplatser

Magnus Nilsson

???

 

Ok, bandbredden mellan DB och webbserver påverkas ju inte överhuvudtaget om du kör GetRows på webbservern, recordsetet har ju redan skyfflats över.

 

Dessutom är det väl givet (?) att en array som innehåller exakt samma data som ett recordset tar mindre minnesutrymme, så det är ju givetvis att föredra.

 

Det finns liksom en anledning att GetRows rekommenderas när det handlar om prestanda, gör en sökning på google t ex. Första exemplet: www.learnasp.com/learn/whygetrows.asp

 

 

Länk till kommentar
Dela på andra webbplatser

Magnus Ahlkvist
Ok, bandbredden mellan DB och webbserver påverkas ju inte överhuvudtaget om du kör GetRows på webbservern, recordsetet har ju redan skyfflats över.

Nej, det har det inte. Recordsetet hämtas ett antal rader i taget.

 

Dessutom är det väl givet (?) att en array som innehåller exakt samma data som ett recordset tar mindre minnesutrymme, så det är ju givetvis att föredra.

Du har redan skapat ett RecordSet-Objekt. RecordSet-objektet tar upp en liten mängd minne i sig, plus det antal rader som har hämtats. Det är en mängd minne som är upptagen. Gör man sedan GetRows på Recordsetet blir det ytterligare en rätt stor mängd minne som upptas.

 

Det finns liksom en anledning att GetRows rekommenderas när det handlar om prestanda, gör en sökning på google t ex. Första exemplet: www.learnasp.com/learn/whygetrows.asp

Om man ska använda hela resultatsetet är GetRows att föredra av prestandaskäl, eftersom man då ändå måste hämta allt data från RecordSetet till asp-sidan. Men om man - som i det här exemplet - ska använda en rätt liten delmängd är det verkligen en dålig idé att göra det.

 

--

En röst talade till mig och sade:

"Le och var glad, ty det kunde vara värre".

Så jag log, och jag var glad.

Och det blev värre.

 

Länk till kommentar
Dela på andra webbplatser

Hejsan JANspeed,

 

Nu har jag gjort precis som du sa men jag får samma resultat som med det som jag gjorde!

Ett felmeddelande som säger:

 

ADODB.Field error '80020009'

 

Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record.

 

?

 

Koder ser ut såhär:

<%

Set Conn = Server.CreateObject("ADODB.Connection")

Conn.Open "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("../databas/arne.mdb")

 

stmSQL = "Select * From tblNyheter Order By Datum DESC, Tid DESC"

Set Recset = Conn.Execute(stmSQL)

 

%>

 

 

 

<%

Dim Count

Count = 0

Do Until Recset.EOF

Count = Count + 1

Recset.movenext

Loop

 

 

Recset.movefirst

 

If count > 8 Then

 

For I to 4

Recset.MoveNext

Next

 

For I to 6

%>

<tr>

<td align="left"><font color="#333366" face="Verdana, Arial, Helvetica,

 

sans-serif" size="1"><B>-[<%=Recset("Datum")%>]-</B></font>

</td>

</tr>

<TR>

<td align="left" valign="top"><font color="#333366" face="Verdana, Arial,

 

Helvetica, sans-serif" size="1"><BR><B><%=Recset("Nyhet")%><BR><BR><BR><BR></B></font>

</td>

</tr>

 

 

<% Recset.movenext

Next

 

 

else

Do until Recset.EOF

%>

<tr>

<td align="left"><font color="#333366" face="Verdana, Arial, Helvetica,

 

sans-serif" size="1"><B>-[<%=Recset("Datum")%>]-</B></font>

</td>

</tr>

<TR>

<td align="left" valign="top"><font color="#333366" face="Verdana, Arial,

 

Helvetica, sans-serif" size="1"><BR><B><%=Recset("Nyhet")%><BR><BR><BR><BR></B></font>

</td>

</tr>

<% Recset.movenext

loop

 

end if %>

 

-----------

 

Vad är det som kan vara galet? Jag blir helt matt på detta!!! :(

 

//Tomas

_________________________________________________

"Det är när det går långsamt som man förlorar sekunder!"

 

 

Länk till kommentar
Dela på andra webbplatser

Magnus Nilsson

Magnus:

 

Intressant, jag visste inte att recordsetet hämtas ett antal rader i taget. Fast det låter ju rimligt. Har du någon källhänvisning till det?

 

Fast givetvis öppnar man bara ett recordset med relevant data, vilket ju gör problemet irrelevant.

 

Grejen är ju att man stänger recordsetet och connection:et exakt efter att man har gjort GetRows, och frigör de resurserna medan man nu gör vad man vill med den fristående datan i arrayen. Allt enligt credot att man bör stänga connections så fort som möjligt. Nu orkar jag inte göra en jämförelse i det här fallet, men jag kan garantera att en GetRows lösning hade varit effektivare i det här fallet precis som i de flesta andra.

 

Miljarder:

Se till att kolla så att det verkligen är något i Recordsetet, annars får du fel i raden Recset.MoveFirst.

 

Dessutom lär inte "For I to 4" fungera, korrekt syntax är "For I = 1 to 4".

 

Länk till kommentar
Dela på andra webbplatser

Magnus Gladh

...

 

- Magnus

----------------------------------------

Ropen skalla, BBB åt alla

 

[inlägget ändrat 2002-05-10 13:27:28 av Magnus Gladh]

Länk till kommentar
Dela på andra webbplatser

Magnus Ahlkvist
Fast givetvis öppnar man bara ett recordset med relevant data, vilket ju gör problemet irrelevant.

 

I det här fallet var ju just problemet att det inte gick att hitta någon SQL-fråga som bara tog fram ex.vis rad 19-27.

Exempel på användning:

I tabellen Produkter finns 100.000 artiklar. I en sökfunktion finns möjligheten att söka på "%", vilket kommer att ge 100.000 träffar, som vi vill lista 9 produkter i taget.

SQL-frågan körs, och vi tittar på första 9 posterna.

I ditt exempel gör vi GetRows, och får en array med 100.000 poster i, varav vi tittar på de nio första.

I mitt exempel tittar vi på de 9 första och stänger objektet.

 

Användaren klickar sedan vidare några gånger, och hamnar på låt oss säga sidan 200, dvs post 200*9=1800

I mitt exempel använder vi oss av de i ADO inbyggda PageSize och AbsolutePage, mycket smidiga att använda. Sedan presenterar vi exakt 9 poster.

I ditt exempel hämtar vi alla 100.000 poster återigen. etc.

 

Intressant, jag visste inte att recordsetet hämtas ett antal rader i taget. Fast det låter ju rimligt. Har du någon källhänvisning till det?

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adosql/adoprg02_4g33.asp

är en beskrivning av vad Server Cursors är, dvs cursorn stannar på databasservern istället för att tas över till webbservern.

 

 

--

En röst talade till mig och sade:

"Le och var glad, ty det kunde vara värre".

Så jag log, och jag var glad.

Och det blev värre.

 

Länk till kommentar
Dela på andra webbplatser

Magnus Nilsson

Men om du öppnar ett recordset på 100000 poster så får du ju skylla dig själv.

 

Kan du ge mig ett relevant exempel där du vill visa poster 19-27 av 100000, och måste hämta alla 100000?

 

Tillägg:

Dessutom skickar inte SQL-server poster på behovsbasis, utan vräker iväg så många som möjligt så fort som möjligt. Det skall alltså till väldigt många poster eller väldigt dålig nätverkskoppling för att det skall vara någon skillnad med getrows eller inte. Källa: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/acdata/ac_8_con_07_7d6b.asp

 

[inlägget ändrat 2002-05-10 14:21:15 av bonka]

Länk till kommentar
Dela på andra webbplatser

Magnus Ahlkvist

Som jag skrev, en sökfunktion som tillåter sökning med "%", dvs de flesta.

 

Varför inte bara inse att det finns användningsområden för Recordsets istället för arrayer med GetRows?

 

Din länk säger inte att allt skickas på en gång från SQL Server, den säger att SQL Server försöker skicka allt på en gång, men klienten (ADODB.RecordSet i det här fallet) tar emot ett nätverkspaket, och väntar på att ta emot nästa tills den "behöver det", dvs tills man gör MoveNext tillräckligt många gånger.

 

--

En röst talade till mig och sade:

"Le och var glad, ty det kunde vara värre".

Så jag log, och jag var glad.

Och det blev värre.

 

Länk till kommentar
Dela på andra webbplatser

Magnus Nilsson

Själv tolkar jag MS-sidan som att, jo, all data skickas på en gång men läggs i nätverksbuffern på klienten, och därifrån hämtas den vid behov. Och alltså belastar nätverket.

 

Dessutom anser jag fortfarande att en query som returnerar så oerhört mycket irrelevant data är felkonstruerad. Använd SET ROWCOUNT, eller SELECT TOP eller vad vet jag. Du är nog betydligt bättre på SQL än vad jag är.

 

Här är f ö en annan länk som bekräftar mina ideer:

http://www.aspfree.com/authors/robert/view.asp?aid=27

 

Jag antar att det enda som kan avgöra den här dispyten är relevanta prestandatester, men det är det väl ingen av oss som orkar göra.. :)

 

Länk till kommentar
Dela på andra webbplatser

Magnus Ahlkvist
Jag antar att det enda som kan avgöra den här dispyten är relevanta prestandatester, men det är det väl ingen av oss som orkar göra.. :)

Testscript:

<%

server.ScriptTimeout=200

set conn=server.CreateObject("adodb.connection")

conn.open "provider=sqloledb;server=servername;uid=sa;pwd=password;database=pubs"

iOffset=request("offset")

if iOffset="" then iOffset=1

iOffset=cint(iOffset)

set rs=server.CreateObject("adodb.recordset")

rs.Open "select top 1000 * from tTest ORDER BY ID",conn,1,1

if request("type")="getrows" then

response.Write now & "<br>"

aPoster = RS.GetRows

'oRS behövs inte längre:

rs.Close

Set RS = Nothing

conn.Close

If IsArray(aPoster) Then

iMax=iOffset*9+9

For iCounter = iOffset*9 To iMax

Response.Write aPoster(0, iCounter) & " " & aPoster(1, iCounter) & "<br>"

Next

End If

response.Write now & "<br>"

else

dim conn

dim rs

dim iOffset

response.Write now & "<br>"

rs.PageSize=9

rs.AbsolutePage=iOffset

for i=1 to 9

Response.Write rs("ID") & " " & rs("textfield") & "<br>"

rs.Movenext

next

rs.Close

conn.Close

response.Write now & "<br>"

end if

%>

 

 

Förutsättningar:

Hämtar 1000 poster från en tabell i en databasserver som befinner sig på 56K-modems bandbredd bort.

Mäter tiden mellan Response.Write now()-raderna. Har alltså inte med själva rs.open-satsen i tidsmätningen, men det är ju samma SQL som exekveras för båda testerna, så det spelar ingen roll.

Presenterar i webbläsaren post 900-909, dvs scriptet körs med:

scriptname.asp?offset=100

Ingen indatakontroll görs i något av fallen.

Ställde ner bandbredden mellan webserver och dbserver för att överdriva effekten, men principen är densamma oavsett vilket.

Använde oxå select top 1000 för att inte alltför många poster skulle visas, ingen användare vill antagligen stega igenom 10000+ sidor för att hitta den artikel de söker efter, och inte speciellt många sökmotorer tillåter mer än 1000 träffar. Men 1000 rader är ju naturligtvis inte alltför mycket information att skicka.

 

Resultat:

Med GetRows: ca 150 sekunder

Med ADO.PageSize och AbsolutePage: cirka 7 sekunder

 

Alltså finns det tillfällen då man föredrar att använda ADO hela vägen istället för den oftast mer optimerade GetRows och sen använda en Array.

 

--

En röst talade till mig och sade:

"Le och var glad, ty det kunde vara värre".

Så jag log, och jag var glad.

Och det blev värre.

 

Länk till kommentar
Dela på andra webbplatser

Ah. Tror att det kan ha varit jag som skrev fel.

 

Eftersom vi satt som villkor att

 

If count > 8 så betyder det att vi inte kan loopa fram först 4 poster (For I to 4) och sen skriva ut 6 poster (For I to 6) för det blir ju ett total på 10 poster som vi går igenom. Vi har ju bara kontrollerat att det finns >8 = 9 poster i databasen och då kommer den ge error om du skriver ut fler än 9 st poster.

 

Alltså måste du minska "For I to 6" till "For I to 4".

 

E du med?

 

/JANspeed

 

 

 

 

Länk till kommentar
Dela på andra webbplatser

Fungerar i alla fall inte! :(

 

 

_________________________________________________

"Det är när det går långsamt som man förlorar sekunder!"

 

 

Länk till kommentar
Dela på andra webbplatser

Det är bra att vara lat, då behöver man inte anstränga sig så mycket. Jag skummade bara igenom tidigare inlägg litegrann :)

 

Jag skulle ha gjort något sådant här:

(indenterat med _)

function showSome(rs,start,count)
___showSome=0
___dim amountShown, nrNow
___amountShown=0
___nrNow=0

___do while not rs.eof
______nrNow=nrNow+1
______if ((nrNow>=start) and (nrNow<=start+count-1)) then
_________response.write(rs("nyhet")&"<br>")
_________amountShown=amountShown+1
______end if
______if (nrNow>=start+count) then exit do
___rs.movenext
___loop

___showSome=amountShown
end function


set recset = conn.execute(stmSQL)

if (showSome(recset,4,4)=0) then response.write("Nothing to show")

 

Till funktionen showSome skickar du in tre parametrar, ditt recordset, vilken den skall börja visa på, samt hur många den skall visa.

 

Jag har inte testat koden, så den fungerar förmodligen inte :)

 

Ciao,

Anders

 

 

Länk till kommentar
Dela på andra webbplatser

 

Vara lat? Man är för okunnig helt enkelt! :(

 

_________________________________________________

"Det är när det går långsamt som man förlorar sekunder!"

 

 

Länk till kommentar
Dela på andra webbplatser

Prova att lägga in en if sats mellan för att kolla om den räknar för många rader.

 

Typ:

 

For I To 4

If NOT Recset.EOF Then

... Koden som ska skrivas ut

End If

Next

 

Om du fortfarande får ett felmeddelande så vet jag inte riktigt vad som kan vara felet.

 

/JANspeed

 

[r] Ah. självklart ska du inte använda For I To 6 utan For I To 4. [/r]

 

[inlägget ändrat 2002-05-15 10:26:33 av JANspeed]

Länk till kommentar
Dela på andra webbplatser

Arkiverat

Det här ämnet är nu arkiverat och är stängt för ytterligare svar.

×
×
  • Skapa nytt...