2011-03-12 47 views
1

服務器的詳細信息MySQL存儲功能:
PHP v5.3.5
使用的MySQLi庫客戶端API版本:5.0.7 mysqlnd-dev的 - 091210 - $修訂:304625 $
MySQL服務器v5.5.9致命錯誤,而從PHP調用使用的MySQLi

我在MySQL中有一個名爲f_get_owner_locations(_in int)的存儲函數。它構造了一個文本變量,它保存特定所有者擁有的任何公寓的位置。 如果我運行一個

SELECT f_get_owner_locations(3); 
從MySQL命令行

,它做什麼,它應該做的,並返回一個行:

+----------------------------+ 
| f_get_owner_locations(3) | 
+----------------------------+ 
| A-01      | 
+----------------------------+ 

但是,每當我試圖通過PHP使用的MySQLi運行庫作爲這樣的:

$sql = "SELECT f_get_owner_locations(3)"; 
$location = $GLOBALS['db']->fetch($sql); 

我得到這個錯誤:

Fatal error: Call to a member function fetch_field() on a non-object 
in ~/kernel/Database.php on line 328 

該行指的是這樣的:

/** 
* Binds results from a returning SQL statement to an array we can 
* loop through. 
* 
* @param $statement Statement object we're binding from. 
* @return Array of values being returned. 
* @since 0.1 
*/ 
private final function _bindResult($statement) 
{ 
    $results = NULL; 
    $bind = array(); 

    //Get the result set, so we can loop through the fields. 
    $result = $statement->result_metadata(); 
    //Loop through the fields and get a reference to each. 
    while($column = $result->fetch_field()) //<=<=<=LINE 328 
     $bind[] = &$results[$column->name]; 
    //Do the actual binding. 
    call_user_func_array(array($statement, 'bind_result'), $bind); 

    //Free the memory since we already have the result. 
    $result->free_result(); 

    return $results; 
} //_bindResult 

記住的SQL語句時不涉及函數調用它不會失敗。即這個工程:

$sql = "SELECT `id` FROM `owners`"; 
$owners = $GLOBALS['db']->fetch($sql); 

但只要我需要得到他們所擁有的公寓爲它添加(及本聲明通過MySQL命令行工作以及):

$sql = "SELECT `id`, f_get_owner_locations(`id`) FROM `owners`"; 
$owners = $GLOBALS['db']->fetch($sql); 

它給我一個關於調用非對象成員函數的錯誤。

我很難過。在while循環之前對$ result做一個var_dump,在我的_bindResults方法中,給了我一個正確的轉儲,然後停下來,那個錯誤就在那裏。

object(mysqli_result)#11 (5) { 
    ["current_field"]=> 
    int(1) 
    ["field_count"]=> 
    int(1) 
    ["lengths"]=> 
    NULL 
    ["num_rows"]=> 
    int(0) 
    ["type"]=> 
    int(1) 
} 

注:以f_get_owner_locations的調用是選擇列表中的第2場,所以它不是存儲在右場數,儘管說,它需要回路領域的正確的金額。

任何建議來解決這個小路障或確認這是MySQLi庫中的錯誤或與我的綁定代碼的問題將不勝感激。

UPDATE: 下面的代碼:

mysql_connect(...); 
mysql_query("select f_get_owner_locations(3)"); 
die(mysql_error()); 

給了我這個輸出:

FUNCTION f_get_owner_locations does not exist. 

我更想知道,這僅僅是在PHP /庫MySQLi的部分比我的失敗呢?

更新2:
按照要求,用於創建函數的代碼:

drop function if exists f_get_owner_locations; 
delimiter | 
create function f_get_owner_locations(_in int) 
returns text deterministic 
begin 
    declare _output text default ""; 
    declare _location varchar(255); 
    declare _count int default 0; 
    declare _done int default 0; 
    declare _cursor cursor for 
     select 
      condos.location 
     from 
      owners left join 
      condo_owners on owners.id = condo_owners.owner left join 
      condos on condo_owners.condo = condos.id 
     where 
      owners.id = _in; 
    declare continue handler for not found set _done = 1; 

    open _cursor; 

    repeat 
     fetch _cursor into _location; 
     set_count = _count + 1; 
     set_output = concat(_output, ", ", _location); 
    until _done end repeat; 

    set _count = _count - 1; 

    close _cursor; 

    set _output = trim(leading ", " from _output); 
    set _output = substring(_output from 1 for (_count * 6)); 
    set _output = trim(trailing ", " from _output); 
    return _output; 
end;| 
delimiter ; 

帶着幾分重構,可能會是一個小一點清潔劑誠然,但是這是我用什麼。

回答

0

因此,在進行了更多的測試之後,我發現它實際上並不是MySQLi庫或我的代碼中的錯誤。

解決方案?爲數據庫用戶授予MySQL中數據庫的「執行」權限。我以root用戶身份登錄時,編寫並測試了SQL語句和函數,而不是腳本正在使用的實際用戶。

哦,它的樂趣。

0

MySQL存儲過程可以返回多個結果集,其中最後的結果集是您感興趣的實際數據。mysqli正確執行的幾件事之一是支持多個結果集。

嘗試檢查mysqli::more_results。另請查看手冊頁上關於mysqli::store_result關於mysqli如何處理多個結果集的免責聲明,其中可能沒有數據。您最終將使用mysqli_result類而不是mysqli_stmt

+0

嗯。我得看看那個。正如我在我的原始問題的編輯中添加的,使用常規MySQL庫而不是MySQLi來測試語句本身返回:「FUNCTION f_get_owner_locations不存在」出現錯誤。 – 2011-03-12 22:02:27

+0

@Mike S,這很奇怪。當你使用'CALL'而不是'SELECT'時會發生什麼? – Charles 2011-03-12 23:00:30

+0

@Charles,MySQLi和普通的MySQL庫給我一個「程序f_get_owner_locations不存在」的錯誤。 – 2011-03-12 23:14:35