如果你熟悉Internet 引擎,那麼你已經熟悉查詢了。你使用查詢來取得滿足特定條件的信息。例如,如果你想找到有ASP信息的全部站點,你可以連接到 Yahoo!並執行一個對Active Sever Pages的搜索。在你輸入這個查詢後,你會收到一個列表,表中包括所有其描述中包含搜索表達式的站點。
多數Internet 引擎允許邏輯查詢。在邏輯查詢中,你可以包括特殊的運算符如AND、OR和NOT,你使用這些運算符來選擇特定的記錄。例如,你可以用AND來限制查詢結果。如果你執行一個對Active Sever Pages AND SQL的搜索。你將得到其描述中同時包含Active Sever Pages 和SQL的記錄。當你需要限制查詢結果時,你可以使用AND。
如果你需要擴展查詢的結果,你可以使用邏輯操作符OR。例如,如果你執行一個搜索,搜索所有的其描述中包含Active Sever Pages OR SQL的站點,你收到的列表中將包括所有其描述中同時包含兩個表達式或其中任何一個表達式的站點。
如果你想從搜索結果中排除特定的站點,你可以使用NOT。例如,查詢“Active Sever Pages ”AND NOT “SQL”將返回一個列表,列表中的站點包含Active Sever Pages,但不包含SQL。當必須排除特定的記錄時,你可以使用NOT。
用SQL執行的查詢與用Internet搜索引擎執行的搜索非常相似。 當你執行一個SQL查詢時,通過使用包括邏輯運算符的查詢條件,你可以得到一個記錄列表。此時查詢結果是來自一個或多個表。
SQL查詢的句法非常簡單。假設有一個名為email_table 的表,包含名字和地址兩個字段,要得到Bill Gates 的e_mail地址,你可以使用下面的查詢:
SELECT email from email_table WHERE name="Bill Gates"
當這個查詢執行時,就從名為email_table的表中讀取Bill Gates的e_mail 地址。這個簡單的語句包括三部分:
■ SELECT語句的第一部分指名要選取的列。在此例中,只有email列被選取。當執行 時,只顯示email列的值 [email protected]。
■ SELECTT語句的第二部份指明要從哪個(些)表中查詢數據。在此例中,要查詢的表名為email_table 。
■ 最後,SELECT語句的WHERE子句指明要選擇滿足什麼條件的記錄。在此例中,查詢條件為只有name列的值為Bill Gates 的記錄才被選取。
Bill Gates很有可能擁有不止一個email地址。如果表中包含Bill Gates的多個email地址。用上述的SELECT語句可以讀取他所有的email地址。SELECT語句從表中取出所有name字段值為Bill Gates 的記錄的email 字段的值。
前面說過,查詢可以在查詢條件中包含邏輯運算符。假如你想讀取Bill Gates 或Clinton總統的所有email地址,你可以使用下面的查詢語句:
SELECT email FROM email_table WHERE name="Bill Gates" OR
name="president Clinton"
此例中的查詢條件比前一個復雜了一點。這個語句從表email_table中選出所有name列為Bill Gates或president Clinton的記錄。如果表中含有Bill Gates或president Clinton的多個地址,所有的地址都被讀取。
SELECT語句的結構看起來很直觀。如果你請一個朋友從一個表中為你選擇一組記錄,你也許以非常相似的方式提出你的要求。在SQL SELECT語句中,你“SELECT
如果一切正常,在你單擊連接按鈕後會出現一個查詢窗口,如圖10.2所示。(如果有異常,請參考第三章)
圖10.2
在執行查詢之前,你需要選擇數據庫。安裝 SQL Sever時你已為自己創建了一個數據庫,SQL Sever還有許多系統數據庫,如master,model,msdb,和tempdb。
方便的是,SQL Sever帶有一個特殊的名為pubs的例子數據庫。庫 pubs中包含供一個虛擬的出版商使用的各個表。文檔中所有的例子程序都是針對這個庫來設計的。本書中的許多例子也使用這個數據庫。
在查詢窗口頂部的DB下拉框中選擇數據庫pubs,這樣你就選擇了數據庫。你所有的查詢都將針對這個庫中的各個表來執行。現在你可以執行你的第一個查詢了。這真讓人興奮!
你的第一個查詢將針對一個名為autrors的表,表中包含所有為某個虛擬出版商工作的作者的相關數據。單擊查詢窗口並輸入以下的語句:
SELECT phone FROM authors WHERE au_name="Ringer"
輸入完成後,單擊執行查詢按鈕(一個綠色三角形,看起來像VCR播放鍵)。單擊此按鈕後,任何出現在查詢窗口中的語句均會被執行。查詢窗口會自動變成結果顯示窗口,你可以看到查詢的結果(見圖10.3)。
你看到的查詢結果也許與圖10.3所示的不同。在SQL Sever的不同版本中,庫pubs中的數據會有所不同。對SQL Sever 6.5來說,將會找到兩條記錄。結果顯示窗口中應顯示如下內容:
phone
……………….
801 826_0752
801 826_0752
(2 row(s) affected)
圖10.3
你所執行的SELECT語句從表authors中取出所有名字為Ringer的作者的電話號碼。你通過在WHERE子句中使用特殊的選擇條件來限制查詢的結果。你也可以忽略選擇條件,從表中取出所有作者的電話號碼。要做到這一點,單擊Query標簽,返回到查詢窗口,輸入以下的SELECT語句:
SELECT Phone
要做到這一點的途徑之一是創建第三個表,專門用來描述另外兩個表的字段之間的關系。
表authors有一個名為au_id的字段,包含有每個作者的唯一標識。表titles有一個名為title_id的字段,包含每個書名的唯一標識。如果你能在字段au_id和字段title_id 之間建立一個關系,你就可以關聯這兩個表。數據庫pubs中有一個名為titleauthor的表,正是用來完成這個工作。表中的每個記錄包括兩個字段,用來把表titles和表authors關聯在一起。下面的SELECT語句使用了這三個表以得到正確的結果:
SELECT au_name,title FROM authors,titles,titleauthor
WHERE authors.au_id=titleauthor.au_id
AND titles.title_id=titleauthor.title_id
當這個SELECT語句執行時,每個作者都將與正確的書名相匹配。表titleauthor指明了表authors和表titles的關系,它通過包含分別來自兩個表的各一個字段實現這一點。第三個表的唯一目的是在另外兩個表的字段之間建立關系。它本身不包含任何附加數據。
注意在這個例子中字段名是如何書寫的。為了區別表authors和表titles中相同的字段名au_id,每個字段名前面都加上了表名前綴和一個句號。名為author.au_id 的字段屬於表authors,名為titleauthor.au_id的字段屬於表titleauthor,兩者不會混淆。
通過使用第三個表,你可以在兩個表的字段之間建立各種類型的關系。例如,一個作者也許寫了許多不同的書,或者一本書也許由許多不同的作者共同完成。當兩個表的字段之間有這種“多對多”的關系時,你需要使用第三個表來指明這種關系。
但是,在許多情況下,兩個表之間的關系並不復雜。比如你需要指明表titles和表publishers之間的關系。因為一個書名不可能與多個出版商相匹配,你不需要通過第三個表來指明這兩個表之間的關系。要指明表titles和表publishers之間的關系,你只要讓這兩個表有一個公共的字段就可以了。在數據庫pubs中,表titles和表publishers都有一個名為pub_id的字段。如果你想得到書名及其出版商的一個列表,你可以使用如下的語句:
SELECT title,pub_name FRO
r>11.95 23.90
2.99 5.98
19.99 39.98
…
(18 row(s) affected)
你可以使用大多數標准的數學運算符來操作字段值,如加(+),減(-),乘(*)和除(/)。你也可以一次對多個字段進行運算,例如:
SELECT price*ytd_sales "total revenue" FROM titles
在這個例子中,通過把價格與銷售量相乘,計算出了每種書的總銷售額。這個SELECT語句的結果將是這樣的:
total revenue
……………………………………………..
81,859,05
46,318,20
55,978,78
81,859,05
40,619,68
…
(18 row(s) affected)
最後,你還可以使用連接運算符(它看起來像個加號)來連接兩個字符型字段:
SELECT au_fname+" "+au_lname "author name" FROM authors
在這個例子中,你把字段au_fname和字段au_lname粘貼在一起,中間用一個逗號 隔開,並把查詢結果的標題指定為author name。這個語句的執行結果將是這樣的:
author names
…………………………………………………………
Johnson White
MarjorIE Green
Cheryl Carson
Michael O’Leary
Dean Straight
…
(23 row(s) affected)
可以看到,SQL為你提供了對查詢結果的許多控制。你應該在ASP編程過程中充分利用這些優點。使用SQL來操作查詢結果幾乎總是比使用有同樣作用的腳本效率更高。
排序查詢結果
本章的介紹中曾強調過,SQL表沒有內在的順序。例如,從一個表中取第二個記錄是沒有意義的。從SQL的角度看來,沒有一個記錄在任何其他記錄之前。
然而,你可以操縱一個SQL查詢結果的順序。在缺省情況下,當記錄從表中取出時,記錄不以特定的順序出現。例如,當從表authors中取出字段au_lname時,查詢結果顯示成這樣:
au_lname
…………………………………….
White
Green
Carson
O’Leary
Straight
…
(23 row(s) affected)
看一列沒有特定順序的名字是很不方便的。如果把這些名字按字母順序排列,讀起來就會容易得多。通過使用ORDER BY子句,你可以強制一個查詢結果按升序排列,就像這樣:
SELECT au_lname FROM authors ORDER BY au_lname
當這個SELECT語句執行時,作者名字的顯示將按字母順序排列。ORDER BY子句將作者名字按升序排列。
你也可以同時對多個列使用ORDER BY子句。例如,如果你想同時按升序顯示字段au_lname和字段au_fname,你需要對兩個字段都進行排序:
SELECT au_lname,au_fname FROM authors ORDER BY au_lname ,au_fname
這個查詢首先把結果按au_lname字段進行排序,然後按字段au_fname排序。記錄將按如下的順序取出:
au_lname au_fname
…………………………………………………………………….
Bennet Abraham
Ringer Albert
Ringer Anne
Smith Meander
…
(23 row(s) affected)
注意有兩個作者有相同的名字Ringer。名為Albert Ringer的作者出現名為Anne Ringer的作者之前,這是因為姓Albert按字母順序應排在姓Anne之前。
如果你想把查詢結果按相反的順序排列,你可以使用關鍵字DESC。關鍵字DESC把查詢結果按降序排列,如下例所示:
SELECT au_lname,au_fname FROM authors
WHERE au_lname=”Ringer” ORDER BY au_lname ,au_fname DESC
例如,如果你想按降序取出所有書的價格,你可以使用如下的SQL查詢:
SELECT price FROM titles ORDER BY price DESC
這個SELECT語句從表中取出所有書的價格,顯示結果時,價格低的書先顯示,價格高的書後顯示。
警告:
不是特別需要時,不要對查詢結果進行排序,因為服務器完成這項工作要費些力氣。這意味著帶有ORDER BY 子句的SELECT語句執行起來比一般的SELECT語句花的時間長。
取出互不相同的記錄
一個表有可能在同一列中有重復的值。例如,數據庫pubs的表authors中有兩個作者的名字是Ringer。如果你從這個表中取出所有的名字,名字Ringer將會顯示兩次。
在特定情況下,你可能只有興趣從一個表中取出互不相同的值。如果一個字段有重復的值,你也許希望每個值只被選取一次,你可以使用關鍵字DISTINCT來做到這一點:
SELCET D
comments TEXT,entrydate
DATETIME)
在這個例子中,字段visitor的數據類型為VARCHAR。注意跟在數據類型後面的括號中的數字。這個數字指定了這個字段所允許存放的字符串的最大長度。在這個例子中,字段visitor能存放的字符串最長為四十個字符。如果名字太長,字符串會被截斷,只保留四十個字符。
VARCHAR類型可以存儲的字符串最長為255個字符。要存儲更長的字符串數據,可以使用文本型數據(下一節中講述)。
另一種字符型數據用來存儲固定長度的字符數據。下面是一個使用這種數據類型的例子:
CREATE TABLE guestbook (visitor CHAR(40),comments TEXT,entrydate
DATETIME)
在這個例子中,字段visitor被用來存儲四十個字符的固定長度字符串。表達式CHAR指定了這個字段應該是固定長度的字符串。
VARCHAR型和CHAR型數據的這個差別是細微的,但是非常重要。假如你向一個長度為四十個字符的VARCHAR型字段中輸入數據Bill Gates。當你以後從這個字段中取出此數據時,你取出的數據其長度為十個字符——字符串Bill Gates的長度。
現在假如你把字符串輸入一個長度為四十個字符的CHAR型字段中,那麼當你取出數據時,所取出的數據長度將是四十個字符。字符串的後面會被附加多余的空格。
當你建立自己的站點時,你會發現使用VARCHAR型字段要比CHAR型字段方便的多。使用VARCHAR型字段時,你不需要為剪掉你數據中多余的空格而操心。
VARCHAR型字段的另一個突出的好處是它可以比CHAR型字段占用更少的內存和硬盤空間。當你的數據庫很大時,這種內存和磁盤空間的節省會變得非常重要。
文本型數據
字符型數據限制了字符串的長度不能超過255個字符。而使用文本型數據,你可以存放超過二十億個字符的字符串。當你需要存儲大串的字符時,應該使用文本型數據。
這裡有一個使用文本型數據的例子:
CREATE TABLE guestbook (visitor VARCHAR(40),comments TEXT,entrydate
DATETIME)
在這個例子中,字段comments被用來存放訪問者對你站點的意見。注意文本型數據沒有長度,而上一節中所講的字符型數據是有長度的。一個文本型字段中的數據通常要麼為空,要麼很大。
當你從Html form的多行文本編輯框(TEXTAREA)中收集數據時,你應該把收集的信息存儲於文本型字段中。但是,無論何時,只要你能避免使用文本型字段,你就應該不適用它。文本型字段既大且慢,濫用文本型字段會使服務器速度變慢。文本型字段還會吃掉大量的磁盤空間。
警告:
一旦你向文本型字段中輸入了任何數據(甚至是空值),就會有2K的空間被自動分配給該數據。除非刪除該記錄,否則你無法收回這部分存儲空間。
數值型數據
SQL Sever支持許多種不同的數值型數據。你可以存儲整數、小數、和錢數。
通常,當你需要在表中的存放數字時,你要使用整型(INT)數據。INT型數據的表數范圍是從-2,147,483,647到2,147,483,647的整數。下面是一個如何使用INT型數據的例子:
CREATE TABLE visitlog (visitor VARCHAR(40),numvisits INT)
這個表可以用來記錄你站點被訪問的次數。只要沒有人訪問你的站點超過2,147,483,647次,nubvisits字段就可以存儲訪問次數。
為了節省內存空間,你可以使用SMALLINT型數據。SMALLINT 型數據可以存儲從-32768到32768的整數。這種數據類型的使用方法與INT型完全相同。
最後,如果你實在需要節省空間,你可以使用TINYINT型數據。同樣,這種類型的使用方法也與INT型相同,不同的是這種類型的字段只能存儲從0到255的整數。TINYINT型字段不能用來存儲負數。
通常,為了節省空間,應該盡可能的使用最小的整型數據。一個TINYINT型數據只占用一個字節;一個INT型數據占用四個字節。這看起來似乎差別不大,但是在比較大的表中,字節數的增長是很快的。另一方面,一旦你已經創建了一個字段,要修改它是很困難的。因此,為安全起見,你應該預測以下,一個字段所需要存儲的數值最大有可能是多大,然後選擇適當的數據類型。
為了能對字段所存放的數據有更多的控制,你可以使用NUMERIC型數據來同時表示一個數的整數部分和小數部分。NUMERIC型數據使你能表示非常大的數——比INT型數據要大得多。一個NUMERIC型字段可以存儲從-1038到1038范圍內的數。NUMERIC型數據還使你能表示有小數部分的數。例如,你可以在NUMERIC型字段中存儲小數3.14
fraction NUMERIC (5,4) )
當這個語句執行時,將創建一個名為numeric_data的包含兩個字段的表。字段bignumber可以存儲直到28位的整數。字段fraction可以存儲有五位整數部分和四位小數部分的小數。
一個NUMERIC型數據的整數部分最大只能有28位,小數部分的位數必須小於或等於整數部分的位數,小數部分可以是零。
你可以使用INT型或NUMERIC型數據來存儲錢數。但是,專門有另外兩種數據類型用於此目的。如果你希望你的網點能掙很多錢,你可以使用MONEY型數據。如果你的野心不大,你可以使用SMALLMONEY型數據。MONEY型數據可以存儲從-922,337,203,685,477.5808到922,337,203,685,477.5807的錢數。如果你需要存儲比這還大的金額,你可以使用NUMERIC型數據。
SMALLMONEY型數據只能存儲從-214,748.3648到214,748.3647 的錢數。同樣,如果可以的話,你應該用SMALLMONEY型來代替MONEY型數據,以節省空間。下面的例子顯示了如何使用這兩種表示錢的數據類型:
CREATE TABLE products (product VARCHAR(40),price M
如果你指定一個字段不能接受空值,那麼當你試圖輸入一個空值時,會有錯誤警告。這些錯誤警告可以為程序調試提供有價值的線索。
缺省值
假設有一個存儲地址信息的表,這個表的字段包括街道、城市、州、郵政編碼和國家。如果你預計地址的大部分是在美國,你可以把這個值作為country字段的缺省值。
為了在創建一個表時指定缺省值,你可以使用表達式DEFAULT。請看下面這個在創建表時使用缺省值的例子:
CREATE TABLE addresses (street VARCHAR(60) NULL,
city VARCHAR(40) NULL,
state VARCHAR(20) NULL
zip VARCHAR(20) NULL,
country VARCHAR(30) DEFAULT ‘USA’)
在這個例子中,字段country的缺省值被指定為美國。注意單引號的使用,引號指明這是字符型數據。為了給非字符型的字段指定缺省值,不要把該值擴在引號中:
CREATE TABLE orders(price MONEY DEFAULT $38.00,