laravel - Laravel firstOrCreate 方法抛出重复 ID 错误
问题描述
我正在我的 Laravel 项目中编写一个命令,该命令将类别插入数据库表,但取决于它们是否已经存在。
我调查了执行此操作的方法并遇到了firstOrCreate
方法,因此我在命令中编写了以下内容:
$comCats = new CommunicationsCategories();
$comCats->firstOrCreate(
['name' => 'Job Updates'], ['region_id' => 1]);
$comCats->firstOrCreate(
['name' => 'Alerts'], ['region_id' => 1]);
基本上,我需要在区域 ID 为 1 的communications_categories 表中创建这两个类别。 Job Updates 类别已经存在,因此它按预期跳过了它,但是当它尝试创建不存在的 Alerts 类别时,我得到了我的控制台中出现以下错误:
SQLSTATE [23505]:唯一违反:7 错误:重复键值违反唯一约束“communications_categories_pkey”
详细信息:键 (id)=(2) 已存在。(SQL: insert into "communications_categories" ("name", "region_id", "updated_at", "created_at") 值 (Alerts, 1, 2018-06-19 09:38:20, 2018-06-19 09:38 :20) 返回“id”)
似乎它正在尝试分配一个已经存在的主键 ID 2 - 但是表结构在主键上有一个 nextval,我认为它会采用最后添加的 ID 并在此之后创建一个新 ID。根据关于 Eloquent Inserts 的 Laravel 文档,这里没有提到必须规定实际的主键 id 本身,并且可填充的元素只有name
and region_id
。
对此的任何帮助表示赞赏,因为我对 Laravel 和 eloqent 数据库方法相当陌生。如果有帮助,我正在使用 PostgreSQL 数据库。
解决方案
另一个答案似乎假设您需要向您解释 firstOrCreate ,而实际上您实际上在 Laravel 框架中遇到了一个错误,并且还假设Key (id)=(2)
指的是region_id
而不是您的自动递增主键id
。
您很可能希望在communications_categories.name
.
您可以改为在 postgres 中使用此 SQL(假设您在名称上有唯一索引),这应该比 firstOrCreate 更可靠,但如果您计划将其他 laravel 功能与 firstOrCreate 一起使用(如观察者或更多查询构建器),它们的功能可能会丢失。
INSERT INTO communications_categories (name, region_id, created_at, updated_at)
VALUES ('Job Updates', 1, NOW(), NOW())
ON CONFLICT (name) DO
UPDATE SET region_id = excluded.region_id,
updated_at = NOW()
RETURNING *;
可以像这样使用:
$values = DB::select($sql); // will return Array of StdClass
returning *
如果您不需要这些值id
,也可以不使用。
DB::insert($sql); // will return true
如果您需要返回 Eloquent 对象,我建议您包含returning *
orreturning id
并将其传递给CommunicationsCategories::findOrFail($values[0]['id'])
. 将那个复杂的插入语句放入 Eloquent select 中可能需要做很多工作。Eloquent 还有一个叫做 hydrate 的函数,它可以在没有额外的 SQL 调用的情况下工作。
SQL 语句将插入所需的值,除非唯一约束存在冲突,否则它将通过更新将因冲突排除的值从插入应用到预先存在的行。
推荐阅读
- swift - “[String]”类型的值没有成员“replacingOccurrences”?
- docker - 没有这样的主机,我通过端口转发连接到服务器上的 kafka 代理
- angular - 从 Typescript 访问 Maven 属性
- java - 分组以找到最小流
- sql-server - 我在 SQL 中使用存储过程并将数据检索到我的数据网格视图中,但此时我遇到了问题
- tomcat - 我试图在 tomcat 上部署我的工作,但它一直向我显示这个错误:没有发现战争。部署中止
- node.js - Node.js | 覆盖设置器
- swift - Swift:将类方法分配给处理程序并处理弱自我
- javascript - 在 React 中无法访问 jQuery 插件
- java - 使用 Xpath 或 CSS 选择器单击带有 Selenium 的按钮