【问题标题】:How can I update all rows except the last one?如何更新除最后一行之外的所有行?
【发布时间】:2016-07-13 18:41:16
【问题描述】:

这是我的脚本:

try{

    $dbh_conn->beginTransaction();

    $user_id = $_POST['iuser_id'];
    $token   = hash('sha512', bin2hex(openssl_random_pseudo_bytes(16)).$user_id);

    $stm = $dbh_conn
    ->prepare("INSERT INTO resend_pass(user_id, token, date_time)
                SELECT ?, ?, unix_timestamp()
                FROM dual
                WHERE NOT EXISTS( SELECT count(*) AS num_week,
                                         COALESCE(sum(date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1  day))),0)  as num_day,
                                         COALESCE(sum(date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1  hour))),0) as num_hour,
                                         COALESCE(sum(date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 minute))),0) as num_1min
                                    FROM resend_pass
                                   WHERE user_id   = ?  
                                     AND date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 WEEK))
                                  HAVING num_week > 11 OR num_day > 5 OR num_hour > 3 OR num_1min > 0 );");
    $stm->execute(array($user_id, $token, $user_id));

    // no row inserted (either there is lots of reuqests or duplicate token (this one has very low possibility))
    if ( !$stm->rowCount() ) { throw new Exception('something is wrong'); }

    $stmt = $dbh_conn->prepare("UPDATE resend_pass SET active = 0 WHERE user_id = ? AND {all rows except the last one}");
    $stmt->execute($user_id);

    $dbh_conn->commit();

    /* sending $token for that email  here  */

    $_SESSION["TopMSG"] = "<div class='msg_success'>
                            ایمیل با موفقیت ارسال شد 
                            <span>
                            - جهت انتخاب رمز عبور جدید
                            </span>
                            </div>";
    header('location: ../login');
    exit;

} catch(Exception $e) {

    $dbh_conn->rollBack();

    $_SESSION["TopMSG"] = "<div class='msg_success'>$e</div>";
    header('location: ../login');
    exit;

}

请关注这一行:

$stmt = $dbh_conn->prepare("UPDATE resend_pass SET active = 0 WHERE user_id = ? AND {all rows except the last one}");

我如何告诉它设置除了刚才插入的最后一行之外的所有行?

【问题讨论】:

  • 该表是否有一个 auto_increment 主键列?INSERT 操作是否总是导致插入一行?
  • 表格没有“最后”的概念,这里的真正标准是什么?
  • 如果您要排除的 ID 是您插入的最后一行的自动增量,您可以在查询中直接使用 MySQL 函数 LAST_INSERT_ID() 例如AND xxx != LAST_INSERT_ID()。无需使用PHP即可获取。

标签: php mysql sql pdo


【解决方案1】:

http://php.net/manual/en/pdo.lastinsertid.php

您可以获取最后插入的 ID 并在 where 子句中使用它。

$lastId = $dbh_conn->lastInsertId();
$stmt = $dbh_conn->prepare("UPDATE resend_pass SET active = 0 WHERE user_id = ? AND [whatever column is used for resend_pass id] <> ?");
$stmt->execute(array($user_id, $lastId));

【讨论】:

    【解决方案2】:

    如果您的表中有一个自动增量列,您可以获取最后插入行的 id 并将其添加到第二个查询的 WHERE 子句中。

    【讨论】:

      【解决方案3】:

      我不知道你如何看待“最后”。它可能是最大日期,可能是最小日期,可能是最大 ID,可能是最小 ID。在下面的示例中,我使用 min date_time 字段。用你需要的替换子查询

       UPDATE resend_pass 
          SET active = 0 
        WHERE user_id = ? AND date_time <> 
         (select min(date_time) 
            from resend_pass
          where user_id = ?) 
      

      【讨论】:

      • INSERT 语句之前写这个查询UPDATE resend_pass SET active = 0 WHERE user_id = ? 怎么样?
      【解决方案4】:

      如果我很好地理解了您的问题,那么我认为您可以使用您的 PDO 连接获取最后插入的行的 ID

      $lastId = $dbh_conn->lastInsertId();
      

      然后在sql查询中使用$lastId的值。

      【讨论】:

      • 这和@caius 的回答完全一样
      【解决方案5】:

      也许移动以下语句更容易:

      $stmt = $dbh_conn->prepare("UPDATE resend_pass SET active = 0 WHERE user_id = ?");
      

      在Insert 上面,所以不需要更改新记录。并且不再需要 AND 条件

      问候

      【讨论】:

      • 那条语句不是有效的 sql,所以我怀疑它会起作用——也许你需要稍微改变一下语句?
      • 是的,它需要一些返工,我已经相应地更新了我的答案。
      猜你喜欢
      • 1970-01-01
      • 2012-11-07
      • 1970-01-01
      • 2010-09-13
      • 2017-02-12
      • 1970-01-01
      • 2011-01-16
      • 2010-09-23
      • 1970-01-01
      相关资源
      最近更新 更多