在 ASP 搭配 Access 或 SQL Server 時,讀取最新的 N 筆記錄是常見需求 (如最新公告、最新文章)。不同資料庫語法略有差異。
<%
Dim sqlnote2, conn, rs
' 取得最新 8 筆,依 id 遞減排序
sqlnote2 = "SELECT TOP 8 * FROM note1 ORDER BY id DESC"
Call opendb() ' 假設為自訂開啟連線函式
rs.Open sqlnote2, conn, 1, 1 ' adOpenKeyset, adLockReadOnly
If Not rs.EOF Then
Do While Not rs.EOF
%>
<tr>
<td width="5" height="22" align="left" bgcolor="#FFFFFF"> </td>
<td width="169" height="27" align="left" bgcolor="#FFFFFF">
<img src="index_files/dot_email.gif" width="5" height="5" />
<a href="<%=rs("file_path")%>" target="_blank" class="prodcut" title="<%=rs("title")%>">
<%=rs("title")%>
</a>
<%
' 今日發布顯示 NEW 圖示
If rs("send_date") = Date() Then
Response.Write("
")
Else
Response.Write(rs("send_date"))
End If
%>
</td>
<td width="1" height="5" align="left" bgcolor="#FFFFFF"> </td>
</tr>
<%
rs.MoveNext
Loop
%>
<tr>
<td colspan="3" align="right" bgcolor="#FFFFFF">
<a href="note.asp" class="page">更多資訊...</a>
</td>
</tr>
<%
Else
' 無資料時顯示
%>
<tr class="button3">
<td colspan="3" bgcolor="#FFFFFF">暫時沒有通知公告</td>
</tr>
<%
End If
Call closedb()
%>
<%
' SQL Server 語法相同,但支援 TOP N PERCENT
sql = "SELECT TOP 10 PERCENT * FROM Articles ORDER BY PubDate DESC"
' 或搭配 WITH TIES 處理同序值
sql = "SELECT TOP 5 WITH TIES * FROM Products ORDER BY UnitPrice DESC"
%>
<%
' 若使用 MySQL (透過 ODBC/OLEDB)
sql = "SELECT * FROM notes ORDER BY id DESC LIMIT 8"
%>
Function GetPagedRecordset(sql, pageNo, pageSize, conn, dbType)
' dbType: "access", "sqlserver", "mysql"
Dim rs, startRow, endRow, finalSQL
If pageNo < 1 Then pageNo = 1
startRow = (pageNo - 1) * pageSize + 1
endRow = pageNo * pageSize
Select Case LCase(dbType)
Case "access"
' Access 使用子查詢 + TOP 模擬分頁 (效能較差)
finalSQL = "SELECT * FROM (" & _
"SELECT TOP " & pageSize & " * FROM (" & _
"SELECT TOP " & endRow & " * FROM (" & sql & ") " & _
"ORDER BY sortField DESC) " & _
"ORDER BY sortField ASC) " & _
"ORDER BY sortField DESC"
Case "sqlserver"
' SQL Server 2012+ 使用 OFFSET FETCH (標準 SQL)
finalSQL = sql & " ORDER BY sortField OFFSET " & (startRow - 1) & " ROWS FETCH NEXT " & pageSize & " ROWS ONLY"
' SQL Server 2008/2005 使用 ROW_NUMBER()
' finalSQL = "WITH CTE AS (SELECT *, ROW_NUMBER() OVER (ORDER BY sortField) AS rn FROM (" & sql & ")) SELECT * FROM CTE WHERE rn BETWEEN " & startRow & " AND " & endRow
Case "mysql"
finalSQL = sql & " ORDER BY sortField LIMIT " & (startRow - 1) & ", " & pageSize
Case Else
Err.Raise vbObjectError + 513, "GetPagedRecordset", "Unsupported dbType: " & dbType
End Select
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open finalSQL, conn, 1, 1 ' adOpenKeyset, adLockReadOnly
Set GetPagedRecordset = rs
End Function
' 使用範例:
' Dim rsNews
' Set rsNews = GetPagedRecordset("SELECT * FROM News WHERE IsPub=1", 1, 10, conn, "access")
%>
| 參數 | 常數 | 值 | 說明 | 適用情境 |
|---|---|---|---|---|
| CursorType (第3參數) | adOpenForwardOnly | 0 | 僅向前游標,唯讀,效能最好 | 單向讀取、不需分頁、大量資料 |
| adOpenKeyset | 1 | 鍵集游標,可書籤、支援 RecordCount | 需分頁、書籤導航、中等資料量 | |
| adOpenDynamic | 2 | 動態游標,即時反映他人異動 | 高併發、需即時資料、資源消耗大 | |
| adOpenStatic | 3 | 靜態游標,資料快照,可移動 | 需 RecordCount、雙向移動、資料不常變 | |
| LockType (第4參數) | adLockReadOnly | 1 | 唯讀 (預設) | 純查詢、報表、列表頁 |
| adLockPessimistic | 2 | 悲觀鎖定,編輯即鎖定 | 高併發寫入、需資料一致性 | |
| adLockOptimistic | 3 | 樂觀鎖定,Update 時才鎖定 | 一般編輯表單、低併發 | |
| adLockBatchOptimistic | 4 | 批次樂觀鎖定 | 離線編輯、批次更新 |
rs.Open sql, conn, 1, 1 (Keyset + ReadOnly) - 最推薦rs.Open sql, conn, 0, 1 (ForwardOnly + ReadOnly) - 無法取得 RecordCountrs.Open sql, conn, 1, 3 (Keyset + Optimistic) 或 3, 3 (Static + Optimistic)rs.Open sql, conn, 0, 1 + rs.CacheSize = 100SELECT id, title, send_date 而非 SELECT *rs.Close: Set rs = Nothing