php - 使用准备好的语句从 PHP5 中的 MySQL 存储过程获取结果

标签 php stored-procedures mysqli prepared-statement resultset

我正在使用 PHP5 和 MySQL 开发一个网站。我使用 mysqlnd 驱动程序,我有一个类使用准备好的语句来执行我想要的任何查询。

我有一张表,用于存储有关照片的信息,例如照片的 ID、标题、拍摄地点的纬度和经度等。

我创建了以下存储过程并根据我在此处找到的内容实现了 Haversin 公式:http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL

程序是:

DELIMITER $$
CREATE PROCEDURE imagesNearMe(IN user_lat DOUBLE, IN user_lng DOUBLE, IN distance INT)
READS SQL DATA
BEGIN

DECLARE lat1 DOUBLE;
DECLARE lng1 DOUBLE;
DECLARE lat2 DOUBLE;
DECLARE lng2 DOUBLE;

SET lng1 = user_lng - (distance/ABS(COS(RADIANS(user_lat)) * 69));
SET lng2 = user_lng + (distance/ABS(COS(RADIANS(user_lat)) * 69));
SET lat1 = user_lat - (distance/69);
SET lat2 = user_lat + (distance/69);

SELECT id, title, description, location, lat, lng, user_id,
        3956 * 2 * ASIN( SQRT( 
        POWER( SIN( (user_lat - ABS(lat)) * pi() / 180 / 2), 2) + 
        COS(user_lat * pi() / 180) * COS( ABS(lat) * pi() * 180) * POWER( SIN( (user_lng - lng) * pi() / 180 / 2), 2) ) ) as distance
        FROM images
        WHERE (lat IS NOT NULL) AND (lng IS NOT NULL)
            AND (lat BETWEEN lat1 AND lat2)
            AND (lng BETWEEN lng1 AND lng2)
        ORDER BY distance ASC;

END$$
DELIMITER ;

当我从 MySQL 控制台调用它并返回预期数据时,该过程工作正常。问题是当我尝试从我的 PHP 代码调用该过程时。由于某种原因,我无法获取过程返回的数据。

我有以下测试方法:

public function CallProcedure( $procedure, $arguments )
    {
        print_r($procedure);
        echo "<br>*************************<br>";

        if( ! $this->_sqlStatement = $this->_dbSession->prepare($procedure))
        {
            return FALSE;
        }

        else
        {
            //Prepare succeeded
            if($arguments)
            {
                //if we have arguments we have to prepare and bind the to the query
                //get the bind string
                $bindString = array_shift($arguments);

                //get references to the parameters passed to the query
                $bindParamRefs = array();
                foreach($arguments as $key => $value)
                {
                    $bindParamRefs[$key] = &$arguments[$key];
                }
                //put a reference to the bindString inside the bindParamsRefs array
                array_unshift($bindParamRefs, $bindString);

                print_r($bindParamRefs);
                echo "<br>*************************<br>";
                //Bind the params to the query
                if(!call_user_func_array(array($this->_sqlStatement, "bind_param"), $bindParamRefs))
                {
                    return FALSE;
                }

                else
                {
                    print_r($this->_sqlStatement);
                    echo "<br>*************************<br>";
                    if( ! $this->_sqlStatement->execute() )
                    {
                        return FALSE;
                    }

                    else
                    {
                        do
                    {
                        $this->_sqlStatement->store_result();
                        print_r($this->_sqlStatement);
                        echo "<br>*************************<br>";


                        $resultSet = array();
                        $resultMetadata = $this->_sqlStatement->result_metadata();
                        $resultVariables = array();
                        $resultData = array();

                        while($resultField = $resultMetadata->fetch_field())
                        {
                            $resultVariables[] = &$resultData[$resultField->name];
                        }

                        call_user_func_array(array($this->_sqlStatement, "bind_result"), $resultVariables);

                        $i = 0;
                        while( $this->_sqlStatement->fetch() )
                        {
                            $resultSet[$i] = array();
                            foreach($resultData as $fieldName => $fieldData)
                            {
                                $resultSet[$i][$fieldName] = $fieldData;
                            }
                            $i++;
                        }

                        print_r($resultSet);
                        echo "<br>*************************<br>";
                        print_r($resultMetadata);
                        echo "<br>*************************<br>";
                        print_r($resultVariables);
                        echo "<br>*************************<br>";
                        print_r($resultData);
                        echo "<br>*************************<br>";

                        $this->_sqlStatement->free_result();

                    }
                    while($this->_sqlStatement->more_results() && $this->_sqlStatement->next_result());

                    $this->_sqlStatement->close();
                    }
                }
            }
        }

    }

