6.6 處理查詢
我們已經(jīng)知道了如何開(kāi)始和結(jié)束與服務(wù)器的會(huì)話,現(xiàn)在應(yīng)該看看如何控制會(huì)話,
Mysql入門系列:如何處理MYSQL查詢MySQL綜合
。本節(jié)介紹了如何與服務(wù)器通信以處理查詢。執(zhí)行的每個(gè)查詢應(yīng)包括以下幾步:1) 構(gòu)造查詢。查詢的構(gòu)造取決于查詢的內(nèi)容—特別要看是否含有二進(jìn)制數(shù)據(jù)。
2) 通過(guò)將查詢發(fā)送到服務(wù)器執(zhí)行來(lái)發(fā)布查詢。
3) 處理查詢結(jié)果。這取決于發(fā)布查詢的類型。例如, SELECT 語(yǔ)句返回?cái)?shù)據(jù)行等待處理,INSERT 語(yǔ)句就不這樣。構(gòu)造查詢的一個(gè)要素就是使用哪個(gè)函數(shù)將查詢發(fā)送到服務(wù)器。較通用的發(fā)布查詢例程是mysql_ real _ query ( )。該例程給查詢提供了一個(gè)計(jì)數(shù)串(字符串加上長(zhǎng)度)。必須了解查詢串的長(zhǎng)度,并將它們連同串本身一起傳遞給mysql_real_query() 。因?yàn)椴樵兪且粋(gè)計(jì)數(shù)的字符串,
所以它的內(nèi)容可能是任何東西,其中包括二進(jìn)制數(shù)據(jù)或者空字節(jié)。查詢不能是空終結(jié)串。另一個(gè)發(fā)布查詢的函數(shù), mysql_ query ( ),在查詢字符串允許的內(nèi)容上有更多的限制,但更容易使用一些。傳遞到mysql_query() 的查詢應(yīng)該是空終結(jié)串,這說(shuō)明查詢內(nèi)部不能含有空字節(jié)(查詢里含有空字節(jié)會(huì)導(dǎo)致錯(cuò)誤地中斷,這比實(shí)際的查詢內(nèi)容要短)。一般說(shuō)來(lái),如果查詢包含任意的二進(jìn)制數(shù)據(jù),就可能包含空字節(jié),因此不要使用mysql_ query( )。另一方面,當(dāng)處理空終結(jié)串時(shí),使用熟悉的標(biāo)準(zhǔn)C 庫(kù)字符串函數(shù)構(gòu)造查詢是很耗費(fèi)資源的,例如strcpy ( )和sprintf( )。
構(gòu)造查詢的另一個(gè)要素就是是否要執(zhí)行溢出字符的操作。如果在構(gòu)造查詢時(shí)使用含有二
進(jìn)制數(shù)據(jù)或者其他復(fù)雜字符的值時(shí),如引號(hào)、反斜線等,就需要使用這個(gè)操作。這些將在
6.8.2節(jié)“對(duì)查詢中有疑問(wèn)的數(shù)據(jù)進(jìn)行編碼”中討論。
下面是處理查詢的簡(jiǎn)單輪廓:
mysql_query() 和mysql_real_query() 的查詢成功都會(huì)返回零值,查詢失敗返回非零值。查詢成功指服務(wù)器認(rèn)為該查詢有效并接受,而且能夠執(zhí)行,并不是指有關(guān)該查詢結(jié)果。例如,它不是指SELECT 查詢所選擇的行,或DELETE 語(yǔ)句所刪除的行。檢查查詢的實(shí)際結(jié)果要包括其他的處理。
查詢失敗可能有多種原因,有一些常見(jiàn)的原因如下:
■ 含有語(yǔ)法錯(cuò)誤。
■ 語(yǔ)義上是非法的—例如涉及對(duì)表中不存在的列的查詢。
■ 沒(méi)有足夠的權(quán)利訪問(wèn)查詢所引用的數(shù)據(jù)。
查詢可以分成兩大類:不返回結(jié)果的查詢和返回結(jié)果的查詢。INSERT、DELETE和UPDATE等語(yǔ)句屬于“不返回結(jié)果”類的查詢,即使對(duì)修改數(shù)據(jù)庫(kù)的查詢,它們也不返回任何行?煞祷氐奈ㄒ恍畔⒕褪怯嘘P(guān)受作用的行數(shù)。SELECT 語(yǔ)句和SHOW 語(yǔ)句屬于“返回結(jié)果”類的查詢;發(fā)布這些語(yǔ)句的目的就是要返回某些信息。返回?cái)?shù)據(jù)的查詢所生成的行集合稱為結(jié)果集,在MySQL中表示為MYSQL_RES 數(shù)據(jù)類型,這是一個(gè)包含行的數(shù)據(jù)值及有關(guān)這些值的元數(shù)據(jù)(如列名和數(shù)據(jù)值的長(zhǎng)度)的結(jié)構(gòu)?盏慕Y(jié)果集(就是包含零行的結(jié)果)要與“沒(méi)有結(jié)果”區(qū)分開(kāi)。
6.6.1處理不返回結(jié)果集的查詢
處理不返回結(jié)果集的查詢,用mysql_query() 或mysql_real_query() 發(fā)布查詢。如果查詢成功,可以通過(guò)調(diào)用mysql_ a ffected_rows() 找出有多少行需要插入、刪除或修改。下面的樣例說(shuō)明如何處理不返回結(jié)果集的查詢:
請(qǐng)注意在打印時(shí)mysql
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程
_ a ffected_rows() 的結(jié)果是如何轉(zhuǎn)換為unsigned long 類型的,這個(gè)函數(shù)返回一個(gè)my_ulonglong 類型的值,但在一些系統(tǒng)上無(wú)法直接打印這個(gè)類型的值(例如,筆者觀察到它可在FreeBSD 下工作,但不能在Solaris 下工作)。把值轉(zhuǎn)換為unsigned long 類型并使用‘% l u’打印格式可以解決這個(gè)問(wèn)題。同樣也要考慮返回my_ulonglong 值的其他函數(shù),如mysql_num_rows() 和mysql_ insert _ id ( )。如果想使客戶機(jī)程序能跨系統(tǒng)地移植,就要謹(jǐn)記這一點(diǎn)。
mysql_ rows _ affected() 返回查詢所作用的行數(shù),但是“受作用的行”的含義取決于查詢的類型。對(duì)于INSERT、DELETE 和UPDATE,是指插入、刪除或者更新的行數(shù),也就是MySQL實(shí)際修改的行數(shù)。如果行的內(nèi)容與所要更新的內(nèi)容相同,則MySQL就不再更新行。這就是說(shuō)雖然可能選擇行來(lái)更新(通過(guò)UPDATE 語(yǔ)句的WHERE 子句),但實(shí)際上該行可能并未改變。
對(duì)于UPDATE,“受作用的行”的意義實(shí)際上是個(gè)爭(zhēng)論點(diǎn),因?yàn)槿藗兿氚阉?dāng)成“被匹配的行”—即選擇要更新的行數(shù),即使更新操作實(shí)際上并未改變其中的值也是如此。如果應(yīng)用程序需要這個(gè)信息, 則當(dāng)與服務(wù)器連接時(shí)可以用它來(lái)請(qǐng)求以實(shí)現(xiàn)這個(gè)功能。將CLIENT_FOUND_ROWS 的flags 值傳遞給mysql_ real _ connect( )。也可以將CLIENT _ FOUND _ROWS 作為flags 參數(shù)傳遞給do _ connect ( );它將把值傳遞給mysql_ real _ connect( )。
6.6.2 處理返回結(jié)果集的查詢
通過(guò)調(diào)用mysql_query() 和mysql_real_query() 發(fā)布查詢之后,返回?cái)?shù)據(jù)的查詢以結(jié)果集形式進(jìn)行。在MySQL中實(shí)現(xiàn)它非常重要, SELECT 不是返回行的唯一語(yǔ)句, SHOW、DESCRIBE 和EXPLAIN 都需要返回行。對(duì)所有這些語(yǔ)句,都必須在發(fā)布查詢后執(zhí)行另外的處理行操作。
處理結(jié)果集包括下面幾個(gè)步驟:
■ 通過(guò)調(diào)用mysql_store_result() 或mysql_use_result() 產(chǎn)生結(jié)果集。這些函數(shù)如果成功則返回MYSQL_RES 指針,失敗則返回N U LL。稍后我們將查看mysql_store_result() 與mysql_use_result() 的不同,以及選擇其中一個(gè)而不選另一個(gè)時(shí)的情況。我們的樣例使
用mysql_ store _ result( ),它能立即從服務(wù)器返回行,并將它們存儲(chǔ)到客戶機(jī)中。
■ 對(duì)結(jié)果集的每一行調(diào)用mysql_ fetch _ rows ( )。這個(gè)函數(shù)返回MYSQL_ROW 值,它是一個(gè)指向字符串?dāng)?shù)組的指針,字符串?dāng)?shù)組表示行中每列的值。要根據(jù)應(yīng)用程序?qū)π羞M(jìn)行操作?梢灾淮蛴〕隽兄担瑘(zhí)行有關(guān)的統(tǒng)計(jì)計(jì)算,或者做些其他操作。當(dāng)結(jié)果集中不再有行時(shí), mysql_fetch_rows() 返回NULL。
■ 處理結(jié)果集時(shí),調(diào)用mysql_free_result() 釋放所使用的內(nèi)存。如果忽略了這一點(diǎn),則應(yīng)用程序就會(huì)泄露出內(nèi)存(對(duì)于長(zhǎng)期運(yùn)行的應(yīng)用程序,適當(dāng)?shù)亟鉀Q結(jié)果集是極其重要的;否則,會(huì)注意到系統(tǒng)將由一些過(guò)程所取代,這些過(guò)程消耗著經(jīng)常增長(zhǎng)的系統(tǒng)資源量)。
下面的樣例輪廓介紹了如何處理返回結(jié)果集的查詢:
我們通過(guò)調(diào)用函數(shù)process_result_set() 來(lái)處理每一行,這里有個(gè)竅門,因?yàn)槲覀儾](méi)有定義這個(gè)函數(shù),所以需要這樣做。通常,結(jié)果的處理集函數(shù)是基于下面的循環(huán):
從mysql_fetch_row() 返回的MYSQL_ROW 值是一個(gè)指向數(shù)值數(shù)組的指針,因此,訪問(wèn)每個(gè)值就是訪問(wèn)row[i],這里i 的范圍是從0到該行的列數(shù)減1。這里有幾
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程
個(gè)關(guān)于MYSQL_ROW 數(shù)據(jù)類型的要點(diǎn)需要注意:
■ MYSQL_ROW 是一個(gè)指針類型,因此,必須聲明類型變量為MYSQL_ROW row,而不是MYSQL_ROW *row。
■ MYSQL_ROW 數(shù)組中的字符串是空終結(jié)的。但是,列可能含有二進(jìn)制數(shù)據(jù),這樣,數(shù)據(jù)中就可能含有空字節(jié),因此,不應(yīng)該把值看成是空終結(jié)的。由列的長(zhǎng)度可知列值有多長(zhǎng)。
■ 所有數(shù)據(jù)類型的值都是作為字符串返回的,即使是數(shù)字型的也是如此。如果需要該值為數(shù)字型,就必須自己對(duì)該字符串進(jìn)行轉(zhuǎn)換。
■ 在MYSQL_ROW 數(shù)組中,NULL 指針代表NULL,除非聲明列為NOT NULL,否則應(yīng)該經(jīng)常檢查列值是否為NULL 指針。
應(yīng)用程序可以利用每行的內(nèi)容做任何想做的事,為了舉例說(shuō)明這一點(diǎn),我們只打印由制表符隔開(kāi)列值的行,為此還需要另外一個(gè)函數(shù), mysql_num_fields() ,它來(lái)自于客戶機(jī)庫(kù);這個(gè)函數(shù)告知我們?cè)撔邪ǘ嗌賯(gè)值(列)。
下面就是process_result_set() 的代碼:
process_result_set() 以制表符分隔的形式打印每一行(將NULL值顯示為單詞“NULL”),它跟在被檢索的行計(jì)數(shù)的后面, 該計(jì)數(shù)通過(guò)調(diào)用mysql_num_rows() 來(lái)計(jì)算。像mysql_ affected_rows() 一樣,mysql_num_rows() 返回my_ulonglong 值,因此,將值轉(zhuǎn)換為
unsigned long 型,并用‘% l u’ 格式打印。
提取行的循環(huán)緊接在一個(gè)錯(cuò)誤檢驗(yàn)的后面,如果要用mysql_store_result() 創(chuàng)建結(jié)果集,
mysql_fetch_row() 返回的NULL值通常意味著“不再有行”。然而,如果用mysql_ use _ result( )創(chuàng)建結(jié)果集,則mysql_fetch_row() 返回的NULL 值通常意味著“不再有行”或者發(fā)生了錯(cuò)誤。無(wú)論怎樣創(chuàng)建結(jié)果集,這個(gè)測(cè)試只允許process_result_set() 檢測(cè)錯(cuò)誤。
process_result_set() 的這個(gè)版本是打印列值要求條件最低的方法,每種方法都有一定的缺點(diǎn),例如假設(shè)執(zhí)行下面的查詢:
我們可以通過(guò)提供一些信息如列標(biāo)簽,及通過(guò)使這些值垂直排列,而使輸出結(jié)果漂亮一點(diǎn)。為此,我們需要標(biāo)簽和每列所需的最寬的值。這個(gè)信息是有效的,但不是列數(shù)據(jù)值的一部分,而是結(jié)果集的元數(shù)據(jù)的一部分(有關(guān)數(shù)據(jù)的數(shù)據(jù))。簡(jiǎn)單歸納了一下查詢處理程序后,我們將在6 . 6 . 6節(jié)“使用結(jié)果集元數(shù)據(jù)”中給出較漂亮的顯示格式。
打印二進(jìn)制數(shù)據(jù)
對(duì)包含可能含有空字節(jié)的二進(jìn)制數(shù)據(jù)的列值,使用‘ % s’printf() 格式標(biāo)識(shí)符不能將它正確地打。 printf() 希望一個(gè)空終結(jié)串,并且直到第一個(gè)空字節(jié)才打印列值。對(duì)于二進(jìn)制數(shù)據(jù),最好用列的長(zhǎng)度,以便打印完整的值,如可以用fwrite() 或putc( )。
6.6.3 通用目標(biāo)查詢處理程序
前面介紹的處理查詢樣例應(yīng)用了語(yǔ)句是否應(yīng)該返回一些數(shù)據(jù)的知識(shí)來(lái)編寫的。這是可能的,因?yàn)椴樵児潭ㄔ诖a內(nèi)部:使用INSERT 語(yǔ)句時(shí),它不返回結(jié)果,使用SHOW TABLES語(yǔ)句時(shí),才返回結(jié)果。
然而,不可能始終知道查詢用的是哪一種語(yǔ)句,例如,如果執(zhí)行一個(gè)從鍵盤鍵入或來(lái)源于文件的查詢,則它可能是任何的語(yǔ)句。不可能提前知道它是否會(huì)返回行。當(dāng)然不想對(duì)查詢做語(yǔ)法分析來(lái)決定它是哪類語(yǔ)
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程
句,總之,并不像看上去那樣簡(jiǎn)單。只看第一個(gè)單詞是不夠的,因?yàn)椴樵円部赡芤宰⑨屨Z(yǔ)句開(kāi)始,例如:
/* comment * / SELECT
幸運(yùn)的是不必過(guò)早地知道查詢類型就能夠正確地處理它。用MySQLC API 可編寫一個(gè)能很好地處理任何類型語(yǔ)句的通用目標(biāo)查詢處理程序,無(wú)論它是否會(huì)返回結(jié)果。在編寫查詢處理程序的代碼之前,讓我們簡(jiǎn)述一下它是如何工作的:
■ 發(fā)布查詢,如果失敗,則結(jié)束。
■ 如果查詢成功,調(diào)用mysql_store_result() 從服務(wù)器檢索行,并創(chuàng)建結(jié)果集。
■ 如果mysql_store_result() 失敗,則查詢不返回結(jié)果集,或者在檢索這個(gè)結(jié)果集時(shí)發(fā)生錯(cuò)誤?梢酝ㄟ^(guò)把連接處理程序傳遞到mysql_field_count() 中,并檢測(cè)其值來(lái)區(qū)別這兩種情況,如下:
■ 如果mysql_field_count() 非零,說(shuō)明有錯(cuò)誤,因?yàn)椴樵儜?yīng)該返回結(jié)果集,但卻沒(méi)有。這種情況發(fā)生有多種原因。例如:結(jié)果集可能太大,內(nèi)存分配失敗,或者在提取行時(shí)客戶機(jī)和服務(wù)器之間發(fā)生網(wǎng)絡(luò)中斷。
這種過(guò)程稍微有點(diǎn)復(fù)雜之處就在于, MySQL3.22.24 之前的早期版本中不存在mysql_ field _ count( ),它們使用的是mysql_ num _ fields ( )。為編寫MySQL任何版本都能運(yùn)行的程序,在調(diào)用mysql_field_count() 的文件中都包含下面的代碼塊:
這就將對(duì)mysql_field_count() 的一些調(diào)用看作是比MySQL3.22.24 更早版本中的mysql_num_fields() 的調(diào)用。
■ 如果mysql_field_count() 返回0,就意味著查詢不返回結(jié)果(這說(shuō)明查詢是類似于INSERT、DELETE、或UPDATE 的語(yǔ)句)。
■ 如果mysql_store_result() 成功,查詢返回一個(gè)結(jié)果集,通過(guò)調(diào)用mysql_fetch_row() 來(lái)處理行,直到它返回NULL 為止。
下面的列表說(shuō)明了處理任意查詢的函數(shù),給出了連接處理程序和空終結(jié)查詢字符串:
6.6.4 可選擇的查詢處理方法
process_query() 的這個(gè)版本有三個(gè)特性:
■ 用mysql_query() 發(fā)布查詢,
電腦資料
《Mysql入門系列:如何處理MYSQL查詢MySQL綜合》(http://www.lotusphilosophies.com)。■ 用mysql_store_query() 檢索結(jié)果集。
■ 沒(méi)有得到結(jié)果集時(shí),用mysql_field_count() 把錯(cuò)誤事件和不需要的結(jié)果集區(qū)別開(kāi)來(lái)。針對(duì)查詢處理的這些特點(diǎn),有如下三種方法:
■ 可以用計(jì)數(shù)查詢字符串和mysql_ real _ query( ),而不使用空終結(jié)查詢字符串和mysql_ query( )。
■ 可以通過(guò)調(diào)用mysql_use_result() 而不是調(diào)用mysql_store_result() 來(lái)創(chuàng)建結(jié)果集。
■ 可以調(diào)用mysql_error() 而不是調(diào)用mysql_field_count() 來(lái)確定結(jié)果集是檢索失敗還是僅僅沒(méi)有設(shè)置檢索。
可用以上部分或全部方法代替process _ query( )。以下是一個(gè)process_real_query() 函數(shù),它與process_query() 類似,但使用了所有三種方法:
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程
6.6.5 mysql_store_result() 與mysql_use_result() 的比較
函數(shù)mysql_store_result() 與mysql_use_result() 類似,它們都有連接處理程序參數(shù),并返回結(jié)果集。但實(shí)際上兩者間的區(qū)別還是很大的。兩個(gè)函數(shù)之間首要的區(qū)別在于從服務(wù)器上檢索結(jié)果集的行。當(dāng)調(diào)用時(shí), mysql_store_result() 立即檢索所有的行,而mysql_use_result() 啟動(dòng)查詢,但實(shí)際上并未獲取任何行, mysql_store_result() 假設(shè)隨后會(huì)調(diào)用mysql_ fetch _ row( )檢索記錄。這些行檢索的不同方法引起兩者在其他方面的不同。本節(jié)加以比較,以便了解如何選擇最適合應(yīng)用程序的方法。
當(dāng)mysql_store_result() 從服務(wù)器上檢索結(jié)果集時(shí),就提取了行,并為之分配內(nèi)存,存儲(chǔ)到客戶機(jī)中,隨后調(diào)用mysql_fetch_row() 就再也不會(huì)返回錯(cuò)誤,因?yàn)樗鼉H僅是把行脫離了已經(jīng)保留結(jié)果集的數(shù)據(jù)結(jié)構(gòu)。mysql_fetch_row() 返回NULL 始終表示已經(jīng)到達(dá)結(jié)果集的末端。相反,mysql_use_result() 本身不檢索任何行,而只是啟動(dòng)一個(gè)逐行的檢索,就是說(shuō)必須對(duì)每行調(diào)用mysql_fetch_row() 來(lái)自己完成。既然如此,雖然正常情況下, mysql_ fetch _ row( )返回NULL 仍然表示此時(shí)已到達(dá)結(jié)果集的末端,但也可能表示在與服務(wù)器通信時(shí)發(fā)生錯(cuò)誤?赏ㄟ^(guò)調(diào)用mysql_errno() 和mysql_error() 將兩者區(qū)分開(kāi)來(lái)。
與mysql_use_result() 相比,mysql_store_result() 有著較高的內(nèi)存和處理需求,因?yàn)槭窃诳蛻魴C(jī)上維護(hù)整個(gè)結(jié)果集,所以內(nèi)存分配和創(chuàng)建數(shù)據(jù)結(jié)構(gòu)的耗費(fèi)是非常巨大的,要冒著溢出內(nèi)存的危險(xiǎn)來(lái)檢索大型結(jié)果集,如果想一次檢索多個(gè)行,可用mysql_ use _result( )。mysql_use_result() 有著較低的內(nèi)存需求,因?yàn)橹恍杞o每次處理的單行分配足夠的空間。這樣速度就較快,因?yàn)椴槐貫榻Y(jié)果集建立復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。另一方面, mysql_use_result() 把較大的負(fù)載加到了服務(wù)器上,它必須保留結(jié)果集中的行,直到客戶機(jī)看起來(lái)適合檢索所有的行。這就使某些類型的客戶機(jī)程序不適用mysql_ use _ result( ):
■ 在用戶的請(qǐng)求下提前逐行進(jìn)行的交互式客戶機(jī)程序(不必僅僅因?yàn)橛脩粜枰缺Х榷尫⻊?wù)器等待發(fā)送下一行)。
■ 在行檢索之間做了許多處理的客戶機(jī)程序。在所有這些情況下,客戶機(jī)程序都不能很快檢索結(jié)果集的所有行,它限制了服務(wù)器,并對(duì)其他客戶機(jī)程序產(chǎn)生負(fù)面的影響,因?yàn)闄z索數(shù)據(jù)的表在查詢過(guò)程中是讀鎖定的。要更新表的客戶機(jī)或要插入行的任何客戶機(jī)程序都被阻塞。
偏移由mysql_store_result() 引起的額外內(nèi)存需求對(duì)一次訪問(wèn)整個(gè)結(jié)果集帶來(lái)相當(dāng)?shù)暮锰。結(jié)果集中的所有行都是有效的,因此,可以任意訪問(wèn): mysql_ data _ seek( )、mysql_ rowseek( )和mysql_row_tell() 函數(shù)允許以任意次序訪問(wèn)行。而mysql_use_result() 只能以mysql_fetch_row() 檢索的順序訪問(wèn)行。如果想要以任意次序而不是從服務(wù)器返回的次序來(lái)處理行,就必須使用mysql_ store _ result( )。例如,如果允許用戶來(lái)回地瀏覽查詢所選的行,最好使用mysql_ store _ result( )。
使用mysql_store_result() 可以獲得在使用mysql_use_result() 時(shí)是無(wú)效的某些類型的列信息。通過(guò)調(diào)用mysql_num_rows() 來(lái)獲得結(jié)果集的行數(shù),每列中的這些值的最大寬度值存儲(chǔ)在MYSQL_FIELD 列信息結(jié)構(gòu)的max_width 成員中。使用mysql_ use _ result( ),直到提取完所有的行,mysql_num_rows() 才會(huì)返回正確值,而且max_wi
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程
dth 無(wú)效,因?yàn)橹挥性诿啃械臄?shù)據(jù)都顯示后才能計(jì)算。
由于mysql_use_result() 比mysql_store_result() 執(zhí)行更少的操作,所以mysql_ use _ result( )就強(qiáng)加了一個(gè)mysql_store_result() 沒(méi)有的需求:即客戶機(jī)對(duì)結(jié)果集中的每一行都必須調(diào)用mysql_ fetch _ row( ),否則,結(jié)果集中剩余的記錄就會(huì)成為下一個(gè)查詢結(jié)果集中的一部分,并且發(fā)生“不同步”的錯(cuò)誤。這種情形在使用mysql_store_result() 時(shí)不會(huì)發(fā)生,因?yàn)楫?dāng)函數(shù)返
回時(shí),所有的行就已被獲取。事實(shí)上,使用mysql_store_result() 就不必再自己調(diào)用mysql_ fetch _ row( )。對(duì)于所有感興趣的事情就是是否得到一個(gè)非空的結(jié)果,而不是結(jié)果所包含的內(nèi)容的查詢來(lái)說(shuō),它是很有用的。例如,要知道表my_tbl 是否存在,可以執(zhí)行下面的查詢:
SHOW TABLES LIKE "my_tb1"
如果在調(diào)用mysql_store_result() 之后,mysql_num_rows() 的值為非零,這個(gè)表就存在,就不必再調(diào)用mysql_fetch_row() (當(dāng)然仍需調(diào)用mysql_ free _ result( ))。如果要提供最大的靈活性,就給用戶選擇使用任一結(jié)果集處理方法的選項(xiàng)。mysql和mysqldump 是執(zhí)行這個(gè)操作的兩個(gè)程序,缺省時(shí),使用mysql_ store _ result( ),但是如果指定--quick 選項(xiàng),則使用mysql_ use _ result( )。
6.6.6 使用結(jié)果集元數(shù)據(jù)
結(jié)果集不僅包括數(shù)據(jù)行的列值,而且還包括數(shù)據(jù)信息,這些信息成為元數(shù)據(jù)結(jié)果集,包括:
■ 結(jié)果集中的行數(shù)和列數(shù),通過(guò)調(diào)用mysql_num_rows() 和mysql_num_fields() 實(shí)現(xiàn)。
■ 行中每列值的長(zhǎng)度,通過(guò)調(diào)用mysql_fetch_lengths() 實(shí)現(xiàn)。
■ 有關(guān)每列的信息, 例如列名和類型、每列值的最大寬度和列來(lái)源的表等。
MYSQL_FIELD 結(jié)構(gòu)存儲(chǔ)這些信息,通過(guò)調(diào)用mysql_fetch_fields() 來(lái)獲得它。附錄F詳細(xì)地描述了MYSQL_FIELD 結(jié)構(gòu),并列出了提供訪問(wèn)列信息的所有函數(shù)。元數(shù)據(jù)的有效性部分決定于結(jié)果集的處理方法,如在上節(jié)中提到的,如果要使用行計(jì)數(shù)或者列長(zhǎng)度的最大值,就必須用mysql_store_result() 而不是mysql_use_result() 創(chuàng)建結(jié)果集。結(jié)果集元數(shù)據(jù)對(duì)確定有關(guān)如何處理結(jié)果集非常有幫助:
■ 列名和寬度信息對(duì)漂亮地生成帶有列標(biāo)題并垂直排列的格式化輸出是非常有用的。
■ 使用列計(jì)數(shù)來(lái)確定處理數(shù)據(jù)行的連續(xù)列值的循環(huán)所迭代的次數(shù)。如果要分配取決于結(jié)果集中已知的行數(shù)或列數(shù)的數(shù)據(jù)結(jié)構(gòu),就可以使用行或列計(jì)數(shù)。
■ 可以確定列的數(shù)據(jù)類型?梢钥闯隽惺欠袷菙(shù)字的,是否可能包括二進(jìn)制數(shù)據(jù)等等。在前面的6.6.1節(jié)“處理返回結(jié)果集的查詢”中,我們編寫了從結(jié)果集的行中以制表符分隔的形式打印出結(jié)果的process_result_set() 程序。這對(duì)某些目的是很好的(例如要把數(shù)據(jù)輸入到電子制表軟件中),但對(duì)于可視化檢查或打印輸出,就不是一個(gè)漂亮的顯示格式。回憶前面的process_result_set() 版本,產(chǎn)生過(guò)這樣的輸出:
讓我們?cè)诿苛屑由蠘?biāo)題和邊框來(lái)對(duì)process_result_set() 做些修改,以生成表格式的輸出。這種修正版看上去更美觀,輸出的結(jié)果是相同的,如下所示:
顯示算法的基本要點(diǎn)是這樣的:
1) 確定每列的顯示寬度。
2) 打印一列帶有邊框的列標(biāo)題(由垂直豎線和前后的虛線分隔)。
3) 打
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程
印結(jié)果集每行的值、帶邊框的列(由垂直豎線分隔),并垂直排列,除此之外,打印
正確的數(shù)字,將NULL 值打印為單詞“NULL”。
4) 最后,打印檢索的行的計(jì)數(shù)。該練習(xí)為結(jié)果集元數(shù)據(jù)的使用提供了一個(gè)很好的示范。為了顯示所描述的輸出,除了行所包含的數(shù)據(jù)值之外,我們還需了解許多有關(guān)結(jié)果集的內(nèi)容。您可能想,“這個(gè)描述聽(tīng)起來(lái)與mysql顯示的輸出驚人地相似”。是的,歡迎把mysql源代碼和修正版的process_result_set() 代碼比較一下,它們是不同的,可以發(fā)現(xiàn)對(duì)同一問(wèn)題使用兩種方法是有指導(dǎo)作用的。
首先,我們需要確定每列的顯示寬度,下面列出如何做這件事情。可觀察到這些計(jì)算完全基于結(jié)果集元數(shù)據(jù),無(wú)論行值是什么,它們都沒(méi)有引用:
列寬度通過(guò)結(jié)果集中列的MYSQL_FIELD 結(jié)構(gòu)的迭代來(lái)計(jì)算,調(diào)用mysql_ fetch _ seek( )定位第一個(gè)結(jié)構(gòu),后續(xù)的mysql_fetch_field() 調(diào)用返回指向連續(xù)列的結(jié)構(gòu)的指針。顯示出來(lái)的列寬度是下面三個(gè)值中的最大值,其中每一個(gè)都取決于列信息結(jié)構(gòu)中的元數(shù)據(jù):
■ field - > name的長(zhǎng)度,也就是列標(biāo)題的長(zhǎng)度。
■ field - > max _ length,列中最長(zhǎng)的數(shù)據(jù)值的長(zhǎng)度。
■ 如果列中可能包括NULL值,則為字符串“ NULL”的長(zhǎng)度,field->flag 表明列是否包含NULL。請(qǐng)注意,已知要顯示的列的寬度后,我們將這個(gè)值賦給max _ length,max_length 是從客戶機(jī)庫(kù)獲取的結(jié)構(gòu)中的一個(gè)成員。這種獲取是允許的嗎?或者M(jìn)YSQL_FIELD 結(jié)構(gòu)的內(nèi)容應(yīng)該為只讀?一般來(lái)說(shuō),是“只讀的”,但是MySQL分發(fā)包中的一些客戶機(jī)程序以同樣的方式改變了max_length 的值,因此,假設(shè)這也是正確的(如果更喜歡不改變max_length 值的方法,則分配一個(gè)unsigned int 值的數(shù)組,將計(jì)算的寬度存儲(chǔ)到這個(gè)數(shù)組中)。顯示寬度的計(jì)算包括一個(gè)說(shuō)明,回想當(dāng)使用mysql_use_result() 創(chuàng)建結(jié)果集時(shí),max_length 沒(méi)有意義。因?yàn)槲覀冃枰猰ax_length 來(lái)確定列值的顯示寬度,所以該算法的正確操作需要使用mysql_store_result() 產(chǎn)生的結(jié)果集( MYSQL _ FIELD結(jié)構(gòu)的length 成員告知列值可以取得的最大值,如果使用mysql_store_result() 而不是mysql_ use _ result( )的話,這可能是個(gè)有用的工作環(huán)境)。
一旦知道了列的寬度,就可以準(zhǔn)備打印,處理標(biāo)題很容易;對(duì)于給定的列,只需使用由field 指向的列信息結(jié)構(gòu),用已計(jì)算過(guò)的寬度打印出name 成員。
對(duì)于數(shù)據(jù),我們對(duì)結(jié)果集中的行進(jìn)行循環(huán),在每次迭代時(shí)打印當(dāng)前行的列值。從行中打印列值有些技巧,因?yàn)橹悼赡苁荖ULL,也可能代表一個(gè)數(shù)(無(wú)論哪種情況都如實(shí)打。A兄档拇蛴∪缦拢@里row[i] 包括數(shù)據(jù)值和指向列信息的field 指針:
如果field->type 指明的列類型是數(shù)字型,如INT、FLOAT或者DECIMAL,那么宏IS _ NUM的值為真。顯示該結(jié)果集的最終的代碼如下所示。注意,因?yàn)槲覀冃枰啻未蛴√摼,所以這段代碼封裝在它自己的函數(shù)中,函數(shù)print_dashes() 是這樣的:
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程
MySQL客戶機(jī)庫(kù)提供了訪問(wèn)列信息結(jié)構(gòu)的幾種方法,例如,前面樣例的代碼多次使用如下形式的循環(huán)訪問(wèn)這些結(jié)構(gòu):
然而,mysql_field_seek() 與mysql_fetch_field() 的結(jié)合是獲得MYSQL_FIELD 結(jié)構(gòu)的唯一途徑,可在附錄F 中查看mysql_fetch_field() 函數(shù)和mysql_fetch_field_direct() 函數(shù),尋找其他獲得列信息結(jié)構(gòu)的方法。
查看全套"Mysql入門系列教程">>>>>
關(guān) 鍵 字:MYSQL
相關(guān)文章:
master數(shù)據(jù)庫(kù)中兩個(gè)非常有用的存儲(chǔ)過(guò)程
如何利用存儲(chǔ)過(guò)程和觸發(fā)器來(lái)管理數(shù)據(jù)
輕松應(yīng)對(duì)創(chuàng)建存儲(chǔ)過(guò)程時(shí)出現(xiàn)失敗的情況
深入了解存儲(chǔ)過(guò)程的編寫經(jīng)驗(yàn)和優(yōu)化措施
通過(guò)實(shí)例講解由淺入深學(xué)會(huì)存儲(chǔ)過(guò)程