0

我创建了一个测试数据库,如下所示:

USE test;
DROP TABLE IF EXISTS test;
DROP PROCEDURE IF EXISTS testparams;
CREATE TABLE test
(
  inparm INT,
  inoutparam INT,
  outparm INT
);

INSERT INTO test VALUES (0, 0, 0);

DELIMITER $$
CREATE PROCEDURE testparams(IN i INT, INOUT io INT, OUT o INT)
BEGIN
   UPDATE test SET inoutparm = io + 1, outparm = FLOOR(RAND() * 1000)
               WHERE inparm = i; 

   SELECT outparm INTO o FROM test WHERE inparm = i;
   SELECT inoutparam INTO io FROM test WHERE inparm = i;

END $$

我还有一个 PHP 脚本:

<?php

$c = new mysqli('localhost', 'test', 'test', 'test') or die('Cannot connect');
echo "Connected\n";

$in = 0;
$out = -1;
$inout = 3;

echo "In: $in Out: $out: Inout: $inout\n";

$s = $c->prepare('CALL testparams(?, ?, ?)') or die('Unable to prepare: ' . $c->error);
$s->bind_param('iii', $in, $inout, $out);
#$s->bind_result($out, $inout);
$s->execute();

echo "After execute SP\nIn: $in Out: $out: Inout: $inout\n";

echo "End of SP\n";
$s = $c->prepare('SELECT inparm, inoutparam, outparm FROM test');

# $s->bind_result($in, $inout, $out); - Get a error here

$s->execute();
while ($s->fetch())
{
    echo "In: $in Out: $out: Inout: $inout\n";
}

?>

我的问题是存储过程似乎没有被调用。这是由于使用OUTINOUT参数吗?如果是这样,您如何在 PHP 中使用这些参数?

生成以下输出的脚本证明了这一点

Connected
In: 0 Out: -1: Inout: 3
End of SP
In: 0 Out: 0: Inout: 0
4

3 回答 3

1

调用语法

对于用提供 MySQL 接口的语言编写的程序, 没有本地方法可以直接从 CALL 语句中检索 OUT 或 INOUT 参数的结果。要获取参数值,请将用户定义的变量传递给 CALL 语句中的过程,然后执行 SELECT 语句以生成包含变量值的结果集。要处理 INOUT 参数,请在 CALL 之前执行一条语句,将相应的用户变量设置为要传递给过程的值。

这似乎在 MySQL 5.6 中发生了变化

在 MySQL 5.6 中,C 程序可以使用prepared-statement 接口来执行CALL 语句并访问OUT 和INOUT 参数。... 提供 MySQL 接口的语言可以使用准备好的 CALL 语句直接检索 OUT 和 INOUT 过程参数。

那会做到的

<?php

$c = new mysqli('localhost', 'test', 'test', 'test') or die('Cannot connect');
echo "<pre>Connected<br>";

$in = 0;
$out = -1;
$inout = 3;

echo "Before executing SP<br>In: $in Inout: $inout Out: $out<br>";

$s = $c->prepare('SET @i = ?, @io = ?') or die('Unable to prepare: ' . $c->error);
$s->bind_param('ii', $in, $inout);
$s->execute();

$s = $c->prepare("CALL testparams(@i, @io, @o)") or die('Unable to prepare: ' . $c->error);
$s->execute();

$s = $c->prepare('SELECT @io, @o');
$s->execute();
$s->bind_result($inout, $out);
$s->fetch();

echo "After execute SP<br>In: $in Inout: $inout Out: $out<br>";

echo "End of SP<br></pre>";

?>

输出

Connected
Before executing SP
In: 0 Inout: 3 Out: -1
After execute SP
In: 0 Inout: 4 Out: 851
End of SP

顺便说一句,SP中有一个错字。这条线

UPDATE test SET inoutparm = io + 1, outparm = FLOOR(RAND() * 1000)

应该

UPDATE test SET inoutparam = io + 1, outparm = FLOOR(RAND() * 1000)
                        ^
于 2013-03-10T08:09:00.177 回答
1

我认为$s->bind_param('sss', $in, $inout, $out);应该

$s->bind_param('iii', $in, $inout, $out);

于 2013-03-10T08:23:17.023 回答
0

'sss' 应该是 'iii' 因为你处理的是整数,而不是字符串。

于 2013-03-10T08:00:00.743 回答