【问题标题】:PDO and MySQL UPDATE in Foreach LoopForeach 循环中的 PDO 和 MySQL UPDATE
【发布时间】:2014-05-26 09:51:40
【问题描述】:

我遇到了这个让我完全难过的问题。这是我的执行模式。 PDO 调用嵌套在 foreach 循环中。

foreach(){
    foreach(){

    }
}

我在 MySQL 中使用 PDO,当我连续执行 UPDATE 查询时,它们在循环中相互干扰。我知道他们从注释掉一组单独工作,然后执行另一组。这是我正在处理的代码模板:

$set_data1 = "UPDATE data_table
              SET data_status = 'PROCESSED' 
              WHERE data_id = :data_id1";

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

$stmt->bindParam(':data_id1', $data_array1['data_id'], PDO::PARAM_INT);

$stmt->execute();

$set_data2 = "UPDATE data_table
              SET data_status = 'PENDING'
              WHERE data_id = :data_id2";

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

$stmt->bindParam(':data_id2', $data_array2['data_id'], PDO::PARAM_INT);

$stmt->execute();

由于某种原因,在嵌套的 foreach 循环中执行两个查询时,来自 $set_data1 的数据被 $set_data2 取消。我试过用 $stmt->closeCursor(); 关闭光标我尝试使用单个语句进行准备,并将新参数绑定到语句。我尝试将 $stmt 和 $db 实例设置为 null,然后重新实例化它们无济于事。我试过在查询中使用 CASE THEN 和 IF 条件......什么都没有。任何有关问题所在的信息都会很棒。我不知道 PDO 是否在循环内对同一张表调用 UPDATES 时出错,因为我在其他地方从未遇到过这个问题。提前致谢!

【问题讨论】:

  • 您没有显示准​​备 $data_array1 和 $data_array2 的代码。两者中的 data_id 是否可能/可能相同?
  • 不,ID 完全不同,因为它们之前使用不同的参数检索,然后存储在单独的数组中。
  • 你能发布它在 foreach 循环中的外观吗?我怀疑你没有在正确的地方调用 execute。

标签: php mysql pdo foreach nested


【解决方案1】:

对于初学者,您使用 bindParam() 就像它是 bindValue(),它们是 quite different

如果不知道从哪里获取数组值,就很难确定发生了什么。看起来您提供的信息实际上可能不是您正在使用的代码并且已被修改,特别是关于 foreach 循环和 data_array 变量,因为您所描述的是 BindParam 常见的问题,所以这是我的假设会继续努力的。如果是这种情况,通常最好提供实际代码 sn-ps,包括初始化使用的变量和发现问题的块,而不仅仅是这些块中的代码。

这是另一个答案with why,基本上确保您通过引用传递 foreach 循环的值部分或将 bindParams 更改为 bindValues。如果您打算继续使用此结构,您还需要确保在此处使用两个单独的对象而不是一个对象,因为每次调用 execute() 时都会运行这两个 bindParam() 方法。

比如说,代码结构是否没有改变(可能应该是这样,因为这一切都在循环中,只有 Execute 应该在循环中):

$set_data1 = "UPDATE data_table
          SET data_status = 'PROCESSED' 
          WHERE data_id = :data_id1";

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

$stmt->bindValue(':data_id1', $data_array1['data_id'], PDO::PARAM_INT);

$stmt->execute();

$set_data2 = "UPDATE data_table
              SET data_status = 'PENDING'
              WHERE data_id = :data_id2";

$stmt2 = $db->prepare($set_data2);

$stmt2->bindValue(':data_id2', $data_array2['data_id'], PDO::PARAM_INT);

$stmt2->execute();

一个更优化的方法是这样的(请记住,这只是一个一般示例):

$set_data = "UPDATE data_table
          SET data_status = :data_status 
          WHERE data_id = :data_id";

$data_array = array( array('data_status' => $dataStatus1, 'data_id' => $dataId), array('data_status' => $dataStatus2, 'data_id' => $dataId2) ); 
/* this is just to represent a multidimensional array (or a multidimensional object) containing the data status and the data id which should be handled and decided before you pass them into a loop. */

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

$data_status = null;
$data_id = null;

$stmt->bindParam(':data_status', $data_status);
$stmt->bindParam(':data_id', $data_id);

foreach( $data_array as $name => $val ) {
    $data_status = $val['data_status'];
    $data_id = $val['data_id'];
    $stmt->execute()';
}

【讨论】:

  • 感谢您的提示。我最终完全重写了逻辑,但也改用了 bindValue,一切都运行得很顺利而且很漂亮。感谢大家的帮助。 :)
【解决方案2】:

虽然非常很难从你提供的草图中分辨出你的真实代码是什么,

这是您在做什么的简化示例:

$apples = 4;
$apples = 18;
echo $apples;

它将打印多少苹果,为什么它会“干扰”初始数量?

【讨论】:

  • 问题仍然存在于不同的数据集。即使我准备一次,多次执行,数据仍然相互干扰。我将不同的参数绑定到两种执行方法,并操作不同的行。我该如何解决这个问题?
  • 你能告诉我,它会打印多少以及为什么?
  • 存储在数据库中的结果是ID不同的两个数据集都将被处理为'PENDING',并完全覆盖data_id1的data_status。
  • 等一下,你是说因为 $apples = 18 覆盖了 $apples = 4,所以两个不同的实例会以某种方式相互交叉?即使我在执行第一个 $stmt 之后将 $db 对象设置为 null,然后调用 $db = new Database(),并将其绑定到 $stmt2,它仍然会在数据库中覆盖它。这是 MySQL 内部的问题吗?
猜你喜欢
  • 2015-10-29
  • 2016-09-02
  • 2015-03-14
  • 1970-01-01
  • 2014-02-02
  • 2013-03-05
  • 2012-10-11
  • 2018-08-20
  • 2014-02-26
相关资源
最近更新 更多