使用MySQLi预处理语句时无法获取行数和获取次数

时间:2017-09-17 10:04:36

标签: php mysql mysqli row prepared-statement

我想从数据库中获取行数,但是当我尝试这样做时,$g_check变量将等于0,我的代码将回显$sugg_title消息在else语句中。但是在数据库中有4个插入的组,因此num_rows属性应该返回4。

$sql = "SELECT DISTINCT gp.logo, gp.name
        FROM gmembers AS gm
        LEFT JOIN groups AS gp ON gp.name = gm.gname
        WHERE gp.creator != ? AND gm.mname != ? LIMIT 10";
$stmt = $conn->prepare($sql);
$stmt->bind_param('ss',$log_username,$log_username);
$stmt->execute();
$g_check = $stmt->num_rows;
if ($g_check > 0){
  $result = $stmt->get_result();
  while ($row = $result->fetch_assoc()) {
    $agList .= '<a href="group.php?g='.$row["name"].'"><img class="group_margin" src="groups/'.$row["name"].'/'.$row["logo"].'" alt="'.$row["name"].'" title="'.$row["name"].'" width="70" height="70" /></a>';
  }
}else{
  $sugg_title = "You have no group suggestions at the moment. Click ";
  $sugg_title .= '<a href="all_groups.php">here</a> to view all groups.';
}

我在strore_result()之后放置了fetch()execute()函数,但后来收到此错误消息:&#34; 致命错误:未捕获错误:呼叫成员函数fetch_assoc()on boolean &#34;

1 个答案:

答案 0 :(得分:2)

如果要使用mysqli_stmt::$num_rows(即检查预准备语句中的行数),则需要在执行预准备语句后使用$stmt->store_result(),然后才能检查编号的数量行。这意味着在我们检查返回的行数之前,结果存储在内存中。

$stmt = $conn->prepare($sql);
$stmt->bind_param('ss',$log_username,$log_username);
$stmt->execute();
$stmt->store_result(); // Need to store the result into memory first
if ($stmt->num_rows) {
    // ...

但是,如果您想使用mysqli_result::$num_rows(在您从语句结果转换的MySQLi结果中),您需要在执行$result = $stmt->get_result();之后执行此操作,并使用$result->num_rows;,如下图所示。

$stmt = $conn->prepare($sql);
$stmt->bind_param('ss',$log_username,$log_username);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows) {
    while ($row = $result->fetch_assoc()) {
    // ....

最后,他们最终应该做同样的事情 - 提供原始准备查询返回的一些行。

注意
请注意,您不能在同一声明中使用store_result()get_result(),这一点非常重要。这意味着在第一个示例中,您无法转换为mysqli-result对象(使用get_result(),这允许您使用标准fetch_assoc()方法)。由于store_result()将结果存储到内存中,因此get_result()无需转换,反之亦然。

这意味着如果您使用store_result(),则需要通过statement-fetch,mysqli_stmt::fetch()获取并通过mysqli_stmt::bind_result()绑定结果。如果使用get_result(),则应检查生成的MySQLi结果对象上的行数(如第二个示例所示)。

你应该为此构建你的代码,这样你只需要使用其中一个。

话虽如此,使用评论中建议的affected_rows,并不是正确的工作工具 - 根据mysqli_stmt::$affected_rows上的手册(同样适用于常规查询, mysqli::$affected_rows):

  

返回受INSERT,UPDATE或DELETE查询影响的行数   此功能仅适用于更新表的查询。要从SELECT查询中获取行数,请改用mysqli_stmt_num_rows()