SQL必知必會(huì)(第4版)_第1頁
SQL必知必會(huì)(第4版)_第2頁
SQL必知必會(huì)(第4版)_第3頁
SQL必知必會(huì)(第4版)_第4頁
SQL必知必會(huì)(第4版)_第5頁
已閱讀5頁,還剩132頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

SQL必知必會(huì)(第4版)數(shù)據(jù)庫入門目錄\h第1課了解SQL\h1.1數(shù)據(jù)庫基礎(chǔ)\h1.1.1數(shù)據(jù)庫\h1.1.2表\h1.1.3列和數(shù)據(jù)類型\h1.1.4行\(zhòng)h1.1.5主鍵\h1.2什么是SQL\h1.3動(dòng)手實(shí)踐\h1.4小結(jié)\h第2課檢索數(shù)據(jù)\h2.1SELECT語句\h2.2檢索單個(gè)列\(zhòng)h2.3檢索多個(gè)列\(zhòng)h2.4檢索所有列\(zhòng)h2.5檢索不同的值\h2.6限制結(jié)果\h2.7使用注釋\h2.8小結(jié)\h第3課排序檢索數(shù)據(jù)\h3.1排序數(shù)據(jù)\h3.2按多個(gè)列排序\h3.3按列位置排序\h3.4指定排序方向\h3.5小結(jié)\h第4課過濾數(shù)據(jù)\h4.1使用WHERE子句\h4.2WHERE子句操作符\h4.2.1檢查單個(gè)值\h4.2.2不匹配檢查\h4.2.3范圍值檢查\h4.2.4空值檢查\h4.3小結(jié)\h第5課高級數(shù)據(jù)過濾\h5.1組合WHERE子句\h5.1.1AND操作符\h5.1.2OR操作符\h5.1.3求值順序\h5.2IN操作符\h5.3NOT操作符\h5.4小結(jié)\h第6課用通配符進(jìn)行過濾\h6.1LIKE操作符\h6.1.1百分號(%)通配符\h6.1.2下劃線(_)通配符\h6.1.3方括號([])通配符\h6.2使用通配符的技巧\h6.3小結(jié)\h第7課創(chuàng)建計(jì)算字段\h7.1計(jì)算字段\h7.2拼接字段\h使用別名\h7.3執(zhí)行算術(shù)計(jì)算\h7.4小結(jié)\h第8課使用數(shù)據(jù)處理函數(shù)\h8.1函數(shù)\h函數(shù)帶來的問題\h8.2使用函數(shù)\h8.2.1文本處理函數(shù)\h8.2.2日期和時(shí)間處理函數(shù)\h8.2.3數(shù)值處理函數(shù)\h8.3小結(jié)\h第9課匯總數(shù)據(jù)\h9.1聚集函數(shù)\h9.1.1AVG()函數(shù)\h9.1.2COUNT()函數(shù)\h9.1.3MAX()函數(shù)\h9.1.4MIN()函數(shù)\h9.1.5SUM()函數(shù)\h9.2聚集不同值\h9.3組合聚集函數(shù)\h9.4小結(jié)\h第10課分組數(shù)據(jù)\h10.1數(shù)據(jù)分組\h10.2創(chuàng)建分組\h10.3過濾分組\h10.4分組和排序\h10.5SELECT子句順序\h10.6小結(jié)\h第11課使用子查詢\h11.1子查詢\h11.2利用子查詢進(jìn)行過濾\h11.3作為計(jì)算字段使用子查詢\h11.4小結(jié)\h第12課聯(lián)結(jié)表\h12.1聯(lián)結(jié)\h12.1.1關(guān)系表\h12.1.2為什么使用聯(lián)結(jié)\h12.2創(chuàng)建聯(lián)結(jié)\h12.2.1WHERE子句的重要性\h12.2.2內(nèi)聯(lián)結(jié)\h12.2.3聯(lián)結(jié)多個(gè)表\h12.3小結(jié)\h第13課創(chuàng)建高級聯(lián)結(jié)\h13.1使用表別名\h13.2使用不同類型的聯(lián)結(jié)\h13.2.1自聯(lián)結(jié)\h13.2.2自然聯(lián)結(jié)\h13.2.3外聯(lián)結(jié)\h13.3使用帶聚集函數(shù)的聯(lián)結(jié)\h13.4使用聯(lián)結(jié)和聯(lián)結(jié)條件\h13.5小結(jié)\h第14課組合查詢\h14.1組合查詢\h14.2創(chuàng)建組合查詢\h14.2.1使用UNION\h14.2.2UNION規(guī)則\h14.2.3包含或取消重復(fù)的行\(zhòng)h14.2.4對組合查詢結(jié)果排序\h14.3小結(jié)\h第15課插入數(shù)據(jù)\h15.1數(shù)據(jù)插入\h15.1.1插入完整的行\(zhòng)h15.1.2插入部分行\(zhòng)h15.1.3插入檢索出的數(shù)據(jù)\h15.2從一個(gè)表復(fù)制到另一個(gè)表\h15.3小結(jié)\h第16課更新和刪除數(shù)據(jù)\h16.1更新數(shù)據(jù)\h16.2刪除數(shù)據(jù)\h16.3更新和刪除的指導(dǎo)原則\h16.4小結(jié)\h第17課創(chuàng)建和操縱表\h17.1創(chuàng)建表\h17.1.1表創(chuàng)建基礎(chǔ)\h17.1.2使用NULL值\h17.1.3指定默認(rèn)值\h17.2更新表\h17.3刪除表\h17.4重命名表\h17.5小結(jié)\h第18課使用視圖\h18.1視圖\h18.1.1為什么使用視圖\h18.1.2視圖的規(guī)則和限制\h18.2創(chuàng)建視圖\h18.2.1利用視圖簡化復(fù)雜的聯(lián)結(jié)\h18.2.2用視圖重新格式化檢索出的數(shù)據(jù)\h18.2.3用視圖過濾不想要的數(shù)據(jù)\h18.2.4使用視圖與計(jì)算字段\h18.3小結(jié)\h第19課使用存儲(chǔ)過程\h19.1存儲(chǔ)過程\h19.2為什么要使用存儲(chǔ)過程\h19.3執(zhí)行存儲(chǔ)過程\h19.4創(chuàng)建存儲(chǔ)過程\h19.5小結(jié)\h第20課管理事務(wù)處理\h20.1事務(wù)處理\h20.2控制事務(wù)處理\h20.2.1使用ROLLBACK\h20.2.2使用COMMIT\h20.2.3使用保留點(diǎn)\h20.3小結(jié)\h第21課使用游標(biāo)\h21.1游標(biāo)\h21.2使用游標(biāo)\h21.2.1創(chuàng)建游標(biāo)\h21.2.2使用游標(biāo)\h21.2.3關(guān)閉游標(biāo)\h21.3小結(jié)\h第22課高級SQL特性\h22.1約束\h22.1.1主鍵\h22.1.2外鍵\h22.1.3唯一約束\h22.1.4檢查約束\h22.2索引\h22.3觸發(fā)器\h22.4數(shù)據(jù)庫安全\h22.5小結(jié)\h附錄A樣例表腳本\hA.1樣例表\hA.2獲得樣例表\hA.2.1下載可供使用的數(shù)據(jù)文件\hA.2.2下載DBMSSQL腳本\h附錄B流行的應(yīng)用程序\hB.1使用ApacheOpenOfficeBase\hB.2使用AdobeColdFusion\hB.3使用IBMDB2\hB.4使用MariaDB\hB.5使用MicrosoftAccess\hB.6使用MicrosoftASP\hB.7使用MicrosoftASP.NET\hB.8使用MicrosoftQuery\hB.9使用MicrosoftSQLServer(包括MicrosoftSQLServerExpress)\hB.10使用MySQL\hB.11使用Oracle\hB.12使用OracleExpress\hB.13使用PHP\hB.14使用PostgreSQL\hB.15使用SQLite\hB.16配置ODBC數(shù)據(jù)源\h附錄CSQL語句的語法\hC.1ALTERTABLE\hC.2COMMIT\hC.3CREATEINDEX\hC.4CREATEPROCEDURE\hC.5CREATETABLE\hC.6CREATEVIEW\hC.7DELETE\hC.8DROP\hC.9INSERT\hC.10INSERTSELECT\hC.11ROLLBACK\hC.12SELECT\hC.13UPDATE\h附錄DSQL數(shù)據(jù)類型\hD.1字符串?dāng)?shù)據(jù)類型\hD.2數(shù)值數(shù)據(jù)類型\hD.3日期和時(shí)間數(shù)據(jù)類型\hD.4二進(jìn)制數(shù)據(jù)類型\h附錄ESQL保留字\h常用SQL語句速查第1課了解SQL這一課介紹SQL究竟是什么,它能做什么事情。1.1數(shù)據(jù)庫基礎(chǔ)你正在讀這本SQL圖書,這表明你需要以某種方式與數(shù)據(jù)庫打交道。SQL正是用來實(shí)現(xiàn)這一任務(wù)的語言,因此在學(xué)習(xí)SQL之前,你應(yīng)該對數(shù)據(jù)庫及數(shù)據(jù)庫技術(shù)的某些基本概念有所了解。你可能還沒有意識到,其實(shí)自己一直在使用數(shù)據(jù)庫。每當(dāng)你從電子郵件地址簿里查找名字時(shí),就是在使用數(shù)據(jù)庫。你在網(wǎng)站上進(jìn)行搜索,也是在使用數(shù)據(jù)庫。你在工作中登錄網(wǎng)絡(luò),也需要依靠數(shù)據(jù)庫驗(yàn)證用戶名和密碼。即使是在自動(dòng)取款機(jī)上使用ATM卡,也要利用數(shù)據(jù)庫進(jìn)行密碼驗(yàn)證和查詢余額。雖然我們一直都在使用數(shù)據(jù)庫,但對究竟什么是數(shù)據(jù)庫并不十分清楚。更何況人們可能會(huì)使用相同的數(shù)據(jù)庫術(shù)語表示不同的事物,進(jìn)一步加劇了這種混亂。因此,我們首先給出一些最重要的數(shù)據(jù)庫術(shù)語,并加以說明。提示:基本概念回顧

