15

Tengo el siguiente en mi archivo de migraciónrieles singularidad de restricción y su adecuación índice único db para la columna nula

def self.up 
    create_table :payment_agreements do |t| 
     t.boolean :automatic, :default => true, :null => false 
     t.string  :payment_trigger_on_order 
     t.references :supplier 
     t.references :seller 
     t.references :product 
     t.timestamps 
    end 
    end 

Quiero asegurar que si se especifica un product_id es único pero también quiere permitir nula por lo Tengo el siguiente en mi modelo:

validates :product_id, 
      :uniqueness => true, 
      :allow_nil => true 

Funciona muy bien pero entonces habría que añadir un índice para el archivo de migración

add_index :payment_agreements, :product_id, :unique => true 

Obviamente, lanzará una excepción cuando se inserten dos valores nulos para product_id. Simplemente podría omitir el índice en la migración, pero existe la posibilidad de que obtenga dos acuerdos de pago con el mismo product_id que se muestra aquí: Concurrency and integrity

Mi pregunta es cuál es la mejor/la forma más común de lidiar con esto problema

+0

Esta pregunta es similar a http://stackoverflow.com/questions/191421/how-to-create-a-unique-index-on-a-null-column – x1a4

+1

validates_uniqueness_of: product_id,: si = > lambda {! self.product_id.nil? } – user386660

Respuesta

0

Algunos sistemas de bases de datos importantes no permiten que un índice único contenga múltiples valores NULL: el único se aplica tanto a los valores NULL como a los que no son NULL. Hay formas de evitar esto en el nivel de la base de datos (por ejemplo, activadores o una columna calculada; consulte link text).

Puede solucionar esto en un nivel de aplicación y colocar una validación que compruebe la exclusividad si el product_id no es nulo.

validate :enforce_unique_product_id 
def enforce_unique_product_id 
    if (!self.product_id.nil? && 
     PaymentAgreement.exists?(:conditions=>['product_id = ?', self.product_id])) 
    errors.add_to_base('There is already an agreement with product id " + 
         self.product_id) 
    end 
end 

(Actualización: Como ha señalado zed_0xff, MySQL permite múltiples valores NULL en un índice UNIQUE en los motores de almacenamiento más comúnmente utilizados.)

11

que depende de su servidor db. como para MySQL:

un índice único crea una restricción de tal manera que todos los valores del índice deben ser distintos. Se produce un error si intenta agregar una nueva fila con un valor de clave que coincida con una fila existente. Esta restricción no se aplica a valores NULL excepto para el motor BDB storage . Para otros motores, un índice ÚNICO permite valores NULL múltiples para columnas que pueden contener NULL.

Cuestiones relacionadas