英文:
Laravel Eloquent upsert method does not recognise UUID primary key and generates insert statement
问题
我正在处理以下代码项目:
模式
Schema::create('form_pages', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->foreignUuid('form_id')
->index()
->constrained()
->onDelete('cascade');
$table->string('name');
$table->integer('sort');
$table->timestamps();
});
模型
class FormPage extends Model
{
use HasFactory;
use HasUuids;
/**
* {@inheritDoc}
*/
protected $fillable = [
'id',
'form_id',
'name',
'sort',
];
// ...
}
Eloquent upsert
FormPage::upsert(
[
[
"id" => "23456693-9011-3c27-9556-408044349520",
"sort" => 0,
],
[
"id" => "66accb28-aff2-3f4c-9006-7de7a6512e30",
"sort" => 2,
],
[
"id" => "b1964720-e475-3733-898b-d4084863dd24",
"sort" => 1,
],
],
['id'],
['sort'],
);
记录已存在于数据库中,唯一变化的是sort
列的值,但是Eloquent似乎无法识别它们并抛出以下错误:
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: form_pages.name (Connection: sqlite, SQL: insert into "form_pages" ("created_at", "form_id", "id", "sort", "updated_at") values (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 83e4ff46-eb0a-3587-ba75-832635c242b4, 0, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 30c09d4d-7418-31d7-ac1e-5371bcf12f67, 2, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 26eaa72b-ac62-3c54-aee9-7c0faf7392ce, 1, 2023-05-24 17:11:35) on conflict ("id") do update set "sort" = "excluded"."sort", "updated_at" = "excluded"."updated_at")
根据Laravel的文档:
除了SQL Server之外的所有数据库都要求
upsert
方法的第二个参数中的列具有“primary”或“unique”索引。此外,MySQL数据库驱动程序会忽略upsert
方法的第二个参数,并始终使用表的“primary”和“unique”索引来检测现有记录。
我在MySQL 8上运行此操作,但可能有些遗漏 - 非常感谢您的帮助。
英文:
I'm working on the project with the following code:
Schema
Schema::create('form_pages', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->foreignUuid('form_id')
->index()
->constrained()
->onDelete('cascade');
$table->string('name');
$table->integer('sort');
$table->timestamps();
});
Model
class FormPage extends Model
{
use HasFactory;
use HasUuids;
/**
* {@inheritDoc}
*/
protected $fillable = [
'id',
'form_id',
'name',
'sort',
];
// ...
}
Eloquent upsert
FormPage::upsert(
[
[
"id" => "23456693-9011-3c27-9556-408044349520",
"sort" => 0,
],
[
"id" => "66accb28-aff2-3f4c-9006-7de7a6512e30",
"sort" => 2,
],
[
"id" => "b1964720-e475-3733-898b-d4084863dd24",
"sort" => 1,
],
],
['id'],
['sort'],
);
The records already exist in the database and the only thing that changes is the value of the sort
column, but eloquent doesn't seem to recognise them and throws the following error
> Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: form_pages.name (Connection: sqlite, SQL: insert into "form_pages" ("created_at", "form_id", "id", "sort", "updated_at") values (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 83e4ff46-eb0a-3587-ba75-832635c242b4, 0, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 30c09d4d-7418-31d7-ac1e-5371bcf12f67, 2, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 26eaa72b-ac62-3c54-aee9-7c0faf7392ce, 1, 2023-05-24 17:11:35) on conflict ("id") do update set "sort" = "excluded"."sort", "updated_at" = "excluded"."updated_at")
According to Laravel's documentation:
> All databases except SQL Server require the columns in the second argument of the upsert method to have a "primary" or "unique" index. In addition, the MySQL database driver ignores the second argument of the upsert method and always uses the "primary" and "unique" indexes of the table to detect existing records.
I'm running this on MySQL 8, but perhaps there is something I missed - any help would be much appreciated.
答案1
得分: 0
It seems that I've forgotten that during the INSERT INTO ... ON DUPLICATE KEY UPDATE
statement, if you have any of the columns set as NOT NULL
, you have to provide the value for them in the first argument. After refactoring my code and adding the mandatory name
index, the upsert
statement now looks like this:
FormPage::upsert(
[
[
"id" => "23456693-9011-3c27-9556-408044349520",
'name' => 'Page 1',
"sort" => 0,
],
[
"id" => "66accb28-aff2-3f4c-9006-7de7a6512e30",
'name' => 'Page 2',
"sort" => 2,
],
[
"id" => "b1964720-e475-3733-898b-d4084863dd24",
'name' => 'Page 3',
"sort" => 1,
],
],
'id',
['sort'],
);
英文:
So it appears I've forgotten that during the INSERT INTO ... ON DUPLICATE KEY UPDATE
statement, if you have any of the columns set as NOT NULL
- you have to provide the value for them in the first argument (yep, error message says it loud enough). After refactoring my code and adding the mandatory name
index the upsert
statement now looks as follow
<!-- language: php -->
FormPage::upsert(
[
[
"id" => "23456693-9011-3c27-9556-408044349520",
'name' => 'Page 1',
"sort" => 0,
],
[
"id" => "66accb28-aff2-3f4c-9006-7de7a6512e30",
'name' => 'Page 2',
"sort" => 2,
],
[
"id" => "b1964720-e475-3733-898b-d4084863dd24",
'name' => 'Page 3',
"sort" => 1,
],
],
'id',
['sort'],
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论