ecto 中的复合主键

scr*_*ipt 1 elixir ecto

在迁移中,我们可以添加多个主键,它们都充当复合主键。我的表中有四个字段,其中三个是主键并且工作正常。当我尝试添加新的迁移并将第四列设为主键时。Postgres 给了我这个错误。

\n\n
   (Postgrex.Error) ERROR 42P16 (invalid_table_definition) multiple primary keys for table "rooms_units" are not allowed\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的新迁移:

\n\n
alter table(:rooms_units) do\n  modify(:date_to, :utc_datetime, primary_key: true)  \nend \n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我将其添加到原始迁移中,则效果很好。

\n\n

这是我原来的迁移:

\n\n
  create table(:rooms_units, primary_key: false) do\n   add(:room_id, references(:rooms), null: false, primary_key: true)\n   add(:unit_id, references(:units), null: false, primary_key: true)\n   add(:date_from, :utc_datetime, null: false, primary_key: true)\n   add(:date_to, :utc_datetime, null: false, default: fragment("\'infinity\'::timestamp"))\n  end\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我在 date_to 列中添加 Primary_key: true ,则效果很好。迁移成功运行。

\n\n

所以我想语法是正确的。但它不会在新的迁移中\xe2\x80\x99 工作。

\n\n

有什么建议或解决方法吗?\n谢谢。

\n

fhd*_*sni 5

您有一个主键,它恰好是一个复合键。

dbname=# \d+ rooms_units
   ...

Indexes:
"rooms_units_pkey" PRIMARY KEY, btree (room_id, unit_id, date_from)

   ...
Run Code Online (Sandbox Code Playgroud)

无法添加另一个主键。每个表只能有一个主键(这就是pk的定义)。但您可以删除当前主键并创建一个新主键。在 Ecto 中可能有更优雅的方法来做到这一点,但这可行

defmodule MyApp.Repo.Migrations.AlterRoomsUnits do
  use Ecto.Migration

  def change do
    drop(constraint("rooms_units", "rooms_units_pkey"))

    alter table(:rooms_units) do
      modify(:room_id, :integer, primary_key: true)
      modify(:unit_id, :integer, primary_key: true)
      modify(:date_from, :utc_datetime, primary_key: true)
      modify(:date_to, :utc_datetime, primary_key: true)
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

现在我们有了一个新的复合主键

dbname=# \d+ rooms_units
   ...

Indexes:
"rooms_units_pkey" PRIMARY KEY, btree (room_id, unit_id, date_from, date_to)

   ...
Run Code Online (Sandbox Code Playgroud)