Создание уникального ограничения на два столбца вместе в Ecto
Как создать уникальный индекс в двух столбцах в Ecto, который соответствовал бы этому:
CREATE TABLE someTable (
col1 int NOT NULL,
col2 int NOT NULL,
primary key (col1, col2)
)
?
Ответы
Ответ 1
Вы можете создать уникальный индекс в нескольких строках с помощью
create unique_index(:some_table, [:col1, :col2])
Я полагаю, что если вы хотите иметь составные клавиши, вам нужно использовать execute/1
для запуска SQL вручную. Не уверен, насколько хорошо составные клавиши работают с Ecto, хотя я обычно придерживаюсь стандартного серийного идентификатора в таблице.
Если вы хотите использовать подход с комбинированным ключом, я думаю, что ограничения NOT NULL
не нужны. Компонентный ключ должен уже обеспечивать, чтобы столбцы не были нулевыми.
Ответ 2
Небольшое продолжение ответа Патрика
Использование только 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
Ответ 3
unique_index
будет не создавать составной первичный ключ, как показано в примере вопроса. Это создает уникальное ограничение.
Если вы хотите создать составной первичный ключ (обратите внимание: не рекомендуется при работе с 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
- это то, что вы хотите.