web-dev-qa-db-fra.com

Une migration pour ajouter une contrainte unique à une combinaison de colonnes

Ce dont j'ai besoin, c'est d'une migration pour appliquer une contrainte unique à une combinaison de colonnes. c'est-à-dire pour une table people, une combinaison de first_name, last_Name et Dob devraient être uniques.

130
rangalo

add_index :people, [:firstname, :lastname, :dob], :unique => true

229
Robert Speicher

Selon howmanyofme.com, "il y a 46 427 personnes nommées John Smith" rien qu'aux États-Unis. C'est environ 127 ans de jours. Comme cela dépasse largement la durée de vie moyenne d'un être humain, cela signifie qu'un affrontement entre la date de naissance et la date de naissance est mathématiquement certain.

Tout ce que je dis, c'est que cette combinaison particulière de champs uniques pourrait conduire à une frustration extrême des utilisateurs/clients à l'avenir.

Pensez à quelque chose qui est réellement unique, comme un numéro d’identification national, le cas échéant.

(Je réalise que je suis très en retard à la fête avec celui-ci, mais cela pourrait aider les futurs lecteurs.)

22
A Fader Darkly

Vous souhaiterez peut-être ajouter une contrainte sans index. Cela dépend de la base de données que vous utilisez. Vous trouverez ci-dessous un exemple de code de migration pour Postgres. (tracking_number, carrier) est une liste des colonnes que vous souhaitez utiliser pour la contrainte.

class AddUniqeConstraintToShipments < ActiveRecord::Migration
  def up
    execute <<-SQL
      alter table shipments
        add constraint shipment_tracking_number unique (tracking_number, carrier);
    SQL
  end

  def down
    execute <<-SQL
      alter table shipments
        drop constraint if exists shipment_tracking_number;
    SQL
  end
end

Il existe différentes contraintes que vous pouvez ajouter. Lire la documentation

18
Josh

Salut Vous pouvez ajouter un index unique dans votre migration aux colonnes par exemple

add_index(:accounts, [:branch_id, :party_id], :unique => true)

ou des index uniques séparés pour chaque colonne

7
Bohdan

Dans l'exemple typique d'une table de jointure entre utilisateurs et publications:

create_table :users
create_table :posts

create_table :ownerships do |t|
  t.belongs_to :user, foreign_key: true, null: false
  t.belongs_to :post, foreign_key: true, null: false
end

add_index :ownerships, [:user_id, :post_id], unique: true

Essayer de créer deux enregistrements similaires provoquera une erreur de base de données (Postgres dans mon cas):

ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_ownerships_on_user_id_and_post_id"
DETAIL:  Key (user_id, post_id)=(1, 1) already exists.
: INSERT INTO "ownerships" ("user_id", "post_id") VALUES ($1, $2) RETURNING "id"

par exemple. Faisant cela:

Ownership.create!(user_id: user_id, post_id: post_id)
Ownership.create!(user_id: user_id, post_id: post_id)

Exemple entièrement exécutable: https://Gist.github.com/Dorian/9d641ca78dad8eb64736173614d97ced

db/schema.rb généré: https://Gist.github.com/Dorian/a8449287fa62b88463f48da986c1744a

4
Dorian