($this->_dbSession是mysqli的一个实例)

上面代码产生的输出是:

CALL imagesNearMe(?, ?, ?)
*************************
Array ( [0] => ddi [1] => 38.246214 [2] => 38.246214 [3] => 150 ) 
*************************
mysqli_stmt Object ( [affected_rows] => -1 [insert_id] => 0 [num_rows] => 0 [param_count] => 3 [field_count] => 0 [errno] => 0 [error] => [sqlstate] => 00000 [id] => 1 ) 
*************************
mysqli_stmt Object ( [affected_rows] => 0 [insert_id] => 0 [num_rows] => 0 [param_count] => 3 [field_count] => 8 [errno] => 0 [error] => [sqlstate] => 00000 [id] => 1 ) 
*************************
Array ( ) 
*************************
mysqli_result Object ( [current_field] => 8 [field_count] => 8 [lengths] => [num_rows] => 0 [type] => 1 ) 
*************************
Array ( [0] => [1] => [2] => [3] => [4] => [5] => [6] => [7] => ) 
*************************
Array ( [id] => [title] => [description] => [location] => [lat] => [lng] => [user_id] => [distance] => ) 
*************************

如您所见,即使语句正确执行,也不会返回任何数据,即使通过从 mysql 控制台使用完全相同的参数调用完全相同的过程返回 4 个结果也是如此。

我错过了什么吗?我完全迷失在这里。

在此先感谢您的帮助。


更新


以下代码:

$dbSession = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT);

if($dbSession->connect_errno)
{
    die($dbSession->connect_error);
}

else
{
    $query = "CALL imagesNearMe(38.2462140, 21.735098, 50)";

    if(!$dbSession->multi_query($query))
    {
        die($dbSession->error);
    }

    else
    {
        do
        {
            if($result = $dbSession->store_result())
            {
                var_dump($result->fetch_all());
                echo "<br>******************************************************<br>";
                $result->free();
            }
            else
            {
                die($dbSession->error);
            }
        }
        while($dbSession->more_results() && $dbSession->next_result());

        $dbSession->close();
    }
}

返回了我期望的所有结果,但为什么准备好的语句不起作用?

最佳答案

找到你的问题

由于 call_user_func_array 的工作方式,您需要使用引用(“&”)并且您在相同的引用上循环遍历 fetch() 方法 - 但是 有第二个结果集“OK”返回说 CALL 语句成功,这会用空白结果集覆盖您正在查找的结果集

尝试改变

$i = 0;
while( $this->_sqlStatement->fetch() )
{
     $resultSet[$i] = array();
     foreach($resultData as $fieldName => $fieldData)
     {
          $resultSet[$i][$fieldName] = $fieldData;
     }
     $i++;
}

if(!$this->_sqlStatement->fetch())
{
     //break do-while() loop
     break;
}
$resultSet[$i] = array();
foreach($resultData as $fieldName => $fieldData)
{
     $resultSet[$i][$fieldName] = $fieldData;
}
$i++;

您还需要在 do-while() 开始之前设置初始 $i

关于php - 使用准备好的语句从 PHP5 中的 MySQL 存储过程获取结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12648770/

相关文章:

php - mysqli 使用 while 循环准备语句

php - 在 MySql 到 MySqli 转换后处理 MySQLi 查询的结果

php - 为什么我无论如何都要连接数据库

php - MySQL Concat 或 Fetch and Merge with PHP;哪个服务器便宜?

php - 用 PHP 发布 1 张以上的图片?

sql - 我在这个 MySQL 存储过程中做错了什么?

azure - 文档数据库 : How to run a query without timing out

Azure 数据工厂 V2 : Copy OR Stored Procedure activity for SQL merge

javascript - 如何使用两点经纬度绘制行车路线路径

php - 插入新事件时 SQL 语法错误