web-dev-qa-db-fra.com

Création d'une contrainte unique sur deux colonnes ensemble dans Ecto

Comment créer un index unique sur deux colonnes dans Ecto, ce qui correspondrait à ceci:

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

?

28
2083

Un petit suivi de la réponse de Patrick

Utiliser uniquement create unique_index sur votre modèle générera finalement une exception au lieu de vous donner une erreur.

Pour obtenir une erreur, ajoutez une contrainte sur votre ensemble de modifications, mais en tant que paramètre, vous pouvez donner le nom d'index créé par unique_index.

Donc dans votre fichier de migration:

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

Puis dans votre changeset:

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

Vous pouvez créer un index unique sur plusieurs lignes avec

create unique_index(:some_table, [:col1, :col2])

Je suppose que si vous voulez avoir des clés composites, vous devez utiliser execute/1 pour exécuter votre SQL manuellement. Je ne sais pas si les clés composites fonctionnent bien avec Ecto, je reste généralement avec l'ID série standard par table.

Si vous optez pour l'approche clé composite, je pense que le NOT NULL les contraintes ne sont pas nécessaires. La clé composite doit déjà imposer que les colonnes ne sont pas nulles.

12
Patrick Oscity

unique_index ne créerait pas une clé primaire composite comme le montre l'exemple de la question. Cela crée une contrainte unique.

Si vous souhaitez créer une clé primaire composite (remarque: non recommandé lorsque vous travaillez avec Ecto), il y a plus d'informations ici :

Migration:

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
      ...

Schéma:

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
    ...

Dans la plupart des cas unique_index c'est ce que vous voulez.

4
Oskar