【问题标题】:FirstOrCreate making duplicatesFirstOrCreate 制作副本
【发布时间】:2020-08-25 19:35:18
【问题描述】:

在 Laravel 中,我正在运行以下命令

          PlateOrder::firstOrCreate(
            ['internal_order' => $internalOrder],
            ['internal_order' => $internalOrder,
            'order_number' => $order->order_number, 'product' => $line_item->name,
             'img_url' => $plate->template, 'template' => 1,
             'order_date' => $fixedDate,
             'qty' => $line_item->quantity,
             'custom1' => $firstLineTrimmed,
             'custom2' => $secondLineTrimmed,
             'created_at' => $order->created_at,
             'r' => $plate->r, 'g' => $plate->g, 'b' => $plate->b,
             'spacing' => $plate->spacing, 'top' => $plate->top ]
          );

使用 firstOrCreate 第一个参数 internal_order 将检查它是否存在。如果它存在,它会更新它,如果它不应该创建它。 但是在我的数据库中,它会导致它重复写入。

84826   142544  1425441HIGHMARK2    08-25-2020  HIGHMARK    VINYLS  NULL    NULL    Colorado Plate Hat - Flex Fit / L/XL (7 1/4" - 7 5/8") / Black FF   prt_Colorado.ai NULL    2   NULL    2020-08-25T05:47:14-07:00   1   0   77  41  38  86
84827   142544  1425441HIGHMARK2    08-25-2020  HIGHMARK    VINYLS  NULL    NULL    Colorado Plate Hat - Flex Fit / L/XL (7 1/4" - 7 5/8") / Black FF   prt_Colorado.ai NULL    2   NULL    2020-08-25T05:47:14-07:00   1   0   77  41  38  86

它创建一个相同的记录,除了 id。这是一个错误还是我错过了什么?

【问题讨论】:

  • 恭喜;你已经经历了你的第一个 mysql 竞态条件!为确保 100% 不会发生这种情况,我将在 internal_order 上的数据库中添加一个唯一键
  • 唯一键会在php端的什么地方生成?如果是这样,则此示例中的键“1425441HIGHMARK2”是唯一的。
  • firstOrCreate 不更新。 $internalOrder 变量实际上是什么??
  • 它包含一个唯一的字符串“1425441HIGHMARK2”,所以首先或创建应该检查它是否存在,如果找到它会做什么? @zahidhasanemon
  • 它只是返回匹配的记录..可能是你在别处做错了

标签: laravel


【解决方案1】:

如果您希望更新不存在的记录,您应该使用updateOrCreate,因为firstOrCreate 不会更新现有记录,而是将其返回。至于插入重复记录,它一定不会找到具有相同internal_order 值的记录。现有条目中是否有可能导致找不到它的尾随或前导空格?此外,没有理由重复第二个数组中的 internal_order 值,因为它会自动使用第一个数组中提供的值。

PlateOrder::updateOrCreate(
        ['internal_order' => $internalOrder],
        [
         'order_number' => $order->order_number,
         'product' => $line_item->name,
         'img_url' => $plate->template, 
         'template' => 1,
         'order_date' => $fixedDate,
         'qty' => $line_item->quantity,
         'custom1' => $firstLineTrimmed,
         'custom2' => $secondLineTrimmed,
         'created_at' => $order->created_at,
         'r' => $plate->r, 
         'g' => $plate->g, 
         'b' => $plate->b,
         'spacing' => $plate->spacing,
         'top' => $plate->top ]
      );

【讨论】:

  • 我检查过没有空格。 internal_order 是在现场生成的,所以它是独一无二的。
  • 我也不需要更新顺序,这就是我首先运行的原因,或者如果它存在就创建它只是跳过并且什么都不做。
  • 你可以尝试手动查询模型,看看是否可以通过内部订单列找到它,例如PlateOrder::whereInternalOrder($internalOrder)->first()
  • 是的,我做到了,这是相同的内部订单。我运行了一个查询,它返回了重复项。
  • 我提供的查询应该只返回一条记录,当你尝试它时,你只得到了一条记录,对吗?我只是想确保我们在同一页面上
【解决方案2】:

感谢@Derek Pollard,我对此进行了深入研究,这确实是一个 mysql 竞争条件。 为了解决这个问题,我最终将 internal_order 列设为唯一 ID。任何创建双精度的尝试都会出错。

这里有一些参考: https://github.com/spatie/first-or-create-racing-condition-demo https://gist.github.com/troatie/def0fba42fcfb70f873b7f033fbe255f

【讨论】:

    猜你喜欢
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 2012-08-19
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多