在數(shù)據(jù)庫(kù)設(shè)計(jì)與管理中,WHERE子句無(wú)疑是大家用的最頻繁的一個(gè)子句之一。那么大家是否真的擅長(zhǎng)這個(gè)子句的使用呢?我看不見(jiàn)的的吧。筆者的下面這些建議就可以幫助大家來(lái)充分使用WHERE子句的功能,發(fā)揮其強(qiáng)大的作用。
建議一:查詢條件中包含撇號(hào)怎么處理?
數(shù)據(jù)庫(kù)的某些列中,可能會(huì)包含一些特殊的符號(hào),如撇號(hào)(‘)。這對(duì)于SQLServer數(shù)據(jù)庫(kù)來(lái)說(shuō)是一個(gè)特殊的符號(hào)。因?yàn)槠湓臼怯脕?lái)區(qū)分字符與變量的。如在查詢語(yǔ)句中,如果輸入的是字符串的值,就需要利用兩個(gè)撇號(hào)引用起來(lái)。(有時(shí)候撇號(hào)大家又叫做單引號(hào))。但是在有些情況下,特別是國(guó)外人的名字中,本身就包含著單引號(hào)。如某個(gè)產(chǎn)品的規(guī)格信息為“8’尖嘴鉗(07型)/ 碳鋼/ 熱處理/ 全拋光/ 鍍鎳鐵合金/ 橙色”。在這個(gè)規(guī)格信息中就有一個(gè)單引號(hào)。此時(shí)如果在WHERE查詢語(yǔ)句中需要查詢這個(gè)規(guī)格信息,那么這個(gè)單引號(hào)還如何處理呢?數(shù)據(jù)庫(kù)管理員如果按如下的格式來(lái)輸入查詢語(yǔ)句(WHERE Description like ‘8’尖嘴鉗’),能夠查詢到所需要的結(jié)果呢?答案是否定的。因?yàn)榇藭r(shí)數(shù)據(jù)庫(kù)系統(tǒng)因?yàn)檫@個(gè)查詢語(yǔ)句中有三個(gè)單引號(hào)分割符號(hào),為此數(shù)據(jù)庫(kù)優(yōu)化器在編譯優(yōu)化這條語(yǔ)句的時(shí)候,無(wú)法識(shí)別輸入的條件語(yǔ)句的含義。
為此數(shù)據(jù)庫(kù)管理員在設(shè)計(jì)查詢語(yǔ)句的時(shí)候,就需要預(yù)計(jì)到這種情況,并在編寫(xiě)語(yǔ)句的時(shí)候采取措施來(lái)避免這種錯(cuò)誤。如果要在查詢條件中包含單引號(hào)的這個(gè)特殊符號(hào)也未嘗不可。在SQLServer數(shù)據(jù)庫(kù)中,如果需要查找的數(shù)據(jù)包含一個(gè)單引號(hào)時(shí),則可以輸入兩個(gè)單引號(hào)來(lái)標(biāo)明這個(gè)單引號(hào)是文本值而非分隔符。其實(shí),這個(gè)單引號(hào)就好像程序開(kāi)發(fā)語(yǔ)言中的轉(zhuǎn)移字符,能夠把系統(tǒng)中的一些特殊符號(hào)轉(zhuǎn)換成文本符號(hào)。不過(guò)由于轉(zhuǎn)義字符的使用或多或少會(huì)影響數(shù)據(jù)庫(kù)的執(zhí)行性能,為此在查詢的時(shí)候還是要盡量避免在查詢條件語(yǔ)句中包含單引號(hào)。數(shù)據(jù)管理員在設(shè)計(jì)SQL查詢語(yǔ)句中,應(yīng)該有意識(shí)的限制這種行為,而不是支持。只有在用戶確實(shí)有這方面需求的情況下,才能夠使用轉(zhuǎn)移字符來(lái)告訴數(shù)據(jù)庫(kù)把單引號(hào)當(dāng)作字符數(shù)據(jù)來(lái)處理。
建議二:數(shù)值作為查詢條件的注意事項(xiàng)。
如果把數(shù)值作為查詢條件時(shí),其不用單引號(hào)括起來(lái),在數(shù)字中間也不會(huì)出現(xiàn)單引號(hào)等分隔符。那么照理來(lái)說(shuō)數(shù)值作為查詢參數(shù)是最容易的事情了。其實(shí)不然。很多數(shù)據(jù)庫(kù)管理員可能不熟悉一些基本的規(guī)則,為此在使用數(shù)值作為查詢條件的時(shí)候,還是會(huì)遇到磕磕碰碰的事情。
如把數(shù)值作為查詢條件的話,則在數(shù)值中可以加入小數(shù)點(diǎn)。默認(rèn)情況下,小數(shù)點(diǎn)位一個(gè)小黑點(diǎn),如12.5。但是并不是在所有操作系統(tǒng)中都是以這個(gè)點(diǎn)好作為小數(shù)點(diǎn)的分隔點(diǎn)。如筆者一次在給客戶進(jìn)行數(shù)據(jù)庫(kù)維護(hù)時(shí),在客戶的電腦上使用sql語(yǔ)句來(lái)查詢記錄,就是把參數(shù)值輸入為12.5。但是怎么執(zhí)行數(shù)據(jù)庫(kù)都提示這條SQL語(yǔ)句有錯(cuò)誤。筆者核對(duì)了好幾次,就是發(fā)現(xiàn)這個(gè)問(wèn)題。但是在筆者自己的筆記本電腦上,把這條SQL語(yǔ)句一模一樣的照寫(xiě)了一遍,執(zhí)行起來(lái)的時(shí)候就沒(méi)有發(fā)生任何錯(cuò)誤。這到底是怎么回事呢?原來(lái)小數(shù)點(diǎn)的分隔符默認(rèn)情況下是采用小黑點(diǎn),但是并不是所有操作系統(tǒng)這支持這個(gè)。小數(shù)點(diǎn)的分隔符用戶可以進(jìn)行自定義。如在Windows操作系統(tǒng)控制面便的區(qū)域設(shè)置中,可以根據(jù)用戶的使用習(xí)慣來(lái)定義小數(shù)點(diǎn)的分隔符。當(dāng)在書(shū)寫(xiě)查詢條件的過(guò)程中如果使用到小數(shù)點(diǎn)的話,那么就需要跟這個(gè)區(qū)域設(shè)置中的設(shè)置相符。如果在這個(gè)區(qū)域設(shè)置中是采用冒號(hào)來(lái)作為小數(shù)的分隔符號(hào)的,那么在查詢語(yǔ)句中也需要利用冒號(hào)來(lái)作為小數(shù)點(diǎn)的分隔符。在數(shù)據(jù)庫(kù)編譯的時(shí)候,會(huì)自動(dòng)把這個(gè)冒號(hào)轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)。為此,在有些教科書(shū)上,把小數(shù)點(diǎn)的分隔符好定義為小黑點(diǎn)筆者人為這是不科學(xué)的,會(huì)對(duì)讀者產(chǎn)生誤導(dǎo)。筆者認(rèn)為,應(yīng)該這么寫(xiě):如果把數(shù)值作為查詢條件的,則除了小數(shù)點(diǎn)分隔符和負(fù)號(hào)之外,不能夠包含非數(shù)字字符。如果為了讓讀者更加明白的話,則在后面可以加一句注釋,這里的小數(shù)點(diǎn)分隔符默認(rèn)情況下是小黑點(diǎn)符號(hào),但是可以在控制面中中的區(qū)域設(shè)置對(duì)方框內(nèi)進(jìn)行重新定義。
另外在使用數(shù)值型數(shù)據(jù)作為查詢條件時(shí),需要注意如果輸入的是正數(shù),那么無(wú)論搜索的是整數(shù)還是實(shí)數(shù),都可以包含小數(shù)點(diǎn)標(biāo)記。也就是說(shuō),12.與12是等價(jià)的(這里假設(shè)小數(shù)點(diǎn)分隔符為.號(hào))。而且在SQLServer數(shù)據(jù)庫(kù)中,還可以利用科學(xué)計(jì)數(shù)法來(lái)作為查詢條件。要知道利用科學(xué)計(jì)數(shù)法來(lái)表示非常大或者非常小的數(shù)字,非常有用。數(shù)據(jù)庫(kù)能夠支持科學(xué)計(jì)數(shù)法作為查詢條件,則對(duì)于一些小數(shù)或者大數(shù)的查詢非常的有用。
建議三:要注意邏輯值的表示方法。
在SQLServer數(shù)據(jù)庫(kù)中,邏輯值的應(yīng)用也是很普遍的。如在員工信息表中,往往把員工的性別利用邏輯值來(lái)表示。如員工如果是男性的話,則利用True來(lái)表示。如果員工是女性的話,則利用false來(lái)表示。再如如果某個(gè)員工離職了,為了后續(xù)查詢往往不會(huì)把這個(gè)員工信息刪除,而是采用另外一種管理機(jī)制來(lái)進(jìn)行管理。如會(huì)在這個(gè)員工信息表中創(chuàng)建一個(gè)isactive等類似的布爾型字段。如果這個(gè)員工信息是有效的,則其值就為T(mén)rue;如果這個(gè)員工信息因?yàn)殡x職等原因已經(jīng)實(shí)現(xiàn)了,則其就為Faluse。
但是數(shù)據(jù)庫(kù)管理需要注意這個(gè)邏輯數(shù)據(jù)的格式會(huì)因數(shù)據(jù)庫(kù)的不同而不同。如在SQLServer中,如果邏輯值為False的話,則在數(shù)據(jù)庫(kù)存儲(chǔ)為0;如果邏輯值為T(mén)rue的話,則其通常存儲(chǔ)的值為1。不過(guò)不同的數(shù)據(jù)庫(kù)這個(gè)對(duì)應(yīng)的值可能不同,如有的數(shù)據(jù)庫(kù)利用-1來(lái)表示邏輯值False等等。為此在編寫(xiě)SQL語(yǔ)句的時(shí)候,數(shù)據(jù)庫(kù)管理員需要注意這方面的差異,要防止張冠李戴的情況發(fā)生。
另外需要注意的是,在開(kāi)發(fā)應(yīng)用程序的時(shí)候,其往往不會(huì)利用數(shù)字0或者1來(lái)表示羅機(jī)值。如在C語(yǔ)言中直接以TRUE或者FALSE來(lái)表示布爾值。為此數(shù)據(jù)庫(kù)開(kāi)發(fā)人員在開(kāi)發(fā)應(yīng)用系統(tǒng)的時(shí)候,需要注意這些表示方式上的差異。在必要的時(shí)候,需要通過(guò)別名等表達(dá)方式來(lái)進(jìn)行相關(guān)的轉(zhuǎn)換。如用戶在生成報(bào)表時(shí),如果利用1或者0數(shù)字來(lái)表示邏輯值的話,可能用戶并不一定看的懂。此時(shí)就需要在數(shù)據(jù)庫(kù)查詢的時(shí)候,進(jìn)行一些轉(zhuǎn)換處理。如可以利用CASE語(yǔ)句來(lái)判斷并利用別名進(jìn)行轉(zhuǎn)換。這也是數(shù)據(jù)庫(kù)設(shè)計(jì)過(guò)程中對(duì)邏輯值進(jìn)行處理的最常見(jiàn)的方法。
建議四:當(dāng)心日期數(shù)據(jù)的處理。
日期型的數(shù)據(jù)在數(shù)據(jù)庫(kù)中使最特殊也是最復(fù)雜的一類數(shù)據(jù)類型。其看起來(lái)像是字符型的數(shù)據(jù),但是其操作起來(lái)要比數(shù)據(jù)型的字符負(fù)責(zé)的多。要掌握在WHERE語(yǔ)句中如果利用日期型的數(shù)據(jù)作為查詢條件,則數(shù)據(jù)庫(kù)管理員首先需要明白其日期的表示格式。因?yàn)椴煌愋偷谋硎靖袷狡渌淼暮x是不同的。
首先數(shù)據(jù)庫(kù)管理員需要注意,在SQLServer與Windows操作系統(tǒng)的環(huán)境下,其日期格式可以在多個(gè)地方進(jìn)行設(shè)置。如區(qū)域設(shè)置特定、數(shù)據(jù)庫(kù)特定、ANSI標(biāo)準(zhǔn)等三個(gè)方面。在數(shù)據(jù)庫(kù)部署的時(shí)候,最好把這三個(gè)地方的日期格式設(shè)置為一致,否則的話,在后續(xù)操作的時(shí)候會(huì)遇到很多不必要的麻煩。如區(qū)域設(shè)置處設(shè)置的日期格式與數(shù)據(jù)庫(kù)特定的日期格式不一致的話,則在利用日期型數(shù)據(jù)進(jìn)行查詢的時(shí)候,很容易因?yàn)槿掌诟袷讲患嫒荻鴮?dǎo)致語(yǔ)法編譯錯(cuò)誤。
其次需要注意的是,在SQL Server數(shù)據(jù)庫(kù)中有兩個(gè)地方可以生成SQL語(yǔ)句。一是在數(shù)據(jù)提供的窗口中生成SQL語(yǔ)句;二是直接編寫(xiě)SQL語(yǔ)句。如果在其提供的查詢窗口中生成SQL語(yǔ)句的話,則在日期型的字段中輸入日期數(shù)據(jù)的話,則數(shù)據(jù)庫(kù)在生成SQL查詢語(yǔ)句的過(guò)程中,會(huì)自動(dòng)對(duì)日期型的數(shù)據(jù)進(jìn)行轉(zhuǎn)換,以符合于數(shù)據(jù)庫(kù)兼容的日期格式。也就是說(shuō),在查詢窗口輸入日期型數(shù)據(jù)查詢條件,一般不會(huì)出現(xiàn)問(wèn)題。但是如果是在應(yīng)用程序中直接編寫(xiě)SQL語(yǔ)句,則此時(shí)需要注意,其輸入的日期要符合數(shù)據(jù)庫(kù)特定的格式或者ANSI標(biāo)準(zhǔn)的格式。而不是在區(qū)域設(shè)置處設(shè)定的格式。
第三,那么查詢返回的結(jié)果會(huì)以什么格式顯示呢?是按照區(qū)域設(shè)置特定的格式、還是數(shù)據(jù)庫(kù)特定的格式或者ANSI標(biāo)準(zhǔn)日期格式顯示呢?這里要注意,其顯示的時(shí)候是以操作系統(tǒng)中區(qū)域設(shè)置處設(shè)置的日期格式來(lái)顯示。而不是數(shù)據(jù)庫(kù)中設(shè)置的日期格式來(lái)顯示。為此在同一個(gè)數(shù)據(jù)庫(kù)中,不同的客戶端其日期顯示格式就有可能不同。這主要是因?yàn)榭蛻舳松厦娴膮^(qū)域設(shè)置中的日期格式設(shè)置不同而造成的。