Laravel Eloquent upsert无法识别UUID主键,触发插入报错
相关代码
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'], );
错误信息
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")
问题分析
- 错误日志显示当前实际使用SQLite连接,但你声明使用MySQL 8,这是核心矛盾点。SQLite的
ON CONFLICT逻辑虽支持upsert,但连接数据库与预期不符会导致索引校验、约束处理出现偏差。 - 若确认连接MySQL,需排查:
id字段是否已设置为主键且为唯一索引,符合Laravel upsert对识别字段的要求;- 数据库中是否真的存在对应
id的记录,否则upsert会执行插入操作,而你传入的数组缺少name、form_id等必填字段,触发非空约束错误。
解决方案
修正数据库连接配置:
检查.env文件及config/database.php,确保当前环境的数据库驱动为mysql,而非sqlite,并验证MySQL主机、端口、用户名、密码等参数正确。验证目标记录存在性:
执行SQL查询确认数据库中存在对应id的记录:SELECT * FROM form_pages WHERE id IN ( '23456693-9011-3c27-9556-408044349520', '66accb28-aff2-3f4c-9006-7de7a6512e30', 'b1964720-e475-3733-898b-d4084863dd24' );若记录不存在,需补充
name、form_id等必填字段后再执行upsert,或先创建对应记录。确认主键索引有效性:
检查form_pages表的id字段是否为主键,可通过MySQL命令行或可视化工具执行以下命令查看:SHOW INDEX FROM form_pages WHERE Key_name = 'PRIMARY';
内容的提问来源于stack exchange,提问作者Sebastian Sulinski

