PHP PDO中从存储过程检索MySQL变量

8

我看到这个问题被问了很多次,但它们都非常长,我无法理解它们在做什么...所以,有人可以告诉我如何使用PDO将此过程中的LAST_INSERT_ID()传递到php中:

表格:

CREATE TABLE names (
    ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name varchar(50) NOT NULL
)

操作步骤:

CREATE DEFINER=`root`@`localhost` PROCEDURE `simpleProcedure`(newname varchar(50), OUT returnid INT(11))
BEGIN
    INSERT INTO names (name) VALUES (newname);
    SET returnid = LAST_INSERT_ID();
END

我尝试过的PHP代码:

$stmt=$db->prepare("CALL simpleProcedure(:name,:returnid)");
$stmt->bindValue(':name',$name,PDO::PARAM_STR);
$stmt->bindParam(':returnid',$returnid,PDO::PARAM_INT,11);
$stmt->execute();
echo $returnid;

但是,对于比我更聪明的人来说可能很明显,这并不起作用。欢迎任何帮助。

我认为这应该起作用的参考:

http://www.php.net/pdo.prepared-statements(示例#4)


1
你可能想使用bindParam而不是bindValue。bindParam通过引用传递变量,这将允许语句将值设置回变量中。http://www.php.net/manual/en/pdostatement.bindparam.php - Jonathan Kuhn
是的,我试过了,不起作用。 - Just Lucky Really
所以,使用 bindParam 看起来正在尝试工作,因为现在我不再收到 $returnid not set 错误... 但它仍然没有输出任何内容。 - Just Lucky Really
不行...那也没用...我已经更新了我的帖子以反映我尝试过的东西 - Just Lucky Really
是的...不幸的是,我认为你是对的Ryan。你想把它作为答案吗:(...我讨厌错误... - Just Lucky Really
显示剩余3条评论
2个回答

8
原来这是一个长期存在的错误...自2005年以来就一直存在!
以下是原始错误报告:从2005到2013年。 这是新的错误报告:从2013年到现在
有多种方法可以返回答案,我找到了其中一种并进行演示...
“诀窍”是从'mysql'过程中获取输出。这是一个“两阶段”过程。
第一部分是使用您的输入运行该过程,并告诉它要将结果存储在哪些MYSQL变量中。
然后,您运行一个单独的查询来“选择”那些'mysql'变量。
在此处已经很清楚地描述:php-calling-mysql-stored-procedures 更新(2017年1月):

这是一个示例,展示了如何使用变量作为'Mysql'过程参数的'IN'、'INOUT'和'OUT'。

在开始之前,这里有一些提示:

  • 在开发时:将PDO运行在“模拟模式”下,因为它更可靠地确定过程调用中的错误。
  • 只将PHP变量绑定到过程的'IN'参数。

当您尝试将变量绑定到'INOUT'和'OUT'参数时,您会得到一些非常奇怪的运行时错误。

像往常一样,我倾向于提供比所需注释更多的注释;-/

运行环境(XAMPP):

  • PHP:5.4.4
  • Mysql:5.5.16

源代码:

SQL代码:

CREATE PROCEDURE `demoSpInOutSqlVars`(IN     pInput_Param  INT, /* PHP Variable will bind to this*/   
                                      /* --- */  
                                      INOUT  pInOut_Param  INT, /* contains name of the SQL User variable that will be read and set by mysql */
                                      OUT    pOut_Param    INT) /* contains name of the SQL User variable that will be set by mysql */
BEGIN
    /*
     * Pass the full names of SQL User Variable for these parameters. e.g. '@varInOutParam'
     * These 'SQL user variables names' are the variables that Mysql will use for:
     *    1) finding values
     *    2) storing results
     *
     * It is similar to 'variable variables' in PHP.  
     */
     SET pInOut_Param      := ABS(pInput_Param) + ABS(pInOut_Param); /* always positive sum  */
     SET pOut_Param        := ABS(pInput_Param) * -3;                /* always negative * 3  */ 
END$$

PHP 代码:

数据库连接:

$db = appDIC('getDbConnection', 'default'); // get the default db connection
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);    
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

注意:当 EMULATE_PREPARES = false 时,输出结果相同。
设置将要使用的所有 PHP 变量:
$phpInParam     = 5;                  
$phpInOutParam  = 404;          /* PHP InOut variable  ==> read and should be changed  */
$phpOutParam    = null;         /* PHP Out   variable  ==> should be changed           */

定义并准备SQL过程调用:

$sql = "call demoSpInOut(:phpInParam, 
                         @varInOutParam, /* mysql variable name will be read and updated */
                         @varOutParam)"; /* mysql variable name that will be written to  */

$stmt = $db->prepare($sql);

绑定 PHP 变量并设置 SQL 变量:

  • 1) 绑定 PHP 变量

    $stmt->bindParam(':phpInParam', $phpInParam, PDO::PARAM_INT);

  • 2) 设置 SQL 用户 INOUT 变量

    $db->exec("SET @varInOutParam = $phpInOutParam"); // 这是安全的,因为它只是将值设置到 MySql 变量中。

执行存储过程:

$allOk = $stmt->execute();

将SQL变量传递给PHP变量:

$sql = "SELECT @varInOutParam AS phpInOutParam,
               @varOutParam   AS phpOutParam
        FROM dual";
$results = current($db->query($sql)->fetchAll());

$phpInOutParam = $results['phpInOutParam'];
$phpOutParam   = $results['phpOutParam'];

注意:也许不是最好的方法;-/
显示PHP变量
"$phpInParam:"     => "5"
"$phpInOutParam:"  => "409"
"$phpOutParam:"    => "-15"

但是这并没有像http://www.php.net/pdo.prepared-statements(示例#4)中描述的那样使用`OUT`函数。如果我要使用另一个`SEELCT`语句,我可能会将过程更改为`SELECT LAST_INSERT_ID() AS returnid而不是SET returnid = LAST_INSERT_ID()`。 - Just Lucky Really

-2

让我先说一下,这只是一个猜测,因为我从来不使用预处理语句...

通常情况下,您不会绑定返回值,而是这样做:

$status = $statement->execute(  );

$resultArray = $statement->fetchAll( );
$statement->closeCursor( );
if (!is_array($resultArray)) {
    return array();
}
return $resultArray[0]['returnid'];

不要完全相信这个...


不好意思,这会返回“未定义索引”错误 :( ... 但是为了表示歉意,这里有一张小鸭子滑板的照片... http://www.vhsmag.com/blog/v/images/001751145.jpg - Just Lucky Really

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接