2011-06-01 117 views
9

根據mysql_query()手冊以及我所瞭解的有關此功能的所有信息,我多次使用它,可以返回資源或FALSE,如果查詢是SELECT。但它不時返回TRUE爲什麼mysql_query()用SELECT語句返回TRUE?

這怎麼可能?它從未發生過。這是PHP 5.3.2中的錯誤嗎?有人對這個有了解嗎?

的代碼是一樣的東西:

if (!$resource = mysql_query($query, $handle)) { 
    throw some exception; 
} 

var_dump($query); 
if ($resource === true && strpos($query, 'SELECT') !== false) { 
    throw new Exception('mysql_query() returned TRUE for SELECT'); 
} 

這是非常難以重現了。它只是不時發生。我也注意到,它有可能發生這種情況的同時,服務器突然中斷連接,在這種情況下,它應該返回FALSE ...

+0

你確定它的查詢您使用返回true工作?因爲真正的只應該是插入更新或刪除。我會檢查並確保你沒有看到前面陳述中的變量。 – 2011-06-01 21:54:56

+0

你是如何得出結論的,它返回TRUE?在你認爲發生這種情況的地方展示一個片段。 – Mel 2011-06-01 21:54:58

+0

添加了片段。 'var_dump()'清楚地顯示了一個普通的'SELECT'查詢,我在一個正常的MySQL客戶端中運行並獲得了正常的結果。 – rid 2011-06-01 21:58:41

回答

6

如果webbiedave是不是在正確的軌道上,只有一個代碼路徑,允許這種情況在PHP源:

#if MYSQL_VERSION_ID < 32224 
#define PHP_MYSQL_VALID_RESULT(mysql)  \ 
    (mysql_num_fields(mysql)>0) 
#else 
#define PHP_MYSQL_VALID_RESULT(mysql)  \ 
    (mysql_field_count(mysql)>0) 
#endif 

...

if (!mysql_result) { 
    if (PHP_MYSQL_VALID_RESULT(mysql->conn)) { /* query should have returned rows */ 
     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save result set"); 
     RETURN_FALSE; 
    } else { 
     RETURN_TRUE; // <<< this case 
    } 
} 

我會認爲這是一個錯誤。特別是因爲沒有真正的方法來驗證這一點 - PHP代碼中的mysql_num_fields使用的是你沒有得到的資源,而不是連接。

雖然它仍然是離奇,請求mysql_query C版失去了連接上返回零 - 如果你能夠,請嘗試以下補丁程序,並重新安裝mysql擴展:

Index: ext/mysql/php_mysql.c 
=================================================================== 
--- ext/mysql/php_mysql.c  (revision 311719) 
+++ ext/mysql/php_mysql.c  (working copy) 
@@ -1485,6 +1485,9 @@ 
       if (PHP_MYSQL_VALID_RESULT(mysql->conn)) { /* query should have returned rows */ 
         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save result set"); 
         RETURN_FALSE; 
+    } else if(mysql_errno(mysql->conn) != 0) { 
+      php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(mysql->conn)); 
+      RETURN_FALSE; 
       } else { 
         RETURN_TRUE; 
       } 
+0

實際上'MYSQL_VERSION_ID'被定義爲'MYSQLND_VERSION_ID',它被定義爲'50007'。所以它應該在'mysql_field_count()'分支上。 – rid 2011-06-01 23:35:33

+0

我不確定'mysql_field_count()'函數會做什麼(將查找它),但是如果它按名稱所做的那樣執行,如果發生問題,'mysql_field_count(mysql)'不會被'0' ? – rid 2011-06-01 23:37:39

+0

@Radu修改了補丁,在那裏有一個錯誤,mysql_error應該是mysql_errno。是的,field_count應該爲零。這是一個不應該發生的事情的經典案例,但我認爲我們在這個領域裏有這個bug。 – Mel 2011-06-01 23:42:21

-2

對於SELECT, SHOW, DESCRIBE, EXPLAIN等語句返回的結果集,請求mysql_query()成功返回的資源,或者錯誤時爲FALSE。

對於其他類型的SQL語句,INSERT, UPDATE, DELETE, DROP等,mysql_query()返回TRUE成功或FALSE出錯。

(from http://php.net/manual/en/function.mysql-query.php)

你說SELECTs返回布爾值true?不只是一個不是零的資源:)?