后面是一些基本數(shù)據(jù)庫概念的簡要介紹。如果你已經(jīng)具有一定的數(shù)據(jù)庫經(jīng)驗(yàn),可以借此復(fù)習(xí)鞏固一下;如果你剛開始接觸數(shù)據(jù)庫,可以由此了解必需的基本知識。理解數(shù)據(jù)庫概念是掌握SQL的重要前提,如果有必要,你或許還應(yīng)該參閱其他一些有關(guān)數(shù)據(jù)庫基礎(chǔ)知識的書籍。1.1.1數(shù)據(jù)庫數(shù)據(jù)庫這個(gè)術(shù)語的用法很多,但就本書而言(從SQL的角度來看),數(shù)據(jù)庫是一個(gè)以某種有組織的方式存儲(chǔ)的數(shù)據(jù)集合。最簡單的辦法是將數(shù)據(jù)庫想象為一個(gè)文件柜。這個(gè)文件柜是一個(gè)存放數(shù)據(jù)的物理位置,不管數(shù)據(jù)是什么,也不管數(shù)據(jù)是如何組織的。數(shù)據(jù)庫(database)

保存有組織的數(shù)據(jù)的容器(通常是一個(gè)文件或一組文件)。注意:誤用導(dǎo)致混淆

人們通常用數(shù)據(jù)庫這個(gè)術(shù)語來代表他們使用的數(shù)據(jù)庫軟件,這是不正確的,也因此產(chǎn)生了許多混淆。確切地說,數(shù)據(jù)庫軟件應(yīng)稱為數(shù)據(jù)庫管理系統(tǒng)(即DBMS)。數(shù)據(jù)庫是通過DBMS創(chuàng)建和操縱的容器,而具體它究竟是什么,形式如何,各種數(shù)據(jù)庫都不一樣。1.1.2表你往文件柜里放資料時(shí),并不是隨便將它們?nèi)舆M(jìn)某個(gè)抽屜就完事了,而是在文件柜中創(chuàng)建文件,然后將相關(guān)的資料放入特定的文件中。在數(shù)據(jù)庫領(lǐng)域中,這種文件稱為表。表是一種結(jié)構(gòu)化的文件,可用來存儲(chǔ)某種特定類型的數(shù)據(jù)。表可以保存顧客清單、產(chǎn)品目錄,或者其他信息清單。表(table)

某種特定類型數(shù)據(jù)的結(jié)構(gòu)化清單。這里的關(guān)鍵一點(diǎn)在于,存儲(chǔ)在表中的數(shù)據(jù)是同一種類型的數(shù)據(jù)或清單。決不應(yīng)該將顧客的清單與訂單的清單存儲(chǔ)在同一個(gè)數(shù)據(jù)庫表中,否則以后的檢索和訪問會(huì)很困難。應(yīng)該創(chuàng)建兩個(gè)表,每個(gè)清單一個(gè)表。數(shù)據(jù)庫中的每個(gè)表都有一個(gè)名字來標(biāo)識自己。這個(gè)名字是唯一的,即數(shù)據(jù)庫中沒有其他表具有相同的名字。說明:表名

使表名成為唯一的,實(shí)際上是數(shù)據(jù)庫名和表名等的組合。有的數(shù)據(jù)庫還使用數(shù)據(jù)庫擁有者的名字作為唯一名的一部分。也就是說,雖然在相同數(shù)據(jù)庫中不能兩次使用相同的表名,但在不同的數(shù)據(jù)庫中完全可以使用相同的表名。表具有一些特性,這些特性定義了數(shù)據(jù)在表中如何存儲(chǔ),包含存儲(chǔ)什么樣的數(shù)據(jù),數(shù)據(jù)如何分解,各部分信息如何命名等信息。描述表的這組信息就是所謂的模式(schema),模式可以用來描述數(shù)據(jù)庫中特定的表,也可以用來描述整個(gè)數(shù)據(jù)庫(和其中表的關(guān)系)。模式

關(guān)于數(shù)據(jù)庫和表的布局及特性的信息。1.1.3列和數(shù)據(jù)類型表由列組成。列存儲(chǔ)表中某部分的信息。列(column)

表中的一個(gè)字段。所有表都是由一個(gè)或多個(gè)列組成的。理解列的最好辦法是將數(shù)據(jù)庫表想象為一個(gè)網(wǎng)格,就像個(gè)電子表格那樣。網(wǎng)格中每一列存儲(chǔ)著某種特定的信息。例如,在顧客表中,一列存儲(chǔ)顧客編號,另一列存儲(chǔ)顧客姓名,而地址、城市、州以及郵政編碼全都存儲(chǔ)在各自的列中。提示:分解數(shù)據(jù)

正確地將數(shù)據(jù)分解為多個(gè)列極為重要。例如,城市、州、郵政編碼應(yīng)該總是彼此獨(dú)立的列。通過分解這些數(shù)據(jù),才有可能利用特定的列對數(shù)據(jù)進(jìn)行分類和過濾(如找出特定州或特定城市的所有顧客)。如果城市和州組合在一個(gè)列中,則按州進(jìn)行分類或過濾就會(huì)很困難。你可以根據(jù)自己的具體需求來決定把數(shù)據(jù)分解到何種程度。例如,一般可以把門牌號和街道名一起存儲(chǔ)在地址里。這沒有問題,除非你哪天想用街道名來排序,這時(shí),最好將門牌號和街道名分開。數(shù)據(jù)庫中每個(gè)列都有相應(yīng)的數(shù)據(jù)類型。數(shù)據(jù)類型(datatype)定義了列可以存儲(chǔ)哪些數(shù)據(jù)種類。例如,如果列中存儲(chǔ)的是數(shù)字(或許是訂單中的物品數(shù)),則相應(yīng)的數(shù)據(jù)類型應(yīng)該為數(shù)值類型。如果列中存儲(chǔ)的是日期、文本、注釋、金額等,則應(yīng)該規(guī)定好恰當(dāng)?shù)臄?shù)據(jù)類型。數(shù)據(jù)類型

所允許的數(shù)據(jù)的類型。每個(gè)表列都有相應(yīng)的數(shù)據(jù)類型,它限制(或允許)該列中存儲(chǔ)的數(shù)據(jù)。數(shù)據(jù)類型限定了可存儲(chǔ)在列中的數(shù)據(jù)種類(例如,防止在數(shù)值字段中錄入字符值)。數(shù)據(jù)類型還幫助正確地分類數(shù)據(jù),并在優(yōu)化磁盤使用方面起重要的作用。因此,在創(chuàng)建表時(shí)必須特別關(guān)注所用的數(shù)據(jù)類型。注意:數(shù)據(jù)類型兼容

數(shù)據(jù)類型及其名稱是SQL不兼容的一個(gè)主要原因。雖然大多數(shù)基本數(shù)據(jù)類型得到了一致的支持,但許多高級的數(shù)據(jù)類型卻沒有。更糟的是,偶然會(huì)有相同的數(shù)據(jù)類型在不同的DBMS中具有不同的名稱。對此用戶毫無辦法,重要的是在創(chuàng)建表結(jié)構(gòu)時(shí)要記住這些差異。1.1.4行表中的數(shù)據(jù)是按行存儲(chǔ)的,所保存的每個(gè)記錄存儲(chǔ)在自己的行內(nèi)。如果將表想象為網(wǎng)格,網(wǎng)格中垂直的列為表列,水平行為表行。例如,顧客表可以每行存儲(chǔ)一個(gè)顧客。表中的行編號為記錄的編號。行(row)

