【问题标题】:Laravel 5 updating single row limit doesn't workLaravel 5 更新单行限制不起作用
【发布时间】:2016-04-26 22:59:39
【问题描述】:

我需要更新 db (PostgreSQL) 中的单个匹配记录,但 Limit 方法不适用于 Update 方法。此代码将更新所有匹配 Where 条件的记录,而不是单个记录。

DB::table("records")
  ->where('need_moderate','=','no')
  ->where('locked_per_time','<',$date_now->format("Y-m-d H:i:s"))
  ->limit(1)
  ->update(["locked_per_time"=>$locked_per->format("Y-m-d H:i:s"),'locked_by'=>$mdkey]);

如何解决这个问题,以便只更新单个记录?

【问题讨论】:

    标签: php postgresql laravel limit


    【解决方案1】:

    OracleMySQL 更新语句不同,不能直接在PostgreSQL update statements 上使用LIMIT。因此,将 limit(1) 方法链接到 Query Builder 实例没有任何作用,因为 Laravel 的 PostgresGrammar 类中负责编译查询的 compileUpdate 方法只编译 where 语句。

    但是,您可以通过使用子查询的条件来克服这个问题,该子查询仅返回将要更新的一行。像这样的东西应该可以工作:

    DB::table("records")->whereIn('id', function ($query) use ($date_now) {
        $query->from('records')
              ->select('id')
              ->where('need_moderate', '=', 'no')
              ->where('locked_per_time', '<', $date_now->format("Y-m-d H:i:s"))
              ->limit(1);
    })->update(["locked_per_time" => $locked_per->format("Y-m-d H:i:s"), 'locked_by' => $mdkey]);
    

    whereIn('id', ...) 条件假定您的表有一个名为 id 的列,该列可用作唯一标识符,因此它可以在子查询中找到与您的条件匹配的第一行。

    【讨论】:

    • 不幸的是代码不能正常工作。即使有 2-4 个线程,相同的记录仍然会发布到不同的线程。我假设第二个线程的内部选择在第一个线程更新之前执行。我将不胜感激。
    • 我不确定我是否理解。请提供更详细的背景信息,说明您希望更新过程如何工作。
    • 对于每个查询,我们通过更改其locked_per_time 来更新记录。在此之后,我们从该记录中获取数据。虽然当前日期小于locked_per_time,但该记录不应该对其他线程可用,并且永远不会被占用两次。但是,即使使用您在运行多个线程时提供的代码,它们也会在第一个线程执行 Updatelocked_per_time 之前以某种方式同时获得相同的记录
    • 我也想过Pessimistic lock,但我不确定它是否有助于同时处理大量请求的多线程。我还考虑了对 db co 的原始请求,因为它肯定是单笔交易,你做过类似的事情吗?这两种选择的优缺点是什么?谢谢
    猜你喜欢
    • 1970-01-01
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 2016-01-30
    • 2023-03-13
    • 2016-12-07
    • 1970-01-01
    相关资源
    最近更新 更多