服务器详细信息:
PHP v5.3.5
使用MySQLi库客户端api版本:mysqlnd 5.0.7-dev - 091210 - $ Revision:304625 $
MySQL Server v5.5.9
我在MySQL中有一个名为f_get_owner_locations(_in int)的存储函数。它构造一个文本变量,用于保存特定所有者拥有的任何公寓的位置。 如果我跑了
SELECT f_get_owner_locations( 3 );
从MySQL命令行开始,它执行它应该做的事情并返回一行:
+----------------------------+
| f_get_owner_locations( 3 ) |
+----------------------------+
| A-01 |
+----------------------------+
但是,每当我尝试使用MySQLi库通过PHP运行它时:
$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方法中为我提供了1个正确的转储,然后停止并且该错误就在那里。
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的调用是该选择列表上的第二个字段,因此它不存储正确的字段数,尽管它说它需要循环到正确的字段数量。
任何有关绕过这个小路障或确认这是MySQLi库中的错误或我的绑定代码问题的建议都将非常感激。
更新: 以下代码:
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 :(得分:0)
MySQL存储过程可以返回多个结果集,其中最后一个结果集是您感兴趣的实际数据.mysqli正确执行的一些事情是支持多个结果集。< / p>
尝试检查mysqli::more_results
。另请参阅手册页上的免责声明mysqli::store_result
,了解mysqli如何处理多个结果集,其中一个可能没有数据。您最终将使用mysqli_result
课程而不是mysqli_stmt
。
答案 1 :(得分:0)
因此,在经过更多测试之后,我发现它实际上并不是MySQLi库或我的代码中的错误。
解决方案?为数据库用户授予MySQL中数据库的“执行”权限。我在以root身份登录时编写并测试了SQL语句和函数,而不是脚本使用的实际用户。
哦,IT的乐趣。