表中的一個(gè)記錄。說明:是記錄還是行?

你可能聽到用戶在提到行時(shí)稱其為數(shù)據(jù)庫記錄(record)。這兩個(gè)術(shù)語多半是可以交替使用的,但從技術(shù)上說,行才是正確的術(shù)語。1.1.5主鍵表中每一行都應(yīng)該有一列(或幾列)可以唯一標(biāo)識自己。顧客表可以使用顧客編號,而訂單表可以使用訂單ID。雇員表可以使用雇員ID或雇員社會(huì)安全號。主鍵(primarykey)

一列(或一組列),其值能夠唯一標(biāo)識表中每一行。唯一標(biāo)識表中每行的這個(gè)列(或這幾列)稱為主鍵。主鍵用來表示一個(gè)特定的行。沒有主鍵,更新或刪除表中特定行就極為困難,因?yàn)槟悴荒鼙WC操作只涉及相關(guān)的行。提示:應(yīng)該總是定義主鍵

雖然并不總是需要主鍵,但多數(shù)數(shù)據(jù)庫設(shè)計(jì)者都會(huì)保證他們創(chuàng)建的每個(gè)表具有一個(gè)主鍵,以便于以后的數(shù)據(jù)操作和管理。表中的任何列都可以作為主鍵,只要它滿足以下條件:任意兩行都不具有相同的主鍵值;每一行都必須具有一個(gè)主鍵值(主鍵列不允許NULL值);主鍵列中的值不允許修改或更新;主鍵值不能重用(如果某行從表中刪除,它的主鍵不能賦給以后的新行)。主鍵通常定義在表的一列上,但并不是必需這么做,也可以一起使用多個(gè)列作為主鍵。在使用多列作為主鍵時(shí),上述條件必須應(yīng)用到所有列,所有列值的組合必須是唯一的(但單個(gè)列的值可以不唯一)。還有一種非常重要的鍵,稱為外鍵,我們將在第12課中介紹。1.2什么是SQLSQL(發(fā)音為字母S-Q-L或sequel)是結(jié)構(gòu)化查詢語言(StructuredQueryLanguage)的縮寫。SQL是一種專門用來與數(shù)據(jù)庫溝通的語言。與其他語言(如英語或Java、C、PHP這樣的編程語言)不一樣,SQL中只有很少的詞,這是有意而為的。設(shè)計(jì)SQL的目的是很好地完成一項(xiàng)任務(wù)——提供一種從數(shù)據(jù)庫中讀寫數(shù)據(jù)的簡單有效的方法。SQL有如下的優(yōu)點(diǎn)。SQL不是某個(gè)特定數(shù)據(jù)庫供應(yīng)商專有的語言。幾乎所有重要的DBMS都支持SQL,所以學(xué)習(xí)此語言使你幾乎能與所有數(shù)據(jù)庫打交道。SQL簡單易學(xué)。它的語句全都是由有很強(qiáng)描述性的英語單詞組成,而且這些單詞的數(shù)目不多。SQL雖然看上去很簡單,但實(shí)際上是一種強(qiáng)有力的語言,靈活使用其語言元素,可以進(jìn)行非常復(fù)雜和高級的數(shù)據(jù)庫操作。下面我們將開始真正學(xué)習(xí)SQL。說明:SQL的擴(kuò)展

許多DBMS廠商通過增加語句或指令,對SQL進(jìn)行了擴(kuò)展。這種擴(kuò)展的目的是提供執(zhí)行特定操作的額外功能或簡化方法。雖然這種擴(kuò)展很有用,但一般都是針對個(gè)別DBMS的,很少有兩個(gè)以上的供應(yīng)商支持這種擴(kuò)展。標(biāo)準(zhǔn)SQL由ANSI標(biāo)準(zhǔn)委員會(huì)管理,從而稱為ANSISQL。所有主要的DBMS,即使有自己的擴(kuò)展,也都支持ANSISQL。各個(gè)實(shí)現(xiàn)有自己的名稱,如PL/SQL、Transact-SQL等。本書講授的SQL主要是ANSISQL。在使用某種DBMS特定的SQL時(shí),會(huì)特別說明。1.3動(dòng)手實(shí)踐與其他任何語言一樣,學(xué)習(xí)SQL的最好方法是自己動(dòng)手實(shí)踐。為此,需要一個(gè)數(shù)據(jù)庫和用來測試SQL語句的應(yīng)用系統(tǒng)。本書中所有課程采用的都是真實(shí)的SQL語句和數(shù)據(jù)表。附錄A給出了具體的樣例表,并介紹了獲得(或創(chuàng)建)它們的詳細(xì)步驟,便于讀者理解每一課講授的內(nèi)容。附錄B介紹在各種應(yīng)用程序中執(zhí)行SQL所需的步驟。在進(jìn)入下一課之前,強(qiáng)烈建議讀者先閱讀這兩個(gè)附錄的內(nèi)容,為以后的學(xué)習(xí)做好準(zhǔn)備。1.4小結(jié)這一課介紹了什么是SQL,它為什么很有用。因?yàn)镾QL是用來與數(shù)據(jù)庫打交道的,所以,我們也復(fù)習(xí)了一些基本的數(shù)據(jù)庫術(shù)語。第2課檢索數(shù)據(jù)這一課介紹如何使用SELECT語句從表中檢索一個(gè)或多個(gè)數(shù)據(jù)列。2.1SELECT語句正如第1課所述,SQL語句是由簡單的英語單詞構(gòu)成的。這些單詞稱為關(guān)鍵字,每個(gè)SQL語句都是由一個(gè)或多個(gè)關(guān)鍵字構(gòu)成的。最經(jīng)常使用的SQL語句大概就是SELECT語句了。它的用途是從一個(gè)或多個(gè)表中檢索信息。關(guān)鍵字(keyword)

作為SQL組成部分的保留字。關(guān)鍵字不能用作表或列的名字。附錄E列出了某些經(jīng)常使用的保留字。為了使用SELECT檢索表數(shù)據(jù),必須至少給出兩條信息——想選擇什么,以及從什么地方選擇。說明:理解例子

本書各課程中的樣例SQL語句(和樣例輸出)使用了附錄A中描述的一組數(shù)據(jù)文件。如果想要理解和試驗(yàn)這些樣例(我強(qiáng)烈建議這樣做),請參閱附錄A,它解釋了如何下載或創(chuàng)建這些數(shù)據(jù)文件。重要的是,要理解SQL是一種語言而不是一個(gè)應(yīng)用程序。具體如何寫SQL語句并顯示語句輸出,是隨不同的應(yīng)用程序而變化的。為幫助讀者根據(jù)自己的環(huán)境使用相應(yīng)的例子,附錄B介紹了如何針對許多流行的應(yīng)用程序及開發(fā)環(huán)境發(fā)出本書中介紹的語句。如果讀者需要了解某個(gè)應(yīng)用程序,附錄B中也給出了相應(yīng)的建議。2.2檢索單個(gè)列我們將從簡單的SQLSELECT語句講起,此語句如下所示:輸入▼SELECTprod_name

FROMProducts;

分析▼上述語句利用SELECT語句從Products表中檢索一個(gè)名為prod_name的列。所需的列名寫在SELECT關(guān)鍵字之后,F(xiàn)ROM關(guān)鍵字指出從哪個(gè)表中檢索數(shù)據(jù)。此語句的輸出如下所示:輸出▼prod_name

Fishbeanbagtoy

Birdbeanbagtoy

Rabbitbeanbagtoy

8inchteddybear

12inchteddybear

18inchteddybear

RaggedyAnn

Kingdoll

Queendoll

提示:未排序數(shù)據(jù)

如果你自己試驗(yàn)這個(gè)查詢,可能會(huì)發(fā)現(xiàn)顯示輸出的數(shù)據(jù)順序與這里的不同。出現(xiàn)這種情況很正常。如果沒有明確排序查詢結(jié)果(下一課介紹),則返回的數(shù)據(jù)沒有特定的順序。返回?cái)?shù)據(jù)的順序可能是數(shù)據(jù)被添加到表中的順序,也可能不是。只要返回相同數(shù)目的行,就是正常的。如上的一條簡單SELECT語句將返回表中的所有行。數(shù)據(jù)沒有過濾(過濾將得出結(jié)果集的一個(gè)子集),也沒有排序。以后幾課將討論這些內(nèi)容。提示:結(jié)束SQL語句

多條SQL語句必須以分號(;)分隔。多數(shù)DBMS不需要在單條SQL語句后加分號,但也有DBMS可能必須在單條SQL語句后加上分號。當(dāng)然,如果愿意可以總是加上分號。事實(shí)上,即使不一定需要,加上分號也肯定沒有壞處。提示:SQL語句和大小寫

