Home > Back-end >  Why Laravel updateOrCreate() & upsert() both need argument to uniquely identify records?
Why Laravel updateOrCreate() & upsert() both need argument to uniquely identify records?

Time:12-03

Both updateOrCreate() & upsert() do the same thing, insert or update, I think they both generate SQL INSERT INTO ON DUPLICATE KEY. So I feel providing argument to uniquely identify records seems unnecessary.

Why do they need "the second argument lists the column(s) that uniquely identify records within the associated table." ?

The reason I can think of maybe in some case they do not generate the sql INSERT INTO ON DUPLICATE KEY so they may need arguments to uniquely identify records? But is this the case ?

CodePudding user response:

The updateOrCreate method find a one record matching the constraints passed as the first parameter and If a the record is found it will update the match with the attributes passed as the second parameter

If no matching record is found a it will be create record with both the constraints passed as the first parameter and the attributes passed as the second parameter.

CodePudding user response:

I check Laravel source and it confirms my doubt, for upsert(), refer to https://github.com/illuminate/database/blob/master/Query/Grammars/MySqlGrammar.php#L164

It generates sql insert on duplicate key update but the $uniqueBy argument is not used at all! (It shouldn't)

public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
{
    $sql = $this->compileInsert($query, $values).' on duplicate key update ';

    $columns = collect($update)->map(function ($value, $key) {
        return is_numeric($key)
            ? $this->wrap($value).' = values('.$this->wrap($value).')'
            : $this->wrap($key).' = '.$this->parameter($value);
    })->implode(', ');

    return $sql.$columns;
}

For updateOrCreate() it actually does NOT generate insert on duplicate key update but TWO sql clauses!!

https://github.com/illuminate/database/blob/master/Eloquent/Builder.php#L469

public function updateOrCreate(array $attributes, array $values = [])
{
    return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
        $instance->fill($values)->save();
    });
}

It is not easy to see the generated sql clause here but checking log, it is 2 clauses, one insert into and one update

  • Related