吾嘗終日而思矣,不如須臾之所學也
SQL語法大全
為了建立互動站點,你需要使用資料庫來儲存來自訪問者的資訊。例如,你要建立一個職業介紹服務的站點,你就需要儲存諸如個人簡歷,所感興趣的工作等等這樣的資訊。建立動態網葉也需要使用資料庫,如果你想顯示符合來訪者要求的最好的工作,你就需要從資料庫中取出這份工作的資訊。你將會發現,在許多情況下需要使用資料庫。
在這一章裡,你將學會怎樣使用“結構化查詢語言”(SQL〕來操作資料庫。SQL語言是資料庫的標準語言。在Active Sever Pages 中,無論何時你要訪問一個數據庫,你就要使用SQL語言。因此,掌握好SQL對ASP程式設計是非常重要的。
注意:
你可以把“SQL”讀作“sequel”,也可以按單個字母的讀音讀作S-Q-L。 兩種發音都是正確的,每種發音各有大量的支持者。在本書裡,認為“SQL”讀作“sequel”。
通過這一章的學習,你將理解怎樣用SQL實現資料庫查詢,你將學會怎樣使用這種查詢從資料表中取出資訊,最後,你將學會怎樣設計和建立自己的資料庫。
注意:
通過下面幾章對SQL的介紹,你將對SQL有足夠的瞭解,從而可以有效地使用Active Sever Pages。但是,SQL是一種複雜的語言,本書不可能包括它的全部細節。要全面掌握SQL語言,你需要學習在Microsoft SQL Sever 中使用SQL。你可以到附近的書店去買一本Microsoft SQL Sever 6.5。
SQL介紹:
本書假設你是在SQL操作Microsoft SQL Sever 的資料庫。你也可以用SQL操作許多其它型別的資料庫。SQL是操作資料庫的標準語言。(事實上,關於SQL語言有一個專門的ANSI標準〕
注意:
不要在你的站點上試圖用Microsoft Access代替Microsoft SQL Sever。SQL Sever可以同時服務於許多使用者,如果你希望你的站點有較高的訪問率,MSAccess是不能勝任的。
在學習SQL的細節之前,你需要理解它的兩大特點。一個特點容易掌握,另一個掌握起來有點困難。
第一個特點是所有SQL資料庫中的資料都儲存在表中。一個表由行和列組成。例如,下面這個簡單的表包括name和e-mail address:
Name Email Address
................................................................
Bill Gates [email protected]
president Clinton [email protected]
StephenWalther [email protected]
這個表有兩列(列也稱為欄位,域〕:Name和Email Address。有三行,每一行包含一組資料。一行中的資料組合在一起稱為一條記錄。
無論何時你向表中新增新資料,你就添加了一條新記錄。一個數據表可以有幾十個記錄,也可以有幾千甚至幾十億個記錄。雖然你也許永遠不需要儲存十億個Email地址,但知道你能這樣做總是好的,也許有一天你會有這樣的需要。
你的資料庫很有可能包含幾十個表,所有儲存在你資料庫中的資訊都被儲存在這些表中。當你考慮怎樣把資訊儲存在資料庫中時,你應該考慮怎樣把它們儲存在表中。
SQL的第二個特點有些難於掌握。這種語言被設計為不允許你按照某種特定的順序來取出記錄,因為這樣做會降低SQL Sever取記錄的效率。使用SQL,你只能按查詢條件來讀取記錄。
當考慮如何從表中取出記錄時,自然會想到按記錄的位置讀取它們。例如,也許你會嘗試通過一個迴圈,逐個記錄地掃描,來選出特定的記錄。在使用SQL時,你必須訓練自己,不要有這種思路。
假如你想選出所有的名字是“Bill Gates”的記錄,如果使用傳統的程式語言,你也許會構造一個迴圈,逐個查看錶中的記錄,看名字域是否是“Bill Gates”。
這種選擇記錄的方法是可行的,但是效率不高。使用SQL,你只要說,“選擇所有名字域等於Bill Gates的記錄”,SQL就會為你選出所有符合條件的記錄。SQL會確定實現查詢的最佳方法。
建設你想取出表中的前十個記錄。使用傳統的程式語言,你可以做一個迴圈,取出前十個記錄後結束迴圈。但使用標準的SQL查詢,這是不可能實現的。從SQL的角度來說,在一個表中不存在前十個記錄這種概念。
開始時,當你知道你不能用SQL實現某些你感覺應該能實現的功能,你會受到挫折。你也許會以頭撞牆甚至想寫惡毒的信件給SQL的設計者們。但後來你會認識到,SQL的這個特點不僅不是個限制,反而是其長處。因為SQL不根據位置來讀取記錄,它讀取記錄可以很快。
綜上所述,SQL有兩個特點:所有資料儲存在表中,從SQL的角度來說,表中的記錄沒有順序。在下一節,你將學會怎樣用SQL從表中選擇特殊的記錄。
使用SQL從表中取記錄。
SQL的主要功能之一是實現資料庫查詢。如果你熟悉Internet 引擎,那麼你已經熟悉查詢了。你使用查詢來取得滿足特定條件的資訊。例如,如果你想找到有ASP資訊的全部站點,你可以連線到 Yahoo!並執行一個對Active Sever Pages的搜尋。在你輸入這個查詢後,你會收到一個列表,表中包括所有其描述中包含搜尋表示式的站點。
多數Internet 引擎允許邏輯查詢。在邏輯查詢中,你可以包括特殊的運算子如AND、OR和NOT,你使用這些運算子來選擇特定的記錄。例如,你可以用AND來限制查詢結果。如果你執行一個對Active Sever Pages AND SQL的搜尋。你將得到其描述中同時包含Active Sever Pages 和SQL的記錄。當你需要限制查詢結果時,你可以使用AND。
如果你需要擴充套件查詢的結果,你可以使用邏輯操作符OR。例如,如果你執行一個搜尋,搜尋所有的其描述中包含Active SeverPages 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 WHEREname="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特定的列FROM一個表WHERE某些列滿足一個特定的條件”。
下一節將介紹怎樣執行SQL查詢來選取記錄。這將幫助你熟悉用SELECT語句從表中取資料的各種不同方法。
使用ISQL執行SELECT查詢
當你安裝SQL Sever時,你同時安裝了一個叫作ISQL/w的應用程式。ISQL/w允許你執行互動的SQL查詢。在把查詢包括到你的ASP網頁中之前,用ISQL/w對其進行測試是非常有用的。
注意:
在這本書的第一部份,你學習了怎樣安裝和配置Microsoft SQL Sever 。如果沒有安裝SQL Sever或者SQL Sever不能執行,請參閱第三章“安裝和使用SQL Sever”。
選擇任務上SQL Sever程式組中的ISQL_w以啟動該程式。程式啟動時,首先會出現一個對話方塊,要求輸入伺服器資訊和登入資訊(見圖10.1)。在Sever框中,輸入你的SQL伺服器的名字。如果伺服器正執行在本地計算機上,伺服器名字就是你計算機的名字。在登入資訊框中,輸入一個登入帳號和密碼或選擇使用“可信連線”,然後單擊Connect按鈕。
圖10。1
注意:
如果你將SQL Sever配置為使用完整安全或混合安全,那麼你可以使用可信連線。如果你使用標準安全,你則需要提供使用者帳號和密碼。要了解更多資訊,參見第三章。
如果一切正常,在你單擊連線按鈕後會出現一個查詢視窗,如圖10.2所示。(如果有異常,請參考第三章)
圖10.2
在執行查詢之前,你需要選擇資料庫。安裝 SQL Sever時你已為自己建立了一個數據庫,SQL Sever還有許多系統資料庫,如master,model,msdb,和tempdb。
方便的是,SQL Sever帶有一個特殊的名為pubs的例子資料庫。庫 pubs中包含供一個虛擬的出版商使用的各個表。文件中所有的例子程式都是針對這個庫來設計的。本書中的許多例子也使用這個資料庫。
在查詢視窗頂部的DB下拉框中選擇資料庫pubs,這樣你就選擇了資料庫。你所有的查詢都將針對這個庫中的各個表來執行。現在你可以執行你的第一個查詢了。這真讓人興奮!
你的第一個查詢將針對一個名為autrors的表,表中包含所有為某個虛擬出版商工作的作者的相關資料。單擊查詢視窗並輸入以下的語句:
SELECT phone FROM authors WHEREau_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語句:
SELECTPhone FROM authors
這個查詢執行後,會取出表authors中的所有電話號碼(沒有特定的順序)。如果表authors中包含一百個電話號碼,會有一百個記錄被取出,如果表中有十億個電話號碼,這十億條記錄都會被取出(這也許需要一些時間)。
表authrs的欄位包括姓,名字,電話號碼,地址,城市,州和郵政編碼。通過在SELECT語句的第一部份指定它們,你可以從表中取出任何一個欄位。你可以在一個SELECT語句中一次取出多個欄位,比如:
SELECT au_fname ,au_lname, phone FROMauthors
這個SELECT語句執行後,將取出這三個列的所有值。下面是這個查詢的結果的一個示例(為了節省紙張,只顯示查詢結果的一部分,其餘記錄用省略號代替):
au_fname au_lname phone
………………………………………………………………………….
Johnson White 408 496_7223
Marjorie Green 415 986_7020
Cheryl Carson 415 548_7723
Michael O’Leary 408 286_2428
…
(23 row(s) affected)
在SELECT語句中,你需要列出多少個欄位,你就可以列出多少。不要忘了把欄位名用逗號隔開。你也可以用星號(*)從一個表中取出所有的欄位。這裡有一個使用星號的例子:
SELECT * FROM authors
這個SELECT語句執行後,表中的所有欄位的值都被取出。你會發現你將在SQL查詢中頻繁使用星號。
技巧:
你可以使用星號來檢視一個表的所有列的名字。要做到這一點,只需要在執行完SELECT語句後看一下查詢結果的列標題。
操作多個表
到現在為止,你只嘗試了用一句SQL查詢從一個表中取出資料。你也可以用一個SELECT語句同時從多個表中取出資料,只需在SELECT語句的FROM從句中列出要從中取出資料的表名稱即可:
SELECT au_lname ,title FROM authors, titles
這個SELECT語句執行時,同時從表authors和表titles中取出資料。從表authors中取出所有的作者名字,從表titles中取出所有的書名。在ISQL/w程式中執行這個查詢,看一下查詢結果。你會發現一些奇怪的出乎意料的情況:作者的名字並沒有和它們所著的書相匹配,而是出現了作者名字和書名的所有可能的組合,這也許不是你所希望見到的。
出了什麼差錯?問題在於你沒有指明這兩個表之間的關係。你沒有通過任何方式告訴SQL如何把表和表關聯在一起。由於不知道如何關聯兩個表,伺服器只能簡單地返回取自兩個表中的記錄的所有可能組合。
要從兩個表中選出有意義的記錄組合,你需要通過建立兩表中欄位的關係來關聯兩個表。要做到這一點的途徑之一是建立第三個表,專門用來描述另外兩個表的欄位之間的關係。
表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 FROM titles,publishers
WHERE titles.pub_id=publishers.pub_id
當然,如果一本書是由兩個出版商聯合出版的,那麼你需要第三個表來代表這種關係。
通常,當你予先知道兩個表的欄位間存在“多對多”關係時,就使用第三個表來關聯這兩個表。反之,如果兩個表的欄位間只有“一對一”或“一對多”關係,你可以使用公共欄位來關聯它門。
操作欄位
通常,當你從一個表中取出欄位值時,該值與建立該表時所定義的欄位名聯絡在一起。如果你從表authors中選擇所有的作者名字,所有的值將會與欄位名au_lname相聯絡。但是在某些情況下,你需要對欄位名進行操作。在SELECT語句中,你可以在預設欄位名後面僅跟一個新名字來取代它。例如,可以用一個更直觀易讀的名字Author Last Name來代替欄位名au_lname:
SELECT au_lname "Author LastName" FROM authors
當這個SELECT語句執行時,來自欄位au_lname的值會與“Author Last Name”相聯絡。查詢結果可能是這樣:
Author Last Name
……………………………………………………………………..
White
Green
Carson
O’Leary
Straight
…
(23 row(s)affected)
注意欄位標題不再是au_lname,而是被Author Last Name所取代。
你也可以通過執行運算,來操作從一個表返回的欄位值。例如,如果你想把表titles中的所有書的價格加倍,你可以使用下面的SELECT語句:
SELECT price*2 FROM titles
當這個查詢執行時,每本書的價格從表中取出時都會加倍。但是,通過這種途徑操作欄位不會改變儲存在表中的書價。對欄位的運算只會影響SELECT語句的輸出,而不會影響表中的資料。為了同時顯示書的原始價格和漲價後的新價格,你可以使用下面的查詢:
SELECT price "Original price",price*2 "New price" FROM titles
當資料從表titles中取出時,原始價格顯示在標題Original price下面,加倍後的價格顯示在標題New price下面。結果可能是這樣:
original price new price
……………………………………………………………….
19.99 39.98
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 ORDERBY 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
這個查詢從表authors中取出所有名字為Ringer的作者記錄。ORDER BY子句根據作者的名字和姓,將查詢結果按降序排列。結果是這樣的:
au_lname au_fname
……………………………………………………………………………………….
Ringer Anne
Ringer Albert
(2 row(s) affectec)
注意在這個表中,姓Anne出現在姓Albert之前。作者名字按降序顯示。
你也可以按數值型欄位對一個查詢結果進行排序。例如,如果你想按降序取出所有書的價格,你可以使用如下的SQL查詢:
SELECT price FROM titles ORDER BY price DESC
這個SELECT語句從表中取出所有書的價格,顯示結果時,價格低的書先顯示,價格高的書後顯示。
警告:
不是特別需要時,不要對查詢結果進行排序,因為伺服器完成這項工作要費些力氣。這意味著帶有ORDER BY 子句的SELECT語句執行起來比一般的SELECT語句花的時間長。
取出互不相同的記錄
一個表有可能在同一列中有重複的值。例如,資料庫pubs的表authors中有兩個作者的名字是Ringer。如果你從這個表中取出所有的名字,名字Ringer將會顯示兩次。
在特定情況下,你可能只有興趣從一個表中取出互不相同的值。如果一個欄位有重複的值,你也許希望每個值只被選取一次,你可以使用關鍵字DISTINCT來做到這一點:
SELCET DISTINCT au_lname FROM authors WHERE au_lname="Ringer"
當這個SELECT語句執行時,只返回一個記錄。通過在SELECT語句中包含關鍵字DISTINCT,你可以刪除所有重複的值。例如,假設有一個關於新聞組資訊釋出的表,你想取出所有曾在這個新聞組中釋出資訊的人的名字,那麼你可以使用關鍵字DISTINCT。每個使用者的名字只取一次——儘管有的使用者釋出了不止一篇資訊。
警告:
如同ORDER BY子句一樣,強制伺服器返回互不相同的值也會增加執行開銷。福氣不得不花費一些時間來完成這項工作。因此,不是必須的時候不要使用關鍵字DISTINCT。
建立新表
前面說過,資料庫中的所有資料儲存在表中。資料表包括行和列。列決定了表中資料的型別。行包含了實際的資料。
例如,資料庫pubs中的表authors有九個欄位。其中的一個欄位名為為au_lname,這個欄位被用來儲存作者的名字資訊。每次向這個表中新增新作者時,作者名字就被新增到這個欄位,產生一條新記錄。
通過定義欄位,你可以建立一個新表。每個欄位有一個名字和一個特定的資料型別(資料型別在後面的“欄位型別”一節中講述),例如欄位au_lname儲存的是字元型資料。一個欄位也可以儲存其它型別的資料。
使用SQL Sever,建立一個新表的方法是很多的。你可以可執行一個SQL語句或使用SQL事務管理器(SQL Enterprise Manager)來建立一個新表。在下一節裡,你將學會如何用SQL語句來建立一個新表。
用SQL建立新表
注意:
如果你還沒有建立自己的資料庫,現在就跳回到第三章建立這個庫。你絕不能向master,tempdb或任何其他任何系統資料庫中新增資料。
從SQL Sever程式組(在工作列中)中啟動ISQL/w程式。出現查詢視窗後,從視窗頂部的下拉列表中選擇你在第三章所建立的資料庫。下一步,在查詢視窗中鍵入下面的SQL語句,單擊執行查詢按鈕,執行這個語句:
CREATE TABLE guestbook (visitorVARCHAR(40),comments TEXT,entrydate
DATETIME)
如果一切正常,你會在結果視窗中看到如下的文字(如果出現異常,請參閱第三章):
This command dit not return data ,and itdid not return any rows
祝賀你,你已經建立了你的第一個表!
你所建立的表名為guestbook,你可以使用這個表來儲存來字你站點訪問者的資訊。你是用REEATETABLE語句建立的這個表,這個語句有兩部分:第一部份指定表的名子;第二部份是括在括號中的各欄位的名稱和屬性,相互之間用逗號隔開。
表guestbook有三個欄位:visitor,comments 和entrydate。visitor欄位儲存訪問者的名字,comments欄位儲存訪問者對你站點的意見,entrydate欄位儲存訪問者訪問你站點的日期和時間。
注意每個欄位名後面都跟有一個專門的表示式。例如,欄位名comments後面跟有表示式TEXT。這個表示式指定了欄位的資料型別。資料型別決定了一個欄位可以儲存什麼樣的資料。因為欄位comments包含文字資訊,其資料型別定義為文字型。
欄位有許多不同的資料型別。下一小節講述SQL所支援的一些重要的資料型別。
欄位型別
不同的欄位型別用來存放不同型別的資料。建立和使用表時,更你應該理解五種常用的欄位型別:字元型,文字型,數值型,邏輯性和日期型。
字元型資料
字元型資料非常有用。當你需要儲存短的字串資訊時,你總是要用到字元型資料。例如,你可以把從HTML form的文字框中搜集到的資訊放在字元型欄位中。
要建立一個欄位用來存放可變長度的字串資訊,你可以使用表示式 VARCHAR。考慮你前面建立的表guestbook:
CREATE TABLE guestbook (visitorVARCHAR(40),comments TEXT,entrydate
DATETIME)
在這個例子中,欄位visitor的資料型別為VARCHAR。注意跟在資料型別後面的括號中的數字。這個數字指定了這個欄位所允許存放的字串的最大長度。在這個例子中,欄位visitor能存放的字串最長為四十個字元。如果名字太長,字串會被截斷,只保留四十個字元。
VARCHAR型別可以儲存的字串最長為255個字元。要儲存更長的字串資料,可以使用文字型資料(下一節中講述)。
另一種字元型資料用來儲存固定長度的字元資料。下面是一個使用這種資料型別的例子:
CREATE TABLE guestbook (visitorCHAR(40),comments TEXT,entrydate
DATETIME)
在這個例子中,欄位visitor被用來儲存四十個字元的固定長度字串。表示式CHAR指定了這個欄位應該是固定長度的字串。
VARCHAR型和CHAR型資料的這個差別是細微的,但是非常重要。假如你向一個長度為四十個字元的VARCHAR型欄位中輸入資料Bill Gates。當你以後從這個欄位中取出此資料時,你取出的資料其長度為十個字元——字串Bill Gates的長度。
現在假如你把字串輸入一個長度為四十個字元的CHAR型欄位中,那麼當你取出資料時,所取出的資料長度將是四十個字元。字串的後面會被附加多餘的空格。
當你建立自己的站點時,你會發現使用VARCHAR型欄位要比CHAR型欄位方便的多。使用VARCHAR型欄位時,你不需要為剪掉你資料中多餘的空格而操心。
VARCHAR型欄位的另一個突出的好處是它可以比CHAR型欄位佔用更少的記憶體和硬碟空間。當你的資料庫很大時,這種記憶體和磁碟空間的節省會變得非常重要。
文字型資料
字元型資料限制了字串的長度不能超過255個字元。而使用文字型資料,你可以存放超過二十億個字元的字串。當你需要儲存大串的字元時,應該使用文字型資料。
這裡有一個使用文字型資料的例子:
CREATE TABLE guestbook (visitorVARCHAR(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 (visitorVARCHAR(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。
當定義一個NUMERIC型欄位時,你需要同時指定整數部分的大小和小數部分的大小。這裡有一個使用這種資料型別的例子:
CREATETABLE numeric_data (bignumber NUMERIC(28,0),
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 (productVARCHAR(40),price MONEY,
Discount_priceSMALLMONEY)
這個表可以用來儲存商品的折扣和普通售價。欄位price 的資料型別是MONEY,欄位discount_price的資料型別是SMALLMONEY。
儲存邏輯值
如果你使用複選框(CHECKBOX)從網頁中搜集資訊,你可以把此資訊儲存在BIT型欄位中。BIT型欄位只能取兩個值:0或1。這裡有一個如何使用這種欄位的例子:
CREATE TABLE opinion (visitorVARCHAR(40),good BIT)
這個表可以用來存放對你的網點進行民意調查所得的資訊。訪問者可以投票表示他們是否喜歡你的網點。如果他們投YES,就在BIT型欄位中存入1。反之,如果他們投NO,就在欄位中存入0(在下一章裡,你將學會如何計算投票)。
當心,在你建立好一個表之後,你不能向表中新增BIT型欄位。如果你打算在一個表中包含BIT型欄位,你必須在建立表時完成。
儲存日期和時間
當你建立一個網點時,你也許需要記錄在一段時間內的訪問者數量。為了能夠儲存日期和時間,你需要使用DATETIME型資料,如下例所示:
CREATE TABL visitorlog( visitor VARCHAR (40),arrivaltime DATETIME ,
departuretime DATETIME)
這個表可以用來記錄訪問者進入和離開你網點的時間和日期。一個DATETIME型的欄位可以儲存的日期範圍是從1753年1月1日第一毫秒到9999年12月31日最後一毫秒。
如果你不需要覆蓋這麼大範圍的日期和時間,你可以使用SMALLDATETIME型資料。它與DATETIME型資料同樣使用,只不過它能表示的日期和時間範圍比DATETIME型資料小,而且不如DATETIME型資料精確。一個SMALLDATETIME型的欄位能夠儲存從1900年1月1日到2079年6月6日的日期,它只能精確到秒。
DATETIME型欄位在你輸入日期和時間之前並不包含實際的資料,認識這一點是重要的。在下一章,你將學習怎樣使用大量的SQL函式來讀取和操作日期和時間(參見下面的“預設值”一節)。你也可以在VBScript和JScript 中使用日期和時間函式來向一個DATETIME型欄位中輸入日期和時間。
欄位屬性
上一節介紹瞭如何建立包含不同型別欄位的表。在這一節中,你將學會如何使用欄位的三個屬性。這些屬性允許你控制空值,預設值和標識值。
允許和禁止空值
大多數字段可以接受空值(NULL)。當一個欄位接受了空值後,如果你不改變它,它將一直保持空值。空值(NULL)和零是不同的,嚴格的說,空值表示沒有任何值。
為了允許一個欄位接受空值,你要在欄位定義的後面使用表示式NULL。例如,下面的表中兩個欄位都允許接受空值:
CREATE TABLE empty (empty1 CHAR (40)NULL,empty2 INT NULL(
注意:
BIT型資料不能是空值。一個這種型別的欄位必須取0或者1。
有時你需要禁止一個欄位使用空值。例如,假設有一個表儲存著信用卡號碼和信用卡有效日期,你不會希望有人輸入一個信用卡號碼但不輸入有效日期。為了強制兩個欄位都輸入資料,你可以用下面的方法建立這個表:
CREATE TABLE creditcards (creditcard_number CHAR(20) NOT NULL,
Creditcard_expire DATETIME NOT NULL)
注意欄位定義的後面跟有表示式NOT NULL。通過包含表示式NOT NULL,你可以禁止任何人只在一個欄位中插入資料,而不輸入另一個欄位的資料。
你將會發現,在你建設自己的網點過程中,這種禁止空值的能力是非常有用的。如果你指定一個欄位不能接受空值,那麼當你試圖輸入一個空值時,會有錯誤警告。這些錯誤警告可以為程式除錯提供有價值的線索。
預設值
假設有一個儲存地址資訊的表,這個表的欄位包括街道、城市、州、郵政編碼和國家。如果你預計地址的大部分是在美國,你可以把這個值作為country欄位的預設值。
為了在建立一個表時指定預設值,你可以使用表示式DEFAULT。請看下面這個在建立表時使用預設值的例子:
CREATE TABLE addresses (streetVARCHAR(60) NULL,
city VARCHAR(40)NULL,
stateVARCHAR(20) NULL
zip VARCHAR(20) NULL,
country VARCHAR(30) DEFAULT ‘USA’)
在這個例子中,欄位country的預設值被指定為美國。注意單引號的使用,引號指明這是字元型資料。為了給非字元型的欄位指定預設值,不要把該值擴在引號中:
CREATE TABLE orders(price MONEY DEFAULT $38.00,
quantity INT DEFAULT50,
entrydate DATETIME DEFAULT GETDATE())
在這個CREATE TABLE語句中,每個欄位都指定了一個預設值。注意DATETIME型欄位entrydate所指定的預設值,該預設值是函式Getdate()的返回值,該函式返回當前的日期和時間。
標識欄位
每個表可以有一個也只能有一個標識欄位。一個標識欄位是唯一標識表中每條記錄的特殊欄位。例如,資料庫pubs中的表jobs包含了一個唯一標識每個工作標識欄位:
job_id job_desc
…………………………………………………………….
1 New Hire Job not specified
2 Chief Executive officer
3 Bushness Operations Manager
4 Chief Financial Officier
5 Publisher
欄位job_id為每個工作提供了唯一的一個數字。如果你決定增加一個新工作,新增記錄的job_id欄位會被自動賦給一個新的唯一值。
為了建立一個標識欄位,你只需在欄位定義後面加上表達式IDENTITY即可。你只能把NUMERIC型或INT型欄位設為標識欄位,這裡有一個例子:
CREATE TABLE visitorID (theIDNUBERIC(18) IDENTITY,name VARCHAR(40))
這個語句所建立的表包含一個名為theid的標識欄位。每當一個新的訪問者名字新增到這個表中時,這個欄位就被自動賦給一個新值。你可以用這個表為你的站點的每一個使用者提供唯一標識。
技巧:
建立一個標示欄位時,注意使用足夠大的資料型別。例如你使用TINYINT型資料,那麼你只能向表中新增255個記錄。如果你預計一個表可能會變得很大,你應該使用NUMERIC型資料。
標識欄位的存在會使你想嘗試許多不可能的事情。例如,你也許想利用標識欄位來對記錄進行基於它們在表中位置的運算。你應該拋棄這種意圖。每個記錄的標識欄位的值是互不相同的,但是,這並不禁止一個標識欄位的標識數字之間存在間隔。例如,你永遠不要試圖利用一個表的標識欄位來取出表中的前十個記錄。這種操作會導致失敗,比如說6號記錄和7號記錄根本不存在。
使用SQL事務管理器建立新表
你可以使用前面幾節所講的方法建立新表。但是,使用事務管理器建立新表會更容易。這一節介紹如何使用這個程式建立新表。
從工作列的SQL Sever程式組中選擇SQL Enterprise Manager,啟動該程式,你會看到如圖10.4所示的視窗。瀏覽服務管理器視窗中的樹形結構,選擇名為Database的資料夾。開啟資料夾Database後,選擇你在第三章中所建立的資料庫。
注意:
如果你還沒有建立自己的資料庫,回到第三章建立它。你決不要向master,tempdb或任何其它系統資料庫中新增資料。
在選擇了資料庫之後,你會看到一個名為Group/users的資料夾和一個名為objects的資料夾。開啟資料夾objects,你會看到許多資料夾,其中一個名為Tables。用右鍵單擊資料夾Tables並選擇New table,就會出現如圖10.5所示的視窗。
你可以使用Manager Tables視窗來建立一個新表。Manager Tables視窗有7個列:Key,Column,Name,Datatype,Size,Nulls和Default。Manager Tables視窗中的每一行標明表中一個欄位的資訊。
圖10.4
10.5
要建立一個新表,你至少要輸入一行資訊。在名為Column Name的列下面鍵入mycolumn。下一步,選擇Datatype列,並從下拉列表中選擇CHAR。當你在這兩個列中輸入資訊後,視窗將是如圖10.6所示的樣子。
圖10.6
你已經建立了一個只有一個欄位的簡單的表。單擊儲存按扭儲存這個新表。當要求你輸入新表的名字時,輸入mytable並單擊OK。現在這個表已經儲存到了你的資料庫中。
如果你開啟服務管理器視窗中的資料夾Tables,你會看到你所建立的新表被列出。你可以雙擊該表的圖表來編輯它,這時Manager Tables視窗會重新出現,你可以增加新的欄位並重新儲存。
用SQL事務管理器可以做的工作,你都可以用SQL語句來實現。但是,事務管理器使得建表過程變得更加簡單。
向表中新增資料
下一章將討論如何使用SQL向一個表中插入資料。但是,如果你需要向一個表中新增許多條記錄,使用SQL語句輸入資料是很不方便的。幸運的是,Microsoft SQL Sever帶有一個稱為Microsoft Query 的客戶端應用程式,這個程式使得向表中新增資料變得容易了。
啟動位於工作列SQL Sever程式組中的Microsoft Query程式。從視窗頂部的選單中選擇File|New Query。這時會顯示一個Select Data Source對話方塊(見圖10.7)。選擇你的資料來源名字並單擊Use。
圖10。7
輸入你的登入帳號和密碼後,程式要求你選擇一個表和一個數據庫。選擇你在上一節中所建立的表(mytable ),單擊按鈕Add,然後單擊按鈕Close關閉該對話方塊。
在視窗的左上角會出現一個對話方塊,框中是取自表mytable的一列欄位名。你可以雙擊任何一個欄位,把它新增到主視窗中。如果你雙擊星號(*)字元,所有的欄位都會被新增到主視窗中。
如果你的表中有記錄,它們現在已經出現在主視窗的欄位標題下面了。但是,因為你剛剛建立了這個表,表還是空的。要新增新記錄,選擇Records|Allow Editing,主視窗中就會出現一條新記錄。輸入一行資料完成這個記錄,就向表中添加了一條新記錄。
圖10。8
當你轉到下一條新記錄時,你向上一條記錄中輸入的值會自動被儲存。如果你需要,你可以用Microsoft Query 向表中輸入幾百條記錄。
刪除和修改表
你應該在建立表之前仔細設計它們,因為你在改變一個已經存在的表時會受到很大的限制。例如,一旦已經建立了一個表,你就不能刪除表中的欄位或者改變欄位的資料型別。在這種情況你所能做的是刪除這個表,然後重頭開始(參見第十一章“中級SQL”中的“使用SQL建立記錄和表”一節)。
要刪除一個表,你可以使用SQL語句DROP TABLE。例如,又從資料庫中徹底刪除表mytable,你要使用如下的語句:
DROP TABLE mytable
警告:
使用DROP TABLE命令時一定要小心。一旦一個表被刪除之後,你將無法恢復它。
當你建設一個站點時,你很可能需要向資料庫中輸入測試資料。而當你準備向世界提供你的網點時,你會想清空表中的這些測試資訊。如果你想清除表中的所有資料但不刪除這個表,你可以使用TRUNCATE TABLE語句。例如,下面的這個SQL語句從表mytable中刪除所有資料:
TRUNCATE TABLE mytable
雖然你不能刪除和修改已經存在的欄位,但你可以增加新欄位。最容易的實現方法是使用SQL事務管理器中的Manager Tables視窗。你也可以使用SQL語句ALTER TABLE。下面是一個如何使用這種語句的例子:
ALTER TABLE mytable ADD mynewcolumn INTNULL
這個語句向表mytable中增加了一個新欄位mynewcolumn。當你增加新欄位時,你必須允許它接受空值,因為表中原來可能已經有了許多記錄。
總結
這一章向你介紹了SQL。使用SQL,你可以操作Microsoft SQL Sever資料庫。你已經學會了使用SELECT語句從資料庫中取出資料,你還學會了怎樣使用CREATE TABLE語句和SQL事務管理器來建立新表。最後,你學會了如何指明一系列重要的欄位屬性。
下一章將介紹如何使用索引來增強SQL查詢的操作。還將通過許多其它的SQL語句和函式,使你的SQL知識得到進一步擴充。
第十一章 中級SQL
本章內容
■建立索引
■SQL核心語句
■集合函式
■其它常用的SQL表示式,
函式,和過程
第十章“SQL基礎”向你初步介紹了SQL。你學會了如何用SELECT語句進行查詢,你還學會了如何建立自己的表。在這一章裡,你將加深你的SQL知識。你將學習如何建立索引來加快查詢速度。你還將學會如果用更多的SQL語句和函式來操作表中的資料。
建立索引
假設你想找到本書中的某一個句子。你可以一頁一頁地逐頁搜尋,但這會花很多時間。而通過使用本書的索引,你可以很快地找到你要搜尋的主題。
表的索引與附在一本書後面的索引非常相似。它可以極大地提高查詢的速度。對一個較大的表來說,通過加索引,一個通常要花費幾個小時來完成的查詢只要幾分鐘就可以完成。因此沒有理由對需要頻繁查詢的表增加索引。
注意:
當你的記憶體容量或硬碟空間不足時,也許你不想給一個表增加索引。對於包含索引的資料庫,SQL Sever需要一個可觀的額外空間。例如,要建立一個聚簇索引,需要大約1.2倍於資料大小的空間。要看一看一個表的索引在資料庫中所佔的空間大小,你可以使用系統儲存過程sp_spaceused,物件名指定為被索引的表名。
聚簇索引和非聚簇索引
假設你已經通過本書的索引找到了一個句子所在的頁碼。一旦已經知道了頁碼後,你很可能漫無目的翻尋這本書,直至找到正確的頁碼。通過隨機的翻尋,你最終可以到達正確的頁碼。但是,有一種找到頁碼的更有效的方法。
首先,把書翻到大概一半的地方,如果要找的頁碼比半本書處的頁碼小,就書翻到四分之一處,否則,就把書翻到四分之三的地方。通過這種方法,你可以繼續把書分成更小的部分,直至找到正確的頁碼附近。這是找到書頁的非常有效的一種方法。
SQL Sever的表索引以類似的方式工作。一個表索引由一組頁組成,這些頁構成了一個樹形結構。根頁通過指向另外兩個頁,把一個表的記錄從邏輯上分成和兩個部分。而根頁所指向的兩個頁又分別把記錄分割成更小的部分。每個頁都把記錄分成更小的分割,直至到達葉級頁。
索引有兩種型別:聚簇索引和非聚簇索引。在聚簇索引中,索引樹的葉級頁包含實際的資料:記錄的索引順序與物理順序相同。在非聚簇索引中,葉級頁指向表中的記錄:記錄的物理順序與邏輯順序沒有必然的聯絡。
聚簇索引非常象目錄表,目錄表的順序與實際的頁碼順序是一致的。非聚簇索引則更象書的標準索引表,索引表中的順序通常與實際的頁碼順序是不一致的。一本書也許有多個索引。例如,它也許同時有主題索引和作者索引。同樣,一個表可以有多個非聚簇索引。
通常情況下,你使用的是聚簇索引,但是你應該對兩種型別索引的優缺點都有所理解。
每個表只能有一個聚簇索引,因為一個表中的記錄只能以一種物理順序存放。通常你要對一個表按照標識欄位建立聚簇索引。但是,你也可以對其它型別的欄位建立聚簇索引,如字元型,數值型和日期時間型欄位。
從建立了聚簇索引的表中取出資料要比建立了非聚簇索引的錶快。當你需要取出一定範圍內的資料時,用聚簇索引也比用非聚簇索引好。例如,假設你用一個表來記錄訪問者在你網點上的活動。如果你想取出在一定時間段內的登入資訊,你應該對這個表的DATETIME型欄位建立聚簇索引。
對聚簇索引的主要限制是每個表只能建立一個聚簇索引。但是,一個表可以有不止一個非聚簇索引。實際上,對每個表你最多可以建立249個非聚簇索引。你也可以對一個表同時建立聚簇索引和非聚簇索引。
假如你不僅想根據日期,而且想根據使用者名稱從你的網點活動日誌中取資料。在這種情況下,同時建立一個聚簇索引和非聚簇索引是有效的。你可以對日期時間欄位建立聚簇索引,對使用者名稱欄位建立非聚簇索引。如果你發現你需要更多的索引方式,你可以增加更多的非聚簇索引。
非聚簇索引需要大量的硬碟空間和記憶體。另外,雖然非聚簇索引可以提高從表中取資料的速度,它也會降低向表中插入和更新資料的速度。每當你改變了一個建立了非聚簇索引的表中的資料時,必須同時更新索引。因此你對一個表建立非聚簇索引時要慎重考慮。如果你預計一個表需要頻繁地更新資料,那麼不要對它建立太多非聚簇索引。另外,如果硬碟和記憶體空間有限,也應該限制使用非聚簇索引的數量。
索引屬性
這兩種型別的索引都有兩個重要屬性:你可以用兩者中任一種型別同時對多個欄位建立索引(複合索引);兩種型別的索引都可以指定為唯一索引。
你可以對多個欄位建立一個複合索引,甚至是複合的聚簇索引。假如有一個表記錄了你的網點訪問者的姓和名字。如果你希望根據完整姓名從表中取資料,你需要建立一個同時對姓欄位和名字欄位進行的索引。這和分別對兩個欄位建立單獨的索引是不同的。當你希望同時對不止一個欄位進行查詢時,你應該建立一個對多個欄位的索引。如果你希望對各個欄位進行分別查詢,你應該對各欄位建立獨立的索引。
兩種型別的索引都可以被指定為唯一索引。如果對一個欄位建立了唯一索引,你將不能向這個欄位輸入重複的值。一個標識欄位會自動成為唯一值欄位,但你也可以對其它型別的欄位建立唯一索引。假設你用一個表來儲存你的網點的使用者密碼,你當然不希望兩個使用者有相同的密碼。通過強制一個欄位成為唯一值欄位,你可以防止這種情況的發生。
用SQL建立索引
為了給一個表建立索引,啟動工作列SQL Sever程式組中的ISQL/w程式。進入查詢視窗後,輸入下面的語句:
CREATE INDEX mycolumn_index ON mytable(myclumn)
這個語句建立了一個名為mycolumn_index的索引。你可以給一個索引起任何名字,但你應該在索引名中包含所索引的欄位名,這對你將來弄清楚建立該索引的意圖是有幫助的。
注意:
在本書中你執行任何SQL語句,都會收到如下的資訊:
This command did not return data,and it did not return any rows
這說明該語句執行成功了。
索引mycolumn_index對錶mytable的mycolumn欄位進行。這是個非聚簇索引,也是個非唯一索引。(這是一個索引的預設屬性)
如果你需要改變一個索引的型別,你必須刪除原來的索引並重建一個。建立了一個索引後,你可以用下面的SQL語句刪除它:
DROPINDEX mytable.mycolumn_index
注意在DROP INDEX 語句中你要包含表的名字。在這個例子中,你刪除的索引是mycolumn_index,它是表mytable的索引。
要建立一個聚簇索引,可以使用關鍵字CLUSTERED。)記住一個表只能有一個聚簇索引。(這裡有一個如何對一個表建立聚簇索引的例子:
CREATECLUSTERED INDEX mycolumn_clust_index ON mytable(mycolumn)
如果表中有重複的記錄,當你試圖用這個語句建立索引時,會出現錯誤。但是有重複記錄的表也可以建立索引;你只要使用關鍵字ALLOW_DUP_ROW把這一點告訴SQL Sever即可:
CREATECLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)
WITH ALLOW_DUP_ROW
這個語句建立了一個允許重複記錄的聚簇索引。你應該儘量避免在一個表中出現重複記錄,但是,如果已經出現了,你可以使用這種方法。
要對一個表建立唯一索引,可以使用關鍵字UNIQUE。對聚簇索引和非聚簇索引都可以使用這個關鍵字。這裡有一個例子:
CREATEUNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)
這是你將經常使用的索引建立語句。無論何時,只要可以,你應該儘量對一個對一個表建立唯一聚簇索引來增強查詢操作。
最後,要建立一個對多個欄位的索引──複合索引──在索引建立語句中同時包含多個欄位名。下面的例子對firstname和lastname兩個欄位建立索引:
CREATEINDEX name_index ON username(firstname,lastname)
這個例子對兩個欄位建立了單個索引。在一個複合索引中,你最多可以對16個欄位進行索引。
用事務管理器建立索引
用事務管理器建立索引比用SQL語句容易的多。使用事務管理器,你可以看到已經建立的索引的列表,並可以通過圖形介面選擇索引選