Una migración para agregar restricción única a una combinación de columnas


Lo que necesito es una migración para aplicar una restricción única a una combinación de columnas. es decir, para una tabla people, una combinación de first_name, last_Name y Dob debe ser único.

Author: Arslan Ali, 2010-07-30

5 answers

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

 204
Author: Robert Speicher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-30 09:45:49

Según howmanyofme.com, "Hay 46.427 personas llamadas John Smith" solo en los Estados Unidos. Eso son unos 127 años de días. Como esto es mucho más de la vida media de un ser humano, esto significa que un choque DOB es matemáticamente cierto.

Todo lo que estoy diciendo es que esa combinación particular de campos únicos podría conducir a la frustración extrema del usuario/cliente en el futuro.

Considere algo que sea realmente único, como un número de identificación nacional, si adecuado.

(Me doy cuenta de que llego muy tarde a la fiesta con esta, pero podría ayudar a los futuros lectores.)

 19
Author: A Fader Darkly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-09 11:23:46

Es posible que desee agregar una restricción sin un índice. Esto dependerá de la base de datos que esté utilizando. A continuación se muestra un ejemplo de código de migración para Postgres. (tracking_number, carrier) es una lista de las columnas que desea usar para la restricción.

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

Hay diferentes restricciones que puede agregar. Lea los documentos

 15
Author: Josh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-24 19:24:03

Hola Puede agregar un índice único en su migración a las columnas por ejemplo

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

O índices únicos separados para cada columna

 7
Author: Bohdan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-30 09:44:50

En el ejemplo típico de una tabla de unión entre usuarios y publicaciones:

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

Intentar crear dos registros similares arrojará un error de base de datos (Postgres en mi caso):

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"

Por ejemplo, haciendo eso:

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

Ejemplo completamente ejecutable: https://gist.github.com/Dorian/9d641ca78dad8eb64736173614d97ced

db/schema.rb generado: https://gist.github.com/Dorian/a8449287fa62b88463f48da986c1744a

 2
Author: Dorian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 22:07:02