尝试插入新房间时,我开始收到以下错误
** (Ecto.ConstraintError) constraint error when attempting to insert struct:
* unique: rooms_pkey
If you would like to convert this constraint into an error, please
call unique_constraint/3 in your changeset and define the proper
constraint name. The changeset defined the following constraints:
* unique: rooms_name_index
主键不应该自动递增吗?什么会突然发生这个错误?插入是作为multi的一部分完成的,相关部分是:
|> Multi.insert(:room, Room.changeset(%Room{}, %{name: "service-user-care-team:" <> Integer.to_string(user.id)}))
有关其他参考,请参阅我的架构,包括变更集
schema "rooms" do
field :name, :string
many_to_many :users, App.User, join_through: "user_rooms", on_delete: :delete_all
has_many :messages, App.Message
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name])
|> validate_required([:name])
|> unique_constraint(:name)
end
这是迁移
defmodule App.Repo.Migrations.CreateRoom do
use Ecto.Migration
def change do
create table(:rooms) do
add :name, :string, null: false
timestamps()
end
create unique_index(:rooms, [:name])
end
end
答案 0 :(得分:1)
tl; dr
替换
|> unique_constraint(:name)
与
|> unique_constraint(:name, name: :rooms_pkey)
==============
unique_constraint不能完全按照您的期望工作。
在您发布的示例中,原子:name
被传递到unique_constraint中。引用文档:
默认情况下,约束名称是从表+字段中推断出来的。 对于复杂的情况可能会明确要求
这就是为什么即使实际索引为:rooms_name_index
,变更集也定义:rooms_pkey
的原因。您必须明确地使用:name
选项,以避免ecto中的这种默认行为。
答案 1 :(得分:0)
我发现为什么会这样。
我忘了在原始描述中包含的一个重要说明是,这是在开发环境中工作时发生的。
它与this answer有关。我之前曾使用Postico手动插入一些数据,其中必须明确包含id。此时pkey序列未更新,后来导致设置了重复的id。