asp經(jīng)典入門教程 在ASP中使用SQL 語句第2/2頁
7. ORDER BY
從Access數(shù)據(jù)庫中選取記錄有件最令人喪氣的事情,它們是以怎樣的順序輸入到數(shù)據(jù)庫內(nèi)就按照怎樣的順序出來。就算你在Access環(huán)境內(nèi)采用Sort By來改變記錄視圖,數(shù)據(jù)表內(nèi)的記錄順序也并沒有發(fā)生改變。
如果你正在使用ASPrecordset在網(wǎng)頁上寫出記錄,那么你或許知道亂紛紛的順序是多令人痛苦的事。但是你可能不得不經(jīng)常得面對這一問題,因?yàn)椴⒉淮嬖谑裁春唵畏奖愕慕鉀Q方案。好在ORDER BY 可以簡化這一難題。
為了對你的結(jié)果排序,只要在SELECT語句末尾加上ORDER BY,然后指定你需要排序的參照列即可。因此,如果你想要根據(jù)顧客的姓氏對Customers表排序,那么你可以編寫如下的查詢語句:
SQL = "SELECT c_lastname, c_firstname, c_email FROM Customers ORDER BY c_lastname"
這樣,只要你建立了recordset而且開始把結(jié)果寫到屏幕上,你就會看見數(shù)據(jù)按照字母順序排列起來了。
多級排序
其實(shí)不僅僅可以在SQL語句中進(jìn)行一級排序。實(shí)際上,在很多情況下,你可能會希望指定兩到三級深度的數(shù)據(jù)排序。假設(shè)你有以下數(shù)據(jù)表,其內(nèi)容如下所示:
先前采用的單級ORDER BY 排序是按下面的順序取出數(shù)據(jù)的:
Absurdly Assured
absurd@assured.com
Absolutely Assured
absolutely@assured.com
Crazed Coder
crazy@coder.net
Loosely Fringe
loose@fringe.to
Lunatic Fringe
lune@fringe.to
Hands On
hands@yes.org
顯然ORDER BY 起了應(yīng)有的作用。在實(shí)際的表結(jié)構(gòu)下,Absurdly Assured 是最后的條目,但它排在檢索結(jié)果的最頂端。Hands On記錄排最后因?yàn)?O 在以上列表中排在字母表最后。顯然,Absolutely按照字母表最好排在Absurdly之前。為此,你需要采取第2級ORDER BY 排序標(biāo)準(zhǔn),參照第2列進(jìn)行排序:
SQL = "SELECT c_lastname, c_firstname, c_email FROM Customers ORDER BY
c_lastname, c_firstname"
其結(jié)果將首先按照c_lastname 列排序然后按照c_firstname 列排序。假如你的數(shù)據(jù)表包含的記錄比較多,仔細(xì)設(shè)計排序會令輸出結(jié)果編排更為合理。
投入使用
如果你同大多數(shù)程序員一樣喜歡自己動手編代碼,沉湎于掌握新技術(shù)的狂熱之中。何不從ASP的冗長編碼中轉(zhuǎn)過頭來嘗試一下SQL編碼呢?下面我們將就ASP編程時常見的問題以及如何在ASP中高效地利用SQL語句做一番探討。
建立隨機(jī)生成的HTML代碼是一件相當(dāng)容易實(shí)現(xiàn)的ASP特性。你可能創(chuàng)建過“每日一帖”、滾動廣告等等,只需要稍加點(diǎn)綴就會令你的網(wǎng)站日久彌新。
對存儲在數(shù)據(jù)庫中的數(shù)據(jù)來說,隨機(jī)數(shù)特性能給出上面的效果,但它們可能太慢了些。你不能要求ASP“找個隨機(jī)數(shù)”然后打印出來。實(shí)際上常見的解決方案是建立如下所示的循環(huán):
Randomize
RNumber = Int(Rnd*499) +1
While Not objRec.EOF
If objRec("ID") = RNumber THEN
... 這里是執(zhí)行腳本 ...
end if
objRec.MoveNext
Wend
這很容易理解。首先,你取出1到500范圍之內(nèi)的一個隨機(jī)數(shù)(假設(shè)500就是數(shù)據(jù)庫內(nèi)記錄的總數(shù))。然后,你遍歷每一記錄來測試ID 的值、檢查其是否匹配RNumber。滿足條件的話就執(zhí)行由THEN 關(guān)鍵字開始的那一塊代碼。假如你的RNumber 等于495,那么要循環(huán)一遍數(shù)據(jù)庫花的時間可就長了。雖然500這個數(shù)字看起來大了些,但相比更為穩(wěn)固的企業(yè)解決方案這還是個小型數(shù)據(jù)庫了,后者通常在一個數(shù)據(jù)庫內(nèi)就包含了成千上萬條記錄。這時候不就死定了?
采用SQL,你就可以很快地找出準(zhǔn)確的記錄并且打開一個只包含該記錄的recordset,如下所示:
Randomize
RNumber = Int(Rnd*499) + 1
SQL = "SELECT * FROM Customers WHERE ID = " & RNumber
set objRec = ObjConn.Execute(SQL)
Response.WriteRNumber & " = " & objRec("ID") & " " & objRec("c_email")
不必寫出RNumber 和ID,你只需要檢查匹配情況即可。只要你對以上代碼的工作滿意,你自可按需操作“隨機(jī)”記錄。Recordset沒有包含其他內(nèi)容,因此你很快就能找到你需要的記錄這樣就大大降低了處理時間。
再談隨機(jī)數(shù)
現(xiàn)在你下定決心要榨干Random 函數(shù)的最后一滴油,那么你可能會一次取出多條隨機(jī)記錄或者想采用一定隨機(jī)范圍內(nèi)的記錄。把上面的標(biāo)準(zhǔn)Random 示例擴(kuò)展一下就可以用SQL應(yīng)對上面兩種情況了。
為了取出幾條隨機(jī)選擇的記錄并存放在同一recordset內(nèi),你可以存儲三個隨機(jī)數(shù),然后查詢數(shù)據(jù)庫獲得匹配這些數(shù)字的記錄:
SQL = "SELECT * FROM Customers WHERE ID = " & RNumber & " OR ID = " & RNumber2 & " OR ID = " & RNumber3
假如你想選出10條記錄(也許是每次頁面裝載時的10條鏈接的列表),你可以用BETWEEN 或者數(shù)學(xué)等式選出第一條記錄和適當(dāng)數(shù)量的遞增記錄。這一操作可以通過好幾種方式來完成,但是 SELECT 語句只顯示一種可能(這里的ID 是自動生成的號碼):
SQL = "SELECT * FROM Customers WHERE ID BETWEEN " & RNumber & " AND " & RNumber & "+ 9"
注意:以上代碼的執(zhí)行目的不是檢查數(shù)據(jù)庫內(nèi)是否有9條并發(fā)記錄。如果你需要保證每次選出10條記錄,那么你必須進(jìn)一步設(shè)計查詢。
從某個頁面表單中取出信息是ASP編程中常見的問題。但是,遍歷通過表單傳遞的記錄會花去多長時間呢?這取決于數(shù)據(jù)庫的大小。簡單的GUI界面都可能令循環(huán)遍歷操作耗費(fèi)太多的時間。
比方說,假設(shè)有個團(tuán)隊成員登錄到GUI屏幕輸入自己的名字姓氏和名字之間用點(diǎn)號連接:amy.cowen。這個值通過表單提交,她的當(dāng)前項目列表就從數(shù)據(jù)庫中取了出來并顯示在屏幕上。為了快速地取出用戶的記錄以便顯示在屏幕上,你可以編寫以下代碼。
假設(shè)HTML頁面上包含以下代碼:
<FORM ACTION="login_post.asp" METHOD="POST">
<INPUT TYPE="text" NAME="dotname">
<INPUT TYPE="submit">
</FORM>
在你的login_post.asp 代碼頁上你希望讀取dotname 字段的值,同時找出數(shù)據(jù)庫內(nèi)匹配的記錄:
SQL = "SELECT dotname, ID FROM team WHERE dotname = '" & Request.Form("dotname") & "'"
假如你采用GET 方法,需要把數(shù)據(jù)庫記錄同QueryString中的字段值做比較,那么你可以采用同樣的基本方法:
SQL = "SELECT dotname, ID FROM team WHERE dotname = '" & Request.QueryString("dotname") & "'"
當(dāng)然,你還可以把表單字段的值分配給某個變量并把它插入到你的SQL語句中:
dotname = Request.QueryString("dotname")
SQL = "SELECT dotname, ID FROM team WHERE dotname = '" & dotname &"'"
假如頁面上有很多條記錄,很多情況下,對這些信息按照字母表降序排序會比傳統(tǒng)的升序排序顯示效率更高。采用你熟悉的ORDER BY 子句,你可以很容易地在頁面上增加這一功能,讓用戶控制其記錄顯示的視圖。
假設(shè)你有個頁面的名字叫customers.asp ,頁面執(zhí)行會從Customers表內(nèi)選取全部記錄并按照字母表順序?qū)蛻粜帐吓判?。先前我們已?jīng)看到過排序的代碼了,為了實(shí)現(xiàn)反向排序,你只需要在ORDER BY 表達(dá)式之后加上desc 即可:
SQL = "SELECT c_lastname, c_firstname, c_email FROM Customers ORDER BY c_lastnamedesc"
要在靜態(tài)模式下這也不賴。但是,也許你想修改以上代碼使之提供新的GUI功能:
<A HREF="customers.asp ">Sort Ascending</A> | <A HREF="customers.asp?sort=desc">Sort Descending</A>
<P>
<%
SQL = "SELECT c_lastname, c_firstname, c_email FROM Customers ORDER BY c_lastname " & sort & " "
set objRec = objConn.Execute(SQL)
While Not objRec.EOF
Response.WriteobjRec("c_lastname") & ", " & objRec("c_firstname") & "
" & objRec("c_email") & "<P>"
objRec.MoveNext
Wend
%>
以上代碼最開頭的鏈接允許用戶修改頁面的視圖。你可以重載同一頁面來查看這些信息,但是,在Sort Descending鏈接的情況下,頁面會給sort 變量賦值。然后,在SQL語句內(nèi)就沒有指定desc而是采用 sort 變量的值。
下面要做的就是讀取頁面頂部sort 的值。
<%
sort = Request.Querystring("sort")
%>
以上代碼從URL中檢出sort的可用值。
并沒有令你費(fèi)太多的功夫,你還可以調(diào)整同一頁面允許用戶對特定的列排序。簡單的SELECT 菜單表單控件列出SORT BY 選項可能是一個更方便的措施。
確定數(shù)據(jù)庫內(nèi)有多少記錄,或者確定有多少記錄達(dá)到了某些標(biāo)準(zhǔn),這些用ASP完成并非難事。如果你采用了正確的游標(biāo)類型,你可以用RecordCount 屬性獲得記錄數(shù)當(dāng)然也可以用recordset。但是,有個更簡單的辦法,這就是在自己的SELECT語句中采用count(*) ,代碼如下所示:
SQL = "SELECT count(*) FROM Customers"
或者
SQL = "SELECT count(*) FROM Customers WHERE c_lastname LIKE 'A%'"
舉例說明,以下代碼將選出一些記錄以及這些記錄的總數(shù):
SQL = "SELECT c_firstname, c_lastname, count(*) FROM Customers WHERE c_lastname LIKE 'A%'"
但是你不能實(shí)現(xiàn)自己的目的。這里采用的“count”函數(shù)其實(shí)是一種集合函數(shù),意思是只返回單行信息:回答你提出的問題。對第1個SELECT 語句來說,問題是“在客戶表內(nèi)有多少條記錄?”查詢返回單一的值作為響應(yīng),因此它不能同你常規(guī)的查詢相組合。假如你希望得到其他數(shù)據(jù),你需要采用RecordCount。
集合函數(shù)除了“count”之外還包括AVG、MIN、MAX和SUM等。
12. 連接
任何熟悉SQL和關(guān)系數(shù)據(jù)庫的人都遇見過大量的連接類型。最簡單的說,連接(join)會把兩個表的內(nèi)容組合到一個虛擬表或者recordset內(nèi)。假如數(shù)據(jù)表有效地規(guī)一化,或許你會經(jīng)常從某一個表中選出特定的信息再從另一個表中選出關(guān)聯(lián)信息。這樣做就需要簡單的“同等連接(equijoin)”。
為了了解實(shí)際的連接操作,現(xiàn)在讓我們假設(shè)在一個數(shù)據(jù)庫內(nèi)存放了某類軟件的相關(guān)記錄。某個表(Software)包含了軟件產(chǎn)品的名稱、軟件的版本以及其他有關(guān)細(xì)節(jié):
另一個表(Releases)則存儲了軟件發(fā)布?xì)v史的信息,其中包括發(fā)布日期和發(fā)布狀態(tài)等(比如測試版、當(dāng)前版、過時等):
上表中還包含了一個列,內(nèi)容指向軟件表中采用的ID號。所以,通過這種索引軟件表的方式,你就知道發(fā)布表中software_ID 等于 2的軟件是Rome。
你采用連接組合信息,這樣就不需要在兩個表之間來回折騰了。不過,除了組合信息之外還可以通過連接把有關(guān)信息合并。這樣,只要發(fā)布表內(nèi)的software_ID 匹配軟件表內(nèi)的ID,你就把匹配信息一起放到一個記錄內(nèi)。
代碼如下:
SQL = "SELECT * FROM Software, Releases WHERE software.ID = releases.softwareID"
仔細(xì)分析以上的語句,首先注意到兩個表名列在了FROM的后面。再根據(jù)所采用的連接,今后你可能還會發(fā)現(xiàn)語法會有所變化(或者連接類型有變),但是以上的語法是最基本的,顯示了數(shù)據(jù)的聯(lián)合選擇方式。這里的WHERE 子句用來比較特定的ID值。在Software 表內(nèi),存在ID 列。同樣的,Releases 表內(nèi)則有個software_ID 列。為了明確你在WHERE 子句里要比較的值,你用表名作為前綴,后面還加上了一個點(diǎn)號(.)。
以下是連接選取數(shù)據(jù)之后的結(jié)果:
注意:在創(chuàng)建連接的時候要仔細(xì)考慮選出數(shù)據(jù)的列。以上代碼采用 * 通配符是為了讓讀者關(guān)注于SELECT 代碼行的其他部分。但是,正如你從上圖看到的那樣,你無法選出softwareID 列,因?yàn)檫@一列沒有作為recordset部分的增加值。它的作用就是為WHERE 子句所用。
相關(guān)文章
asp Access數(shù)據(jù)備份,還原,壓縮類代碼
asp Access數(shù)據(jù)備份,還原,壓縮類實(shí)現(xiàn)代碼,大家可以參考下。2009-11-11使用 Osql 工具管理 SQL Server 桌面引擎 (MSDE 2000)應(yīng)用介紹
SQL Server 桌面引擎(也叫 MSDE 2000)沒有自己的用戶界面,因?yàn)樗饕O(shè)計為在后臺運(yùn)行2012-11-11用ASP和SQL實(shí)現(xiàn)基于Web的事件日歷
用ASP和SQL實(shí)現(xiàn)基于Web的事件日歷...2006-09-09SQL Server--怎樣用ADO在SQL SERVER中建庫,建表
SQL Server--怎樣用ADO在SQL SERVER中建庫,建表...2006-08-08在線數(shù)據(jù)庫管理工具(db007) v1.5
以視圖界面方式在線處理access、sql數(shù)據(jù)庫的一個asp工具,需要的朋友可以試試2006-09-09為什么ASP中執(zhí)行動態(tài)SQL總報錯誤信息?提示語句語法錯誤
為什么ASP中執(zhí)行動態(tài)SQL總報錯誤信息?提示語句語法錯誤...2007-04-04用Asp備份與恢復(fù)SQL Server 數(shù)據(jù)庫
用Asp備份與恢復(fù)SQL Server 數(shù)據(jù)庫...2006-08-08asp Driver和Provider兩種連接字符串連接Access時的區(qū)別
Microsoft OLE DB Provider for ODBC Drivers 錯誤 '80040e21' 多步 OLE DB 操作產(chǎn)生錯誤。如果可能,請檢查每個 OLE DB 狀態(tài)值。沒有工作被完成。2009-12-12