Situation
I have a database table products , its migration is something like that
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('reference')->unique();
$table->unsignedBigInteger('required_field');
$table->string('unrequired_field')->nullable();
$table->timestamps();
$table->softDeletes();
});
I have some data
| id | reference | required_field | unrequired_field |
|-----|-----------|----------------|------------------|
| 1 | ABCD | 500 | "some text" |
| 2 | EFGH | 100 | NULL |
I have a function that updates my database's unrequired_field without specifying my required_field and may also insert new records (specifying all the fields)
Scenario 1
What I expected
Product::upsert([
[
'reference' => "ABCD",
'unrequired_field' => "new text"
],
[
'reference' => "EFGH",
'unrequired_field' => "new text"
]
], ['reference'], ['unrequired_field']);
I was hoping upsert here just updates my table to become
| id | reference | required_field | unrequired_field |
|-----|-----------|----------------|------------------|
| 1 | ABCD | 500 | "new text" |
| 2 | EFGH | 100 | "new text" |
What I got
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1364 Field 'required_field' doesn't have a default value (SQL: insert into `products` (.....
As you can see here, upsert tried to INSERT even though reference exists in the database, it should just update !
Scenario 2
What I expected
Product::upsert([
[
'reference' => "EFGH",
'unrequired_field' => "new text"
],
[
'reference' => "IJKL",
'required_field' => 200,
'unrequired_field' => "new text"
]
], ['reference'], ['unrequired_field']);
I was hoping upsert here would update row number 2 and insert a new row to my table to become
| id | reference | required_field | unrequired_field |
|-----|-----------|----------------|------------------|
| 1 | ABCD | 500 | "some text" |
| 2 | EFGH | 100 | "new text" |
| 3 | IJKL | 200 | "new text" |
What I got
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1364 Field 'required_field' doesn't have a default value (SQL: insert into `products` (....
Same error, it tries only to insert all lines
Scenario 3
What I expected
Product::upsert([
[
'reference' => "IJKL",
'required_field' => 200,
'unrequired_field' => "new text"
]
], ['reference'], ['unrequired_field']);
I was hoping upsert here would insert a new row to my table to become
| id | reference | required_field | unrequired_field |
|-----|-----------|----------------|------------------|
| 1 | ABCD | 500 | "some text" |
| 2 | EFGH | 100 | NULL |
| 3 | IJKL | 200 | "new text" |
What I got
This worked fine, as upsert generated an INSERT that correctly works
Question
Am I misunderstanding the concept of upserts or is it a bug with Laravel's implementation of upsert ? If so, how can we fix it ?