在 Ecto 中一起创建两列的唯一约束

问题描述 投票:0回答:4

如何在 Ecto 中的两列上创建唯一索引,这对应于:

CREATE TABLE someTable (
    col1 int NOT NULL,
    col2 int NOT NULL,
    primary key (col1, col2)
)

elixir ecto
4个回答
132
投票

帕特里克的回答的一些后续

仅在模型上使用 create unique_index 最终将引发异常而不是给您错误。

要获得错误,请在变更集上添加约束,但作为参数,您可以给出由 unique_index 创建的索引名称。

因此在您的迁移文件中:

create unique_index(:your_table, [:col1, :col2], name: :your_index_name)

然后在你的变更集中:

def changeset(model, param \\ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)
  |> unique_constraint(:name_your_constraint, name: :your_index_name)
end

13
投票

您可以使用

跨多行创建唯一索引
create unique_index(:some_table, [:col1, :col2])

我想如果你想要复合键,你需要使用

execute/1
手动运行 SQL。虽然不确定复合键与 Ecto 的配合效果如何,但我通常只坚持使用每个表的标准序列 ID。

如果您应该采用复合键方法,我认为

NOT NULL
约束是不必要的。组合键应该已经强制列不为空。


7
投票

unique_index/3
不会创建复合主键,如问题示例中所示。它确实创建了一个独特的约束。

如果您确实想创建复合主键(注意:在使用 Ecto 时不建议),

这里有更多信息

迁移:

defmodule HelloPhoenix.Repo.Migrations.CreatePlayer do use Ecto.Migration def change do create table(:players, primary_key: false) do add :first_name, :string, primary_key: true add :last_name, :string, primary_key: true add :position, :string add :number, :integer ...

架构:

defmodule HelloPhoenix.Player do use Ecto.Schema @primary_key false schema "players" do field :first_name, :string, primary_key: true field :last_name, :string, primary_key: true field :position, :string field :number, :integer ...
在大多数情况下,

unique_index/3

就是您想要的。
    


4
投票
这是一篇旧帖子,但我今天遇到了这个。 请记住,唯一的

constraint 与唯一的 index 不同(至少不是在 PostGres 的所有版本中——这方面似乎有一些变化)。在 Ecto 中,目前添加非索引约束的唯一方法似乎是在迁移中使用 execute/1

,例如 

defmodule YourMigration do use Ecto.Migration def up do execute(""" ALTER TABLE pre.yourtable ADD CONSTRAINT something UNIQUE (something) """) end def down do execute(""" ALTER TABLE pre.yourtable DROP CONSTRAINT something """) end end
    
© www.soinside.com 2019 - 2024. All rights reserved.