請注意,SQL語句不區(qū)分大小寫,因此SELECT與select是相同的。同樣,寫成Select也沒有關(guān)系。許多SQL開發(fā)人員喜歡對SQL關(guān)鍵字使用大寫,而對列名和表名使用小寫,這樣做使代碼更易于閱讀和調(diào)試。不過,一定要認(rèn)識到雖然SQL是不區(qū)分大小寫的,但是表名、列名和值可能有所不同(這有賴于具體的DBMS及其如何配置)。提示:使用空格

在處理SQL語句時(shí),其中所有空格都被忽略。SQL語句可以寫成長長的一行,也可以分寫在多行。下面這三種寫法的作用是一樣的。SELECTprod_name

FROMProducts;

SELECTprod_nameFROMProducts;

SELECT

prod_name

FROM

Products;

多數(shù)SQL開發(fā)人員認(rèn)為,將SQL語句分成多行更容易閱讀和調(diào)試。2.3檢索多個(gè)列要想從一個(gè)表中檢索多個(gè)列,仍然使用相同的SELECT語句。唯一的不同是必須在SELECT關(guān)鍵字后給出多個(gè)列名,列名之間必須以逗號分隔。提示:當(dāng)心逗號

在選擇多個(gè)列時(shí),一定要在列名之間加上逗號,但最后一個(gè)列名后不加。如果在最后一個(gè)列名后加了逗號,將出現(xiàn)錯(cuò)誤。下面的SELECT語句從Products表中選擇3列。輸入▼SELECTprod_id,prod_name,prod_price

FROMProducts;

分析▼

與前一個(gè)例子一樣,這條語句使用SELECT語句從表Products中選擇數(shù)據(jù)。在這個(gè)例子中,指定了3個(gè)列名,列名之間用逗號分隔。此語句的輸出如下:輸出▼prod_idprod_nameprod_price

BNBG01Fishbeanbagtoy3.4900

BNBG02Birdbeanbagtoy3.4900

BNBG03Rabbitbeanbagtoy3.4900

BR018inchteddybear5.9900

BR0212inchteddybear8.9900

BR0318inchteddybear11.9900

RGAN01RaggedyAnn4.9900

RYL01Kingdoll9.4900

RYL02Queendool9.4900

說明:數(shù)據(jù)表示

從上述輸出可以看到,SQL語句一般返回原始的、無格式的數(shù)據(jù)。數(shù)據(jù)的格式化是表示問題,而不是檢索問題。因此,表示(如把上面的價(jià)格值顯示為正確的十進(jìn)制數(shù)值貨幣金額)一般在顯示該數(shù)據(jù)的應(yīng)用程序中規(guī)定。通常很少直接使用實(shí)際檢索出的數(shù)據(jù)(沒有應(yīng)用程序提供的格式)。2.4檢索所有列除了指定所需的列外(如上所述,一個(gè)或多個(gè)列),SELECT語句還可以檢索所有的列而不必逐個(gè)列出它們。在實(shí)際列名的位置使用星號(*)通配符可以做到這點(diǎn),如下所示。輸入▼SELECT*

FROMProducts;

分析▼

如果給定一個(gè)通配符(*),則返回表中所有列。列的順序一般是列在表定義中出現(xiàn)的物理順序,但并不總是如此。不過,SQL數(shù)據(jù)很少這樣(通常,數(shù)據(jù)返回給應(yīng)用程序,根據(jù)需要進(jìn)行格式化,再表示出來)。因此,這不應(yīng)該造成什么問題。警告:使用通配符

一般而言,除非你確實(shí)需要表中的每一列,否則最好別使用*通配符。雖然使用通配符能讓你自己省事,不用明確列出所需列,但檢索不需要的列通常會(huì)降低檢索和應(yīng)用程序的性能。提示:檢索未知列

使用通配符有一個(gè)大優(yōu)點(diǎn)。由于不明確指定列名(因?yàn)樾翘枡z索每一列),所以能檢索出名字未知的列。2.5檢索不同的值如前所述,SELECT語句返回所有匹配的行。但是,如果你不希望每個(gè)值每次都出現(xiàn),該怎么辦呢?例如,你想檢索products表中所有產(chǎn)品供應(yīng)商的ID:輸入▼SELECTvend_id

FROMProducts;

輸出▼vend_id

BRS01

BRS01

BRS01

DLL01

DLL01

DLL01

DLL01

FNG01

FNG01

SELECT語句返回9行(即使表中只有3個(gè)產(chǎn)品供應(yīng)商),因?yàn)閜roducts表中有9種產(chǎn)品。那么如何檢索出不同的值?辦法就是使用DISTINCT關(guān)鍵字,顧名思義,它指示數(shù)據(jù)庫只返回不同的值。輸入▼SELECTDISTINCTvend_id

FROMProducts;

分析▼SELECTDISTINCTvend_id告訴DBMS只返回不同(具有唯一性)的vend_id行,所以正如下面的輸出,只有3行。如果使用DISTINCT關(guān)鍵字,它必須直接放在列名的前面。輸出▼vend_id

BRS01

DLL01

FNG01

警告:不能部分使用DISTINCT

DISTINCT關(guān)鍵字作用于所有的列,不僅僅是跟在其后的那一列。例如,你指定SELECTDISTINCTvend_id,prod_price,除非指定的兩列完全相同,否則所有的行都會(huì)被檢索出來。2.6限制結(jié)果SELECT語句返回指定表中所有匹配的行,很可能是每一行。如果你只想返回第一行或者一定數(shù)量的行,該怎么辦呢?這是可行的,然而遺憾的是,各種數(shù)據(jù)庫中的這一SQL實(shí)現(xiàn)并不相同。在SQLServer和Access中使用SELECT時(shí),可以使用TOP關(guān)鍵字來限制最多返回多少行,如下所示:輸入▼SELECTTOP5prod_name

FROMProducts;

輸出▼prod_name

8inchteddybear

12inchteddybear

18inchteddybear

Fishbeanbagtoy

Birdbeanbagtoy

分析▼上面代碼使用SELECTTOP5語句,只檢索前5行數(shù)據(jù)。如果你使用的是DB2,很可能習(xí)慣使用下面這一DBMS特定的SQL語句,像這樣:輸入▼SELECTprod_name

FROMProducts

FETCHFIRST5ROWSONLY;

分析▼FETCHFIRST5ROWSONLY就會(huì)按字面的意思去做的。如果你使用Oracle,需要基于ROWNUM(行計(jì)數(shù)器)來計(jì)算行,像這樣:輸入▼SELECTprod_name

FROMProducts

WHEREROWNUM<=5;

如果你使用MySQL、MariaDB、PostgreSQL或者SQLite,需要使用LIMIT子句,像這樣:輸入▼SELECTprod_name

FROMProducts

LIMIT5;

分析▼上述代碼使用SELECT語句來檢索單獨(dú)的一列數(shù)據(jù)。LIMIT5指示MySQL等DBMS返回不超過5行的數(shù)據(jù)。這個(gè)語句的輸出參見下面的代碼。為了得到后面的5行數(shù)據(jù),需要指定從哪兒開始以及檢索的行數(shù),像這樣:輸入▼SELECTprod_name

FROMProducts

LIMIT5OFFSET5;

分析▼LIMIT5OFFSET5指示MySQL等DBMS返回從第5行起的5行數(shù)據(jù)。第一個(gè)數(shù)字是指從哪兒開始,第二個(gè)數(shù)字是檢索的行數(shù)。這個(gè)語句的輸出是:輸出▼prod_name

Rabbitbeanbagtoy

RaggedyAnn

Kingdoll

Queendoll

所以,LIMIT指定返回的行數(shù)。帶OFFSET的LIMIT指定從哪兒開始。在我們的例子中,Products表中只有9種產(chǎn)品,所以LIMIT5OFFSET5只返回了4行數(shù)據(jù)(因?yàn)闆]有第5行)。警告:第0行

第一個(gè)被檢索的行是第0行,而不是第1行。因此,LIMIT1OFFSET1會(huì)檢索第2行,而不是第1行。提示:MySQL和MariaDB快捷鍵

MySQL和MariaDB支持簡化版的LIMIT4OFFSET3語句,即LIMIT3,4。使用這個(gè)語法,,之前的值對應(yīng)LIMIT,,之后的值對應(yīng)OFFSET。說明:并非所有的SQL實(shí)現(xiàn)都一樣

