6.6 處理查詢
我們已經知道了如何開始和結束與服務器的會話,現在應該看看如何控制會話。本節介紹了如何與服務器通信以處理查詢。執行的每個查詢應包括以下幾步:
1) 構造查詢。查詢的構造取決於查詢的內容—特別要看是否含有二進制數據。
2) 通過將查詢發送到服務器執行來發布查詢。
3) 處理查詢結果。這取決於發布查詢的類型。例如, SELECT 語句返回數據行等待處理,INSERT 語句就不這樣。構造查詢的一個要素就是使用哪個函數將查詢發送到服務器。較通用的發布查詢例程是mysql_ real _ query ( )。該例程給查詢提供了一個計數串(字符串加上長度)。必須了解查詢串的長度,並將它們連同串本身一起傳遞給mysql_real_query() 。因為查詢是一個計數的字符串,
所以它的內容可能是任何東西,其中包括二進制數據或者空字節。查詢不能是空終結串。另一個發布查詢的函數, mysql_ query ( ),在查詢字符串允許的內容上有更多的限制,但更容易使用一些。傳遞到mysql_query() 的查詢應該是空終結串,這說明查詢內部不能含有空字節(查詢裡含有空字節會導致錯誤地中斷,這比實際的查詢內容要短)。一般說來,如果查詢包含任意的二進制數據,就可能包含空字節,因此不要使用mysql_ query( )。另一方面,當處理空終結串時,使用熟悉的標准C 庫字符串函數構造查詢是很耗費資源的,例如strcpy ( )和sprintf( )。
構造查詢的另一個要素就是是否要執行溢出字符的操作。如果在構造查詢時使用含有二
進制數據或者其他復雜字符的值時,如引號、反斜線等,就需要使用這個操作。這些將在
6.8.2節“對查詢中有疑問的數據進行編碼”中討論。
下面是處理查詢的簡單輪廓:
mysql_query() 和mysql_real_query() 的查詢成功都會返回零值,查詢失敗返回非零值。查詢成功指服務器認為該查詢有效並接受,而且能夠執行,並不是指有關該查詢結果。例如,它不是指SELECT 查詢所選擇的行,或DELETE 語句所刪除的行。檢查查詢的實際結果要包括其他的處理。
查詢失敗可能有多種原因,有一些常見的原因如下:
■ 含有語法錯誤。
■ 語義上是非法的—例如涉及對表中不存在的列的查詢。
■ 沒有足夠的權利訪問查詢所引用的數據。
查詢可以分成兩大類:不返回結果的查詢和返回結果的查詢。INSERT、DELETE和UPDATE等語句屬於“不返回結果”類的查詢,即使對修改數據庫的查詢,它們也不返回任何行。可返回的唯一信息就是有關受作用的行數。SELECT 語句和SHOW 語句屬於“返回結果”類的查詢;發布這些語句的目的就是要返回某些信息。返回數據的查詢所生成的行集合稱為結果集,在MySQL中表示為MYSQL_RES 數據類型,這是一個包含行的數據值及有關這些值的元數據(如列名和數據值的長度)的結構。空的結果集(就是包含零行的結果)要與“沒有結果”區分開。
6.6.1處理不返回結果集的查詢
處理不返回結果集的查詢,用mysql_query() 或mysql_real_query() 發布查詢。如果查詢成功,可以通過調用mysql_ a ffected_rows() 找出有多少行需要插入、刪除或修改。下面的樣例說明如何處理不返回結果集的查詢:
請注意在打印時mysql_ a ffected_rows() 的結果是如何轉換為unsigned long 類型的,這個函數返回一個my_ulonglong 類型的值,但在一些系統上無法直接打印這個類型的值(例如,筆者觀察到它可在FreeBSD 下工作,但不能在Solaris 下工作)。把值轉換為unsigned long 類型並使用‘% l u’打印格式可以解決這個問題。同樣也要考慮返回my_ulonglong 值的其他函數,如mysql_num_rows() 和mysql_ insert _ id ( )。如果想使客戶機程序能跨系統地移植,就要謹記這一點。
mysql_ rows _ affected() 返回查詢所作用的行數,但是“受作用的行”的含義取決於查詢的類型。對於INSERT、DELETE 和UPDATE,是指插入、刪除或者更新的行數,也就是MySQL實際修改的行數。如果行的內容與所要更新的內容相同,則MySQL就不再更新行。這就是說雖然可能選擇行來更新(通過UPDATE 語句的WHERE 子句),但實際上該行可能並未改變。