PHP mysqli为带有out参数的存储过程准备语句

Posted

技术标签:

【中文标题】PHP mysqli为带有out参数的存储过程准备语句【英文标题】:PHP mysqli prepared statement for stored procedure with out parameter 【发布时间】:2014-10-30 10:59:06 【问题描述】:

我有一个存储过程 IsUserPresent,例如:

DELIMITER $$
CREATE PROCEDURE IsUserPresent(
    in userid varchar (150),
    out isPresent bit
)
BEGIN
    SET isPresent=0;
    SELECT COUNT(*)
    INTO isPresent
    FROM users_table
    WHERE users_table.userid=userid;
END$$

我想使用 mysqli 准备语句从 php 调用它。我正在按照代码 sn-p 执行此操作,但它给了我警告。

$connect=&ConnectDB();
$stmt=$connect->prepare("CALL IsUserPresent(?,?)");
$stmt->bind_param('si',$uid,$userCount);
$stmt->execute();
$toRet = $userCount!=0;
Disconnect($connect);
return $toRet;

警告如下:

Premature end of data (mysqlnd_wireprotocol.c:1112)
Warning: mysqli_stmt::execute(): RSET_HEADER packet 1 bytes shorter than expected
Warning: mysqli_stmt::execute(): Error reading result set's header

【问题讨论】:

【参考方案1】:

存储过程处理预准备语句的方式有点复杂。 PHP manual 声明您必须使用会话变量(MySQL 会话,而不是 PHP)

INOUT/OUT 参数

使用会话变量访问 INOUT/OUT 参数的值。

所以你可以用

$connect=&ConnectDB();
// bind the first parameter to the session variable @uid
$stmt = $connect->prepare('SET @uid := ?');
$stmt->bind_param('s', $uid);
$stmt->execute();

// bind the second parameter to the session variable @userCount
$stmt = $connect->prepare('SET @userCount := ?');
$stmt->bind_param('i', $userCount);
$stmt->execute();

// execute the stored Procedure
$result = $connect->query('call IsUserPresent(@uid, @userCount)');

// getting the value of the OUT parameter
$r = $connect->query('SELECT @userCount as userCount');
$row = $r->fetch_assoc();               

$toRet = ($row['userCount'] != 0);

备注:

我建议将此过程重写为一个带有一个返回 INT 的 IN 参数的函数。

【讨论】:

【参考方案2】:

应该是评论,但由于代码格式发布为答案。

无法评论PHP代码,我不是程序员,但你的程序应该更像这样:

DELIMITER $$
CREATE PROCEDURE IsUserPresent(
    in p_userId varchar (150),
    out p_isPresent bit
)
BEGIN

    SELECT EXISTS (SELECT 1 FROM users_table WHERE user_table.userid = p_userId) 
    INTO p_isPresent;

END$$

使用exists(),因为它会在找到条目后立即停止。 count() 继续查找记录,尽管这不是必需的。

并且您将参数命名为与列名称相同的名称。这对 MySQL 来说是令人困惑的,应该不惜一切代价避免。好的做法是,在参数前面加上 p_,在变量前面加上 v_ 和/或一些变量或参数类型的指示。

为了更好的可读性,我还将参数名称更改为驼峰式。

哦,最后总是在问题中包含错误消息。

【讨论】:

上面的语句在 p_isPresent 中做了什么。我认为我们不能使用外部嵌套查询返回的结果。感谢您的提示。 exists() 返回 0 或 1(真或假)。并且子查询不是问题,因为您将结果放入变量中。

以上是关于PHP mysqli为带有out参数的存储过程准备语句的主要内容,如果未能解决你的问题,请参考以下文章

php调用oracle带有out参数的存储过程

使用 PDO 调用带有 Out 参数的存储过程

如何将 MySQLi 准备好的语句与存储过程一起使用

PHP:带有“select *”的Mysqli准备语句

带有两个OUT参数和c#的Mysql存储过程

使用自定义 ItemReader 调用带有 IN 和 OUT 参数的存储过程