我加入這一節(jié)只有一個(gè)原因,就是要說明,SQL雖然通常都有相當(dāng)一致的實(shí)現(xiàn),但你不能想當(dāng)然地認(rèn)為它總是這樣。非?;镜恼Z句往往是容易移植的,但較復(fù)雜的語句就不同了。當(dāng)你針對某個(gè)問題尋找SQL解決方案時(shí),一定要記住這一點(diǎn)。2.7使用注釋可以看到,SQL語句是由DBMS處理的指令。如果你希望包括不進(jìn)行處理和執(zhí)行的文本,該怎么辦呢?為什么你想要這么做呢?原因有以下幾點(diǎn)。我們這里使用的SQL語句都很短,也很簡單。然而,隨著你的SQL語句變長,復(fù)雜性增加,你就會(huì)想添加一些描述性的注釋,這便于你自己今后參考,或者供項(xiàng)目后續(xù)參與人員參考。這些注釋需要嵌入在SQL腳本中,但顯然不能進(jìn)行實(shí)際的DBMS處理。(相關(guān)示例可以參見附錄B中使用的create.sql和populate.sql。)這同樣適用于SQL文件開始處的內(nèi)容,它可能包含程序員的聯(lián)系方式、程序描述以及一些說明。(相關(guān)示例也可參見附錄B中的那些.sql文件。)注釋的另一個(gè)重要應(yīng)用是暫時(shí)停止要執(zhí)行的SQL代碼。如果你碰到一個(gè)長SQL語句,而只想測試它的一部分,那么應(yīng)該注釋掉一些代碼,以便MariaDB將其視為注釋而加以忽略。很多DBMS都支持各種形式的注釋語法。我們先來看行內(nèi)注釋:輸入▼SELECTprod_name--這是一條注釋

FROMProducts;

分析▼注釋使用--(兩個(gè)連字符)嵌在行內(nèi)。--之后的文本就是注釋,例如,這用來描述CREATETABLE語句中的列就很不錯(cuò)。下面是另一種形式的行內(nèi)注釋(雖然這種形式很少得到支持)。輸入▼#這是一條注釋

SELECTprod_name

FROMProducts;

分析▼在一行的開始處使用#,這一整行都將作為注釋。你在本書提供的腳本create.sql和populate.sql中可以看到這種形式的注釋。你也可以進(jìn)行多行注釋,注釋可以在腳本的任何位置停止和開始。輸入▼/*SELECTprod_name,vend_id

FROMProducts;*/

SELECTprod_name

FROMProducts;

分析▼注釋從/*開始,到*/結(jié)束,/*和*/之間的任何內(nèi)容都是注釋。這種方式常用于給代碼加注釋,就如這個(gè)例子演示的,這里定義了兩個(gè)SELECT語句,但是第一個(gè)不會(huì)執(zhí)行,因?yàn)樗呀?jīng)被注釋掉了。2.8小結(jié)這一課學(xué)習(xí)了如何使用SQL的SELECT語句來檢索單個(gè)表列、多個(gè)表列以及所有表列。你也學(xué)習(xí)了如何返回不同的值,如何注釋代碼。同時(shí)不幸的是,更復(fù)雜的SQL使得SQL代碼變得不輕便。下一課將講授如何對檢索出來的數(shù)據(jù)進(jìn)行排序。第3課排序檢索數(shù)據(jù)這一課講授如何使用SELECT語句的ORDERBY子句,根據(jù)需要排序檢索出的數(shù)據(jù)。3.1排序數(shù)據(jù)正如上一課所述,下面的SQL語句返回某個(gè)數(shù)據(jù)庫表的單個(gè)列。但請看其輸出,并沒有特定的順序。輸入▼SELECTprod_name

FROMProducts;

輸出▼prod_name

Fishbeanbagtoy

Birdbeanbagtoy

Rabbitbeanbagtoy

8inchteddybear

12inchteddybear

18inchteddybear

RaggedyAnn

Kingdoll

Queendoll

其實(shí),檢索出的數(shù)據(jù)并不是隨機(jī)顯示的。如果不排序,數(shù)據(jù)一般將以它在底層表中出現(xiàn)的順序顯示,這有可能是數(shù)據(jù)最初添加到表中的順序。但是,如果數(shù)據(jù)隨后進(jìn)行過更新或刪除,那么這個(gè)順序?qū)?huì)受到DBMS重用回收存儲(chǔ)空間的方式的影響。因此,如果不明確控制的話,則最終的結(jié)果不能(也不應(yīng)該)依賴該排序順序。關(guān)系數(shù)據(jù)庫設(shè)計(jì)理論認(rèn)為,如果不明確規(guī)定排序順序,則不應(yīng)該假定檢索出的數(shù)據(jù)的順序有任何意義。子句(clause)

SQL語句由子句構(gòu)成,有些子句是必需的,有些則是可選的。一個(gè)子句通常由一個(gè)關(guān)鍵字加上所提供的數(shù)據(jù)組成。子句的例子有我們在前一課看到的SELECT語句的FROM子句。為了明確地排序用SELECT語句檢索出的數(shù)據(jù),可使用ORDERBY子句。ORDERBY子句取一個(gè)或多個(gè)列的名字,據(jù)此對輸出進(jìn)行排序。請看下面的例子:輸入▼SELECTprod_name

FROMProducts

ORDERBYprod_name;

分析▼

除了指示DBMS軟件對prod_name列以字母順序排序數(shù)據(jù)的ORDERBY子句外,這條語句與前面的語句相同。結(jié)果如下。輸出▼prod_name

12inchteddybear

18inchteddybear

8inchteddybear

Birdbeanbagtoy

Fishbeanbagtoy

Kingdoll

Queendoll

Rabbitbeanbagtoy

RaggedyAnn

ORDERBY子句的位置

在指定一條ORDERBY子句時(shí),應(yīng)該保證它是SELECT語句中最后一條子句。如果它不是最后的子句,將會(huì)出現(xiàn)錯(cuò)誤消息。通過非選擇列進(jìn)行排序

通常,ORDERBY子句中使用的列將是為顯示而選擇的列。但是,實(shí)際上并不一定要這樣,用非檢索的列排序數(shù)據(jù)是完全合法的。3.2按多個(gè)列排序經(jīng)常需要按不止一個(gè)列進(jìn)行數(shù)據(jù)排序。例如,如果要顯示雇員名單,可能希望按姓和名排序(首先按姓排序,然后在每個(gè)姓中再按名排序)。如果多個(gè)雇員有相同的姓,這樣做很有用。要按多個(gè)列排序,簡單指定列名,列名之間用逗號分開即可(就像選擇多個(gè)列時(shí)那樣)。下面的代碼檢索3個(gè)列,并按其中兩個(gè)列對結(jié)果進(jìn)行排序——首先按價(jià)格,然后按名稱排序。輸入▼SELECTprod_id,prod_price,prod_name

FROMProducts

ORDERBYprod_price,prod_name;

輸出▼prod_idprod_priceprod_name

BNBG023.4900Birdbeanbagtoy

BNBG013.4900Fishbeanbagtoy

BNBG033.4900Rabbitbeanbagtoy

RGAN014.9900RaggedyAnn

BR015.99008inchteddybear

BR028.990012inchteddybear

RYL019.4900Kingdoll

RYL029.4900Queendoll

BR0311.990018inchteddybear

重要的是理解在按多個(gè)列排序時(shí),排序的順序完全按規(guī)定進(jìn)行。換句話說,對于上述例子中的輸出,僅在多個(gè)行具有相同的prod_price值時(shí)才對產(chǎn)品按prod_name進(jìn)行排序。如果prod_price列中所有的值都是唯一的,則不會(huì)按prod_name排序。3.3按列位置排序除了能用列名指出排序順序外,ORDERBY還支持按相對列位置進(jìn)行排序。為理解這一內(nèi)容,我們來看個(gè)例子:輸入▼SELECTprod_id,prod_price,prod_name

FROMProducts

ORDERBY2,3;

輸出▼prod_idprod_priceprod_name

BNBG023.4900Birdbeanbagtoy

BNBG013.4900Fishbeanbagtoy

BNBG033.4900Rabbitbeanbagtoy

RGAN014.9900RaggedyAnn

BR015.99008inchteddybear

BR028.990012inchteddybear

RYL019.4900Kingdoll

RYL029.4900Queendoll

BR0311.990018inchteddybear

分析▼可以看到,這里的輸出與上面的查詢相同,不同之處在于ORDERBY子句。SELECT清單中指定的是選擇列的相對位置而不是列名。ORDERBY2表示按SELECT清單中的第二個(gè)列prod_name進(jìn)行排序。ORDERBY2,3表示先按prod_price,再按prod_name進(jìn)行排序。這一技術(shù)的主要好處在于不用重新輸入列名。但它也有缺點(diǎn)。首先,不明確給出列名有可能造成錯(cuò)用列名排序。其次,在對SELECT清單進(jìn)行更改時(shí)容易錯(cuò)誤地對數(shù)據(jù)進(jìn)行排序(忘記對ORDERBY子句做相應(yīng)的改動(dòng))。最后,如果進(jìn)行排序的列不在SELECT清單中,顯然不能使用這項(xiàng)技術(shù)。按非選擇列排序

顯然,當(dāng)根據(jù)不出現(xiàn)在SELECT清單中的列進(jìn)行排序時(shí),不能采用這項(xiàng)技術(shù)。但是,如果有必要,可以混合匹配使用實(shí)際列名和相對列位置。3.4指定排序方向數(shù)據(jù)排序不限于升序排序(從A到Z),這只是默認(rèn)的排序順序。還可以使用ORDERBY子句進(jìn)行降序(從Z到A)排序。為了進(jìn)行降序排序,必須指定DESC關(guān)鍵字。下面的例子以價(jià)格降序來排序產(chǎn)品(最貴的排在最前面):輸入▼SELECTprod_id,prod_price,prod_name

FROMProducts

ORDERBYprod_priceDESC;

輸出▼prod_idprod_priceprod_name

BR0311.990018inchteddybear

RYL019.4900Kingdoll

RYL029.4900Queendoll

BR028.990012inchteddybear

BR015.99008inchteddybear

RGAN014.9900RaggedyAnn

BNBG013.4900Fishbeanbagtoy

BNBG023.4900Birdbeanbagtoy

BNBG033.4900Rabbitbeanbagtoy

如果打算用多個(gè)列排序,該怎么辦?下面的例子以降序排序產(chǎn)品(最貴的在最前面),再加上產(chǎn)品名:輸入▼SELECTprod_id,prod_price,prod_name

FROMProducts

ORDERBYprod_priceDESC,prod_name;

輸出▼prod_idprod_priceprod_name

BR0311.990018inchteddybear

RYL019.4900Kingdoll

RYL029.4900Queendoll

BR028.990012inchteddybear

BR015.99008inchteddybear

RGAN014.9900RaggedyAnn

BNBG023.4900Birdbeanbagtoy

BNBG013.4900Fishbeanbagtoy

BNBG033.4900Rabbitbeanbagtoy

分析▼

DESC關(guān)鍵字只應(yīng)用到直接位于其前面的列名。在上例中,只對prod_price列指定DESC,對prod_name列不指定。因此,prod_price列以降序排序,而prod_name列(在每個(gè)價(jià)格內(nèi))仍然按標(biāo)準(zhǔn)的升序排序。警告:在多個(gè)列上降序排序

如果想在多個(gè)列上進(jìn)行降序排序,必須對每一列指定DESC關(guān)鍵字。請注意,DESC是DESCENDING的縮寫,這兩個(gè)關(guān)鍵字都可以使用。與DESC相對的是ASC(或ASCENDING),在升序排序時(shí)可以指定它。但實(shí)際上,ASC沒有多大用處,因?yàn)樯蚴悄J(rèn)的(如果既不指定ASC也不指定DESC,則假定為ASC)。提示:區(qū)分大小寫和排序順序

在對文本性數(shù)據(jù)進(jìn)行排序時(shí),A與a相同嗎?a位于B之前,還是Z之后?這些問題不是理論問題,其答案取決于數(shù)據(jù)庫的設(shè)置方式。在字典(dictionary)排序順序中,A被視為與a相同,這是大多數(shù)數(shù)據(jù)庫管理系統(tǒng)的默認(rèn)行為。但是,許多DBMS允許數(shù)據(jù)庫管理員在需要時(shí)改變這種行為(如果你的數(shù)據(jù)庫包含大量外語字符,可能必須這樣做)。這里的關(guān)鍵問題是,如果確實(shí)需要改變這種排序順序,用簡單的ORDERBY子句可能做不到。你必須請求數(shù)據(jù)庫管理員的幫助。3.5小結(jié)這一課學(xué)習(xí)了如何用SELECT語句的ORDERBY子句對檢索出的數(shù)據(jù)進(jìn)行排序。這個(gè)子句必須是SELECT語句中的最后一條子句。根據(jù)需要,可以利用它在一個(gè)或多個(gè)列上對數(shù)據(jù)進(jìn)行排序。第4課過濾數(shù)據(jù)這一課將講授如何使用SELECT語句的WHERE子句指定搜索條件。4.1使用WHERE子句數(shù)據(jù)庫表一般包含大量的數(shù)據(jù),很少需要檢索表中的所有行。通常只會(huì)根據(jù)特定操作或報(bào)告的需要提取表數(shù)據(jù)的子集。只檢索所需數(shù)據(jù)需要指定搜索條件(searchcriteria),搜索條件也稱為過濾條件(filtercondition)。在SELECT語句中,數(shù)據(jù)根據(jù)WHERE子句中指定的搜索條件進(jìn)行過濾。WHERE子句在表名(FROM子句)之后給出,如下所示:輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREprod_price=3.49;

分析▼

這條語句從products表中檢索兩個(gè)列,但不返回所有行,只返回prod_price值為3.49的行,如下所示:輸出▼prod_nameprod_price

Fishbeanbagtoy3.49

Birdbeanbagtoy3.49

Rabbitbeanbagtoy3.49

這個(gè)示例使用了簡單的相等檢驗(yàn):檢查這一列的值是否為指定值,據(jù)此過濾數(shù)據(jù)。不過,SQL不止能測試等于,還能做更多的事情。提示:有多少個(gè)0?

你在練習(xí)這個(gè)示例時(shí),會(huì)發(fā)現(xiàn)顯示的結(jié)果可能是3.49、3.490、3.4900等。出現(xiàn)這樣的情況,往往是因?yàn)镈BMS指定了所使用的數(shù)據(jù)類型及其默認(rèn)行為。所以,如果你的輸出可能與書上的有點(diǎn)不同,不必焦慮,畢竟從數(shù)學(xué)角度講,3.49和3.4900是一樣的。提示:SQL過濾與應(yīng)用過濾

數(shù)據(jù)也可以在應(yīng)用層過濾。為此,SQL的SELECT語句為客戶端應(yīng)用檢索出超過實(shí)際所需的數(shù)據(jù),然后客戶端代碼對返回?cái)?shù)據(jù)進(jìn)行循環(huán),提取出需要的行。通常,這種做法極其不妥。優(yōu)化數(shù)據(jù)庫后可以更快速有效地對數(shù)據(jù)進(jìn)行過濾。而讓客戶端應(yīng)用(或開發(fā)語言)處理數(shù)據(jù)庫的工作將會(huì)極大地影響應(yīng)用的性能,并且使所創(chuàng)建的應(yīng)用完全不具備可伸縮性。此外,如果在客戶端過濾數(shù)據(jù),服務(wù)器不得不通過網(wǎng)絡(luò)發(fā)送多余的數(shù)據(jù),這將導(dǎo)致網(wǎng)絡(luò)帶寬的浪費(fèi)。警告:WHERE子句的位置

在同時(shí)使用ORDERBY和WHERE子句時(shí),應(yīng)該讓ORDERBY位于WHERE之后,否則將會(huì)產(chǎn)生錯(cuò)誤(關(guān)于ORDERBY的使用,請參閱第3課)。4.2WHERE子句操作符我們在做相等檢驗(yàn)時(shí)看到了第一個(gè)WHERE子句,它確定一個(gè)列是否包含指定的值。SQL支持表4-1列出的所有條件操作符。表4-1WHERE子句操作符操作符說明=等于<>不等于!=不等于<小于<=小于等于!不小于>大于>=大于等于!>不大于BETWEEN在指定的兩個(gè)值之間ISNULL為NULL值警告:操作符兼容

表4-1中列出的某些操作符是冗余的(如<>與!=相同,!<相當(dāng)于>=)。并非所有DBMS都支持這些操作符。想確定你的DBMS支持哪些操作符,請參閱相應(yīng)的文檔。4.2.1檢查單個(gè)值我們已經(jīng)看到了檢驗(yàn)相等的例子,現(xiàn)在來看看幾個(gè)使用其他操作符的例子。第一個(gè)例子是列出所有價(jià)格小于10美元的產(chǎn)品:輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREprod_price<10;

輸出▼prod_nameprod_price

Fishbeanbagtoy3.49

Birdbeanbagtoy3.49

Rabbitbeanbagtoy3.49

8inchteddybear5.99

12inchteddybear8.99

RaggedyAnn4.99

Kingdoll9.49

Queendoll9.49

下一條語句檢索所有價(jià)格小于等于10美元的產(chǎn)品(因?yàn)闆]有價(jià)格恰好是10美元的產(chǎn)品,所以結(jié)果與前一個(gè)例子相同):輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREprod_price<=10;

4.2.2不匹配檢查這個(gè)例子列出所有不是供應(yīng)商DLL01制造的產(chǎn)品:輸入▼SELECTvend_id,prod_name

FROMProducts

WHEREvend_id<>'DLL01';

輸出▼vend_idprod_name

BRS018inchteddybear

BRS0112inchteddybear

BRS0118inchteddybear

FNG01Kingdoll

FNG01Queendoll

提示:何時(shí)使用引號

如果仔細(xì)觀察上述WHERE子句中的條件,會(huì)看到有的值括在單引號內(nèi),而有的值未括起來。單引號用來限定字符串。如果將值與字符串類型的列進(jìn)行比較,就需要限定引號。用來與數(shù)值列進(jìn)行比較的值不用引號。下面是相同的例子,其中使用!=而不是<>操作符:輸入▼SELECTvend_id,prod_name

FROMProducts

WHEREvend_id!='DLL01';

警告:是!=還是<>?

!=和<>通??梢曰Q。但是,并非所有DBMS都支持這兩種不等于操作符。例如,MicrosoftAccess支持<>而不支持!=。如果有疑問,請參閱相應(yīng)的DBMS文檔。4.2.3范圍值檢查要檢查某個(gè)范圍的值,可以使用BETWEEN操作符。其語法與其他WHERE子句的操作符稍有不同,因?yàn)樗枰獌蓚€(gè)值,即范圍的開始值和結(jié)束值。例如,BETWEEN操作符可用來檢索價(jià)格在5美元和10美元之間的所有產(chǎn)品,或在指定的開始日期和結(jié)束日期之間的所有日期。下面的例子說明如何使用BETWEEN操作符,它檢索價(jià)格在5美元和10美元之間的所有產(chǎn)品:輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREprod_priceBETWEEN5AND10;

輸出▼prod_nameprod_price

8inchteddybear5.99

12inchteddybear8.99

Kingdoll9.49

Queendoll9.49

分析▼

從這個(gè)例子可以看到,在使用BETWEEN時(shí),必須指定兩個(gè)值——所需范圍的低端值和高端值。這兩個(gè)值必須用AND關(guān)鍵字分隔。BETWEEN匹配范圍中所有的值,包括指定的開始值和結(jié)束值。4.2.4空值檢查在創(chuàng)建表時(shí),表設(shè)計(jì)人員可以指定其中的列能否不包含值。在一個(gè)列不包含值時(shí),稱其包含空值NULL。NULL

無值(novalue),它與字段包含0、空字符串或僅僅包含空格不同。確定值是否為NULL,不能簡單地檢查是否=NULL。SELECT語句有一個(gè)特殊的WHERE子句,可用來檢查具有NULL值的列。這個(gè)WHERE子句就是ISNULL子句。其語法如下:輸入▼SELECTprod_name

FROMProducts

WHEREprod_priceISNULL;

這條語句返回所有沒有價(jià)格(空prod_price字段,不是價(jià)格為0)的產(chǎn)品,由于表中沒有這樣的行,所以沒有返回?cái)?shù)據(jù)。但是,Customers表確實(shí)包含具有NULL值的列:如果沒有電子郵件地址,則cust_email列將包含NULL值:輸入▼SELECTcust_name

FROMCUSTOMERS

WHEREcust_emailISNULL;

輸出▼cust_name

KidsPlace

TheToyStore

提示:各DBMS特有的操作符

許多DBMS擴(kuò)展了標(biāo)準(zhǔn)的操作符集,提供了更高級的過濾選擇。更多信息請參閱相應(yīng)的DBMS文檔。警告:NULL和非匹配

通過過濾選擇不包含指定值的所有行時(shí),你可能希望返回含NULL值的行。但是這做不到。因?yàn)槲粗╱nknown)有特殊的含義,數(shù)據(jù)庫不知道它們是否匹配,所以在進(jìn)行匹配過濾或非匹配過濾時(shí),不會(huì)返回這些結(jié)果。過濾數(shù)據(jù)時(shí),一定要驗(yàn)證被過濾列中含NULL的行確實(shí)出現(xiàn)在返回的數(shù)據(jù)中。4.3小結(jié)這一課介紹了如何用SELECT語句的WHERE子句過濾返回的數(shù)據(jù)。我們學(xué)習(xí)了如何檢驗(yàn)相等、不相等、大于、小于、值的范圍以及NULL值等。第5課高級數(shù)據(jù)過濾這一課講授如何組合WHERE子句以建立功能更強(qiáng)、更高級的搜索條件。我們還將學(xué)習(xí)如何使用NOT和IN操作符。5.1組合WHERE子句第4課介紹的所有WHERE子句在過濾數(shù)據(jù)時(shí)使用的都是單一的條件。為了進(jìn)行更強(qiáng)的過濾控制,SQL允許給出多個(gè)WHERE子句。這些子句有兩種使用方式,即以AND子句或OR子句的方式使用。操作符(operator)

用來聯(lián)結(jié)或改變WHERE子句中的子句的關(guān)鍵字,也稱為邏輯操作符(logicaloperator)。5.1.1AND操作符要通過不止一個(gè)列進(jìn)行過濾,可以使用AND操作符給WHERE子句附加條件。下面的代碼給出了一個(gè)例子:輸入▼SELECTprod_id,prod_price,prod_name

FROMProducts

WHEREvend_id='DLL01'ANDprod_price<=4;

分析▼

此SQL語句檢索由供應(yīng)商DLL01制造且價(jià)格小于等于4美元的所有產(chǎn)品的名稱和價(jià)格。這條SELECT語句中的WHERE子句包含兩個(gè)條件,用AND關(guān)鍵字聯(lián)結(jié)在一起。AND指示DBMS只返回滿足所有給定條件的行。如果某個(gè)產(chǎn)品由供應(yīng)商DLL01制造,但價(jià)格高于4美元,則不檢索它。類似地,如果產(chǎn)品價(jià)格小于4美元,但不是由指定供應(yīng)商制造的也不被檢索。這條SQL語句產(chǎn)生的輸出如下:輸出▼prod_idprod_priceprod_name

BNBG023.4900Birdbeanbagtoy

BNBG013.4900Fishbeanbagtoy

BNBG033.4900Rabbitbeanbagtoy

AND

用在WHERE子句中的關(guān)鍵字,用來指示檢索滿足所有給定條件的行。這個(gè)例子只包含一個(gè)AND子句,因此最多有兩個(gè)過濾條件??梢栽黾佣鄠€(gè)過濾條件,每個(gè)條件間都要使用AND關(guān)鍵字。說明:沒有ORDERBY子句

為了節(jié)省空間,也為了減少你的輸入,我在很多例子里省略了ORDERBY子句。因此,你的輸出完全有可能與書上的輸出不一致。雖然返回行的數(shù)量總是對的,但它們的順序可能不同。當(dāng)然,如果你愿意也可以加上一個(gè)ORDERBY子句,它應(yīng)該放在WHERE子句之后。5.1.2OR操作符OR操作符與AND操作符正好相反,它指示DBMS檢索匹配任一條件的行。事實(shí)上,許多DBMS在ORWHERE子句的第一個(gè)條件得到滿足的情況下,就不再計(jì)算第二個(gè)條件了(在第一個(gè)條件滿足時(shí),不管第二個(gè)條件是否滿足,相應(yīng)的行都將被檢索出來)。請看如下的SELECT語句:輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREvend_id='DLL01'ORvend_id=‘BRS01’;

分析▼

此SQL語句檢索由任一個(gè)指定供應(yīng)商制造的所有產(chǎn)品的產(chǎn)品名和價(jià)格。OR操作符告訴DBMS匹配任一條件而不是同時(shí)匹配兩個(gè)條件。如果這里使用的是AND操作符,則沒有數(shù)據(jù)返回(因?yàn)闀?huì)創(chuàng)建沒有匹配行的WHERE子句)。這條SQL語句產(chǎn)生的輸出如下:輸出▼prod_nameprod_price

Fishbeanbagtoy3.4900

Birdbeanbagtoy3.4900

Rabbitbeanbagtoy3.4900

8inchteddybear5.9900

12inchteddybear8.9900

18inchteddybear11.9900

RaggedyAnn4.9900

OR

WHERE子句中使用的關(guān)鍵字,用來表示檢索匹配任一給定條件的行。5.1.3求值順序WHERE子句可以包含任意數(shù)目的AND和OR操作符。允許兩者結(jié)合以進(jìn)行復(fù)雜、高級的過濾。但是,組合AND和OR會(huì)帶來了一個(gè)有趣的問題。為了說明這個(gè)問題,來看一個(gè)例子。假如需要列出價(jià)格為10美元及以上,且由DLL01或BRS01制造的所有產(chǎn)品。下面的SELECT語句使用組合的AND和OR操作符建立了一個(gè)WHERE子句:輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREvend_id='DLL01'ORvend_id=‘BRS01’

ANDprod_price>=10;

輸出▼prod_nameprod_price

Fishbeanbagtoy3.4900

Birdbeanbagtoy3.4900

Rabbitbeanbagtoy3.4900

18inchteddybear11.9900

RaggedyAnn4.9900

分析▼

請看上面的結(jié)果。返回的行中有4行價(jià)格小于10美元,顯然,返回的行未按預(yù)期的進(jìn)行過濾。為什么會(huì)這樣呢?原因在于求值的順序。SQL(像多數(shù)語言一樣)在處理OR操作符前,優(yōu)先處理AND操作符。當(dāng)SQL看到上述WHERE子句時(shí),它理解為:由供應(yīng)商BRS01制造的價(jià)格為10美元以上的所有產(chǎn)品,以及由供應(yīng)商DLL01制造的所有產(chǎn)品,而不管其價(jià)格如何。換句話說,由于AND在求值過程中優(yōu)先級更高,操作符被錯(cuò)誤地組合了。此問題的解決方法是使用圓括號對操作符進(jìn)行明確分組。請看下面的SELECT語句及輸出:輸入▼SELECTprod_name,prod_price

FROMProducts

WHERE(vend_id='DLL01'ORvend_id=‘BRS01’)

ANDprod_price>=10;

輸出▼prod_nameprod_price

18inchteddybear11.9900

分析▼

這條SELECT語句與前一條的唯一差別是,將前兩個(gè)條件用圓括號括了起來。因?yàn)閳A括號具有比AND或OR操作符更高的求值順序,所以DBMS首先過濾圓括號內(nèi)的OR條件。這時(shí),SQL語句變成了選擇由供應(yīng)商DLL01或BRS01制造的且價(jià)格在10美元及以上的所有產(chǎn)品,這正是我們希望的結(jié)果。提示:在WHERE子句中使用圓括號

任何時(shí)候使用具有AND和OR操作符的WHERE子句,都應(yīng)該使用圓括號明確地分組操作符。不要過分依賴默認(rèn)求值順序,即使它確實(shí)如你希望的那樣。使用圓括號沒有什么壞處,它能消除歧義。5.2IN操作符IN操作符用來指定條件范圍,范圍中的每個(gè)條件都可以進(jìn)行匹配。IN取一組由逗號分隔、括在圓括號中的合法值。下面的例子說明了這個(gè)操作符:輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREvend_idIN('DLL01','BRS01')

ORDERBYprod_name;

輸出▼prod_nameprod_price

12inchteddybear8.9900

18inchteddybear11.9900

8inchteddybear5.9900

Birdbeanbagtoy3.4900

Fishbeanbagtoy3.4900

Rabbitbeanbagtoy3.4900

RaggedyAnn4.9900

分析▼

此SELECT語句檢索由供應(yīng)商DLL01和BRS01制造的所有產(chǎn)品。IN操作符后跟由逗號分隔的合法值,這些值必須括在圓括號中。你可能會(huì)猜測IN操作符完成了與OR相同的功能,恭喜你猜對了!下面的SQL語句完成與上面的例子相同的工作:輸入▼SELECTprod_name,prod_price

FROMProducts

WHEREvend_id='DLL01'ORvend_id='BRS01'

ORDERBYprod_name;

輸出▼prod_nameprod_price

12inchteddybear8.9900

18inchteddybear11.9900

8inchteddybear5.9900

Birdbeanbagtoy3.4900

Fishbeanbagtoy3.4900

Rabbitbeanbagtoy3.4900

RaggedyAnn4.9900

為什么要使用IN操作符?其優(yōu)點(diǎn)為:在有很多合法選項(xiàng)時(shí),IN操作符的語法更清楚,更直觀。在與其他AND和OR操作符組合使用IN時(shí),求值順序更容易管理。IN操作符一般比一組OR操作符執(zhí)行得更快(在上面這個(gè)合法選項(xiàng)很少的例子中,你看不出性能差異)。IN的最大優(yōu)點(diǎn)是可以包含其他SELECT語句,能夠更動(dòng)態(tài)地建立WHERE子句。第11課會(huì)對此進(jìn)行詳細(xì)介紹。IN

WHERE子句中用來指定要匹配值的清單的關(guān)鍵字,功能與OR相當(dāng)。5.3NOT操作符WHERE子句中的NOT操作符有且只有一個(gè)功能,那就是否定其后所跟的任何條件。因?yàn)镹OT從不單獨(dú)使用(它總是與其他操作符一起使用),所以它的語法與其他操作符有所不同。NOT關(guān)鍵字可以用在要過濾的列前,而不僅是在其后。NOT

WHERE子句中用來否定其后條件的關(guān)鍵字。下面的例子說明NOT的用法。為了列出除DLL01之外的所有供應(yīng)商制造的產(chǎn)品,可編寫如下的代碼:輸入▼SELECTprod_name

FROMProducts

WHERENOTvend_id='DLL01'

ORDERBYprod_name;

輸出▼prod_name

12inchteddybear

18inchteddybear

8inchteddybear

Kingdoll

Queendoll

分析▼

這里的NOT否定跟在其后的條件,因此,DBMS不是匹配vend_id為DLL01,而是匹配非DLL01之外的所有東西。上面的例子也可以使用<>操作符來完成,如下所示:輸入▼SELECTprod_name

FROMProducts

WHEREvend_id<>'DLL01'

ORDERBYprod_name;

輸出▼prod_name

12inchteddybear

18inchteddybear

8inchteddybear

Kingdoll

Queendoll

分析▼

為什么使用NOT?對于這里的這種簡單的WHERE子句,使用NOT確實(shí)沒有什么優(yōu)勢。但在更復(fù)雜的子句中,NOT是非常有用的。例如,在與IN操作符聯(lián)合使用時(shí),NOT可以非常簡單地找出與條件列表不匹配的行。說明:MariaDB中的NOT

MariaDB支持使用NOT否定IN、BETWEEN和EXISTS子句。大多數(shù)DBMS允許使用NOT否定任何條件。5.4小結(jié)這一課講授如何用AND和OR操作符組合成WHERE子句,還講授了如何明確地管理求值順序,如何使用IN和NOT操作符。第6課用通配符進(jìn)行過濾這一課介紹什么是通配符、如何使用通配符以及怎樣使用LIKE操作符進(jìn)行通配搜索,以便對數(shù)據(jù)進(jìn)行復(fù)雜過濾。6.1LIKE操作符前面介紹的所有操作符都是針對已知值進(jìn)行過濾的。不管是匹配一個(gè)值還是多個(gè)值,檢驗(yàn)大于還是小于已知值,或者檢查某個(gè)范圍的值,其共同點(diǎn)是過濾中使用的值都是已知的。但是,這種過濾方法并不是任何時(shí)候都好用。例如,怎樣搜索產(chǎn)品名中包含文本beanbag的所有產(chǎn)品?用簡單的比較操作符肯定不行,必須使用通配符。利用通配符,可以創(chuàng)建比較特定數(shù)據(jù)的搜索模式。在這個(gè)例子中,如果你想找出名稱包含beanbag的所有產(chǎn)品,可以構(gòu)造一個(gè)通配符搜索模式,找出在產(chǎn)品名的任何位置出現(xiàn)beanbag的產(chǎn)品。通配符(wildcard)

用來匹配值的一部分的特殊字符。搜索模式(searchpattern)

由字面值、通配符或兩者組合構(gòu)成的搜索條件。通配符本身實(shí)際上是SQL的WHERE子句中有特殊含義的字符,SQL支持幾種通配符。為在搜索子句中使用通配符,必須使用LIKE操作符。LIKE指示DBMS,后跟的搜索模式利用通配符匹配而不是簡單的相等匹配進(jìn)行比較。謂詞(predicate)

操作符何時(shí)不是操作符?答案是,它作為謂詞時(shí)。從技術(shù)上說,LIKE是謂詞而不是操作符。雖然最終的結(jié)果是相同的,但應(yīng)該對此術(shù)語有所了解,以免在SQL文獻(xiàn)或手冊中遇到此術(shù)語時(shí)不知所云。通配符搜索只能用于文本字段(串),非文本數(shù)據(jù)類型字段不能使用通配符搜索。6.1.1百分號(%)通配符最常使用的通配符是百分號(%)。在搜索串中,%表示任何字符出現(xiàn)任意次數(shù)。例如,為了找出所有以詞Fish起頭的產(chǎn)品,可發(fā)布以下SELECT語句:輸入▼SELECTprod_id,prod_name

FROMProducts

WHEREprod_nameLIKE'Fish%';

輸出▼prod_idprod_name

BNBG01Fishbeanbagtoy

分析▼

此例子使用了搜索模式'Fish%'。在執(zhí)行這條子句時(shí),將檢索任意以Fish起頭的詞。%告訴DBMS接受Fish之后的任意字符,不管它有多少字符。說明:Acces

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論