【问题标题】:Ecto unique constraint error on pkeypkey 上的 Ecto 唯一约束错误
【发布时间】:2018-03-10 14:11:04
【问题描述】:

我在尝试插入新房间时开始收到以下错误

** (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

【问题讨论】:

标签: postgresql phoenix-framework ecto postgrex


【解决方案1】:

我找到了发生这种情况的原因。

我忘记包含在原始描述中的一个重要说明是,这是在开发环境中工作时发生的。

this answer 相关。我之前使用 Postico 手动插入了一些数据,其中必须明确包含 id。那时 pkey 序列没有更新,后来导致设置了重复的 id。

【讨论】:

    【解决方案2】:

    tl;博士

    替换

    |> unique_constraint(:name)
    

    |> unique_constraint(:name, name: :rooms_pkey)
    

    ==============

    unique_constraint 并没有完全按照您的预期工作。

    在您发布的示例中,原子 :name 被传递到 unique_constraint。引用文档:

    默认情况下,约束名称是从表+字段中推断出来的。 复杂情况下可能需要明确要求

    这就是变更集定义:rooms_name_index 的原因,即使实际索引是:rooms_pkey。您必须显式地使用 :name 选项以避免这种默认行为。

    【讨论】:

      猜你喜欢
      • 2018-11-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多