+0

這不do解釋爲什麼它的select返回true – dynamic 2011-06-01 21:56:09

+0

是的,它是'TRUE'。用'==='檢查。 – rid 2011-06-01 21:58:27

+8

選民再次怪異。複製說明OP已經知道的手冊並不回答問題。 – Mel 2011-06-01 21:58:58

0

當你說它「返回TRUE」時,你如何測試它?你沒有任何機會做這樣的事情,對嗎?

$result = mysql_query($sql); 
if ($result == TRUE) { /* stuff */ } 

如果是這樣,請記住,所有非零,返回非空白,非空值將評估爲TRUE。您可以使用更嚴格的驗證:

if ($result === TRUE) { /* stuff */ } 

這不僅評估等效性,而且評估類型。你在做類似var_export($ result)的事情嗎?檢查數據類型並驗證你是否真的獲得了TRUE的布爾值?

-2

James想說的是,如果查詢已被正確執行並執行,函數mysql_query()只會返回true。它與查詢產生的結果無關。

如果您想實際獲取結果,請使用mysql_fetch_assoc()/ mysql_fetch_array()/ mysql_results()。

0

讓我們以另一種方式來看,當mysql_query()返回FALSE這意味着由於某種原因,查詢嘗試失敗。意思是說,即使在你做了查詢之後,你的查詢出錯了,因爲這對數據庫沒有任何影響,或者查詢甚至無法達到它可以看到數據庫的地步。

+0

是的,那是預期的行爲。但是,'mysql_query()'返回'TRUE',而不是'FALSE'。 – rid 2011-06-01 22:24:17

+0

@Radu,別忘了,'!$ resource = mysql_query($ query,$ handle)'如果mysql_query返回'FALSE',就等同於'TRUE'。 – 2011-06-02 05:26:00

+1

mysql_query()可以返回false並修改數據庫。如果將數據插入到MyISAM表中,並在插入幾行後出現錯誤(重複的唯一鍵等),則mysql_query()返回false(錯誤),但行保留在表中。 – peufeu 2011-06-02 11:16:09

0

你沒有提到的數據但你應該檢查是否超過max_allowed_packet

When a MySQL client or the mysqld server receives a packet bigger than max_allowed_packet bytes, it issues a Packet too large error and closes the connection. With some clients, you may also get a Lost connection to MySQL server during query error if the communication packet is too large.

[...]

Both the client and the server have their own max_allowed_packet variable, so if you want to handle big packets, you must increase this variable both in the client and in the server.

http://dev.mysql.com/doc/refman/5.5/en/packet-too-large.html

不知道怎麼的mysql_query返回值是受此影響,但它值得調查。將它設置爲my.cnf以查看它是否解決了問題是最好的開始。

+0

確實值得調查。我如何知道PHP客戶端的'max_allowed_pa​​cket'是什麼?這顯然不在服務器上,因爲查詢非常短。 – rid 2011-06-01 22:48:28

+0

我相信你需要通過'SET @@ max_allowed_pa​​cket = NUM​​'行來通過mysql_query發出一條SQL語句我認爲你可以使用'64MB'等縮寫符號,但我還沒有嘗試過。 – webbiedave 2011-06-01 22:59:57

+0

@Radu:我不知道如何查看客戶端設置。你可以試試'SHOW VARIABLES LIKE'max_allowed_pa​​cket';'mysql客戶端的默認值是16MB,這對PHP客戶端來說可能也是正確的。我不確定那個。 – webbiedave 2011-06-01 23:06:06

0

mysql_query不返回FALSE,更不用說TRUE。它返回一個資源ID,如果等於0,則認爲FALSE。我的例子是爲了說明布爾結果

$resource = mysql_query($query, $handle); 
if (!$resource) throw some exception; 
if (!$resource && strpos($query, 'SELECT')) { 
throw new Exception('mysql_query() returned TRUE for SELECT'); 
} 

PHP Booleans

+0

你是什麼意思? – rid 2011-06-28 12:26:51

+0

mysql_query不返回FALSE,更不用說TRUE。它返回一個資源ID,如果等於0,則認爲FALSE。我的例子是說明布爾結果。 – Steve 2011-07-10 16:21:06

+0

Steve,下次請編輯您的答案並加以改進。我這次爲你做了,並投了票。 – 2015-10-28 11:28:20