【问题标题】:After rewind mysql query results, not working to re-use query倒回mysql查询结果后,无法重新使用查询
【发布时间】:2018-04-05 18:26:20
【问题描述】:

我对 mysql/php 倒带比较陌生。我正在执行一个查询,在我标记当前数据集并重新运行它之后,我需要运行相同的数据集来运行需要很长时间的 shell 脚本。我将在几分钟内运行与 cron 相同的脚本,因此我可以标记另一组并知道我正在获取不同的数据集来运行慢速 shell 脚本。由于某种原因,倒带不起作用,所以它没有使用数据集两次:

if(!($stmt = $mysqli->prepare("SELECT  node, model FROM Table WHERE vendor = 'Calix' AND model in ('C7','E7') AND  ((update_status NOT in ('u') OR (update_time IS NULL) OR ((DATEDIFF(NOW(),SW_ver_update_time)>14)) )) LIMIT 100"))) //AND ping_reply IS NULL AND software_version IS NULL 
{
    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

if(!$stmt->bind_result($ip, $model))
{
    echo "Binding results failed: (" . $stmt->errno . ") " . $stmt->error;
}

if(!$stmt->execute())
{
    $tempErr = "Error select node, model c7,e7 status: " . $stmt->error;
    printf($tempErr . "\n");    //show mysql execute error if exists  
    $err->logThis($tempErr);
}

$stmt1 = $mysqli1->prepare("UPDATE Table SET update_status = 'u' , update_time = UTC_TIMESTAMP() WHERE node = ?");

while($stmt->fetch()) {
    print "current ip: " . $ip . "\n";
    $stmt1->bind_param("s", $ip);
    $stmt1->execute(); //write time stamp and 'u' on ones 'in process of Updating'
}
//rewind db pointer
mysql_data_seek($stmt, 0);

//Circulate through 100 dslams fetched that we marked as in process.  
//This takes a long time to execuate and will be running this script concurrently in 5 minutes 
//so we need to know what we're working on so we don't fetch them again.
while($stmt->fetch()) {
  print "hello current ip: " . $ip . "\n";
  //will execute shell script here 
  //I never see hello print statement
}

我查看了mysql_data_seek,但没有看到使用 fetch() 的示例。倒带后我可以不使用 fetch() 吗?这里有什么问题?谢谢!

*更新: 我试过了

$stmt->data_seek(0);

但它仍然不允许我重复使用该查询。如果有人对如何让倒带工作或绕过它有什么建议,比如存储查询结果,以便我可以在以后不重新运行查询的情况下重复使用它们,那也没关系。

【问题讨论】:

    标签: php mysql rewind


    【解决方案1】:

    您不能将mysql_data_seek() 与mysqli 函数一起使用。 MySQL 的每个 PHP 扩展都是独立的,您不能将一个扩展的函数与另一个扩展的查询结果一起使用。

    您希望在 mysqli 扩展中使用等效函数:mysqli_stmt::data_seek()


    你的cmets:

    您可以使用get_result(),然后在结果上调用fetch_all()。这将返回一个行数组,其中每一行都是 MySQL 查询返回的列数组。

    if(!($stmt = $mysqli->prepare("SELECT  node, model FROM Table WHERE vendor = 'Calix' AND model in ('C7','E7') AND  ((update_status NOT in ('u') OR (update_time IS NULL) OR ((DATEDIFF(NOW(),SW_ver_update_time)>14)) )) LIMIT 100"))) //AND ping_reply IS NULL AND software_version IS NULL 
    {
        error_log("Prepare failed: ({$mysqli->errno}) {$mysqli->error}");
        die();
    }
    
    if(!$stmt->execute())
    {
        error_log("Error select node, model c7,e7 status: {$stmt->error}");
        die();
    }
    
    if (!($result = $stmt->get_result()))
    {
        error_log("Error get result of select node, model c7,e7: {$stmt->error}");
        die();
    }
    
    $rows = $result->fetch_all(MYSQLI_ASSOC);
    

    我还展示了error_log() 的用法,它会自动记录到您的 http 错误日志中。如果有错误,我会打电话给die(),这样代码就不会尝试继续下一步。在您的脚本中,您可能会采用不同的结构,例如使用 return,如果还有其他代码要运行。

    否则你可以完全接受exceptions

    【讨论】:

    • 我从来没有听说过!谢谢!我试过 $stmt->data_seek(0);在我的第二个 while stmt->fetch 之前,仍然看不到第二个循环中的 print 语句。
    • 坦率地说,我从未使用过 data_seek()。我只是将结果集的行放入 PHP 数组中,然后您可以访问任何您想要的。无论如何,MySQL 实际上并不支持游标,所以如果这完全可行,它需要 mysqli 将所有行存储在内存中。
    • 我以前从未将结果放入数组中。那不是一次将它们放入数组中吗?这无助于我以可重用的方式获取当前/完整查询的所有当前结果。你有例子吗?
    猜你喜欢
    • 2018-03-06
    • 2014-08-22
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多