PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Rails каква е разликата в уникалния индекс и validates_uniqueness_of

Ето разликата между уникален индекс и validates_uniqueness_of

Това е корекция, която позволява на ActiveRecord да идентифицира генерирани от db грешки за уникални нарушения на ограниченията. Например, той кара следното да работи, без да декларира validates_uniqueness_of:

create_table "users" do |t|
  t.string   "email",   null: false
end
add_index "users", ["email"], unique: true

class User < ActiveRecord::Base
end

User.create!(email: '[email protected]')
u = User.create(email: '[email protected]')
u.errors[:email]
=> "has already been taken"

Предимствата са бързина, лекота на използване и пълнота --

Скорост

С този подход не е необходимо да правите търсене в db, за да проверите за уникалност при запазване (което понякога може да бъде доста бавно, когато индексът е пропуснат -- https://rails.lighthouseapp.com/projects/8994/tickets/2503-validate.. . ). Ако наистина ви е грижа за валидирането на уникалността, така или иначе ще трябва да използвате ограничения на базата данни, така че базата данни да потвърди уникалността независимо от всичко и този подход премахва допълнителна заявка. Проверката на индекса два пъти не е проблем за DB (той се кешира втория път), но запазването на DB от приложението е голяма победа.

Лекота на използване

Като се има предвид, че така или иначе трябва да имате db ограничения за истинска уникалност, този подход ще позволи всичко да се случи автоматично, след като db ограниченията са налице. Все още можете да използвате validates_uniqueness_of, ако желаете.

Пълнота

validates_uniqueness_of винаги е бил малко хак -- не може да се справи правилно с условията на състезание и води до изключения, които трябва да се обработват с помощта на донякъде излишна логика за обработка на грешки. (Вижте раздела „Едновременност и интегритет“ в http://api.rubyonrails .org/classes/ActiveRecord/Validations/ClassMe... )

валидира_уникалността_на не е достатъчно, за да гарантира уникалността на стойността. Причината за това е, че в производството множество работни процеси могат да причинят състезателни условия:

  1. Две едновременни заявки се опитват да създадат потребител с едно и също име (и ние искаме потребителските имена да са уникални)

  2. Заявките се приемат на сървъра от два работни процеса, които сега ще ги обработват паралелно

  3. И двете заявки сканират таблицата с потребители и виждат, че името е налично

  4. И двете заявки преминават проверка и създават потребител с привидно налично име

За по-ясно разбиране, моля, проверете това

Ако създадете уникален индекс за колона, това означава, че сте сигурни, че таблицата няма да има повече от един ред със същата стойност за тази колона. Използването само на validates_uniqueness_of validation във вашия модел не е достатъчно за налагане на уникалност, защото може да има едновременни потребители, които се опитват да създадат едни и същи данни.

Представете си, че двама потребители се опитват да регистрират акаунт с един и същ имейл, където сте добавили validates_uniqueness_of :email във вашия потребителски модел. Ако натиснат бутона „Регистрация“ едновременно, Rails ще потърси този имейл в таблицата с потребители и ще отговори, че всичко е наред и че е добре да запазите записа в таблицата. След това Rails ще запише двата записа в потребителската таблица с един и същ имейл и сега имате наистина скапан проблем, с който трябва да се справите.

За да избегнете това, трябва да създадете уникално ограничение и на ниво база данни:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :email
      ...
    end
    
    add_index :users, :email, unique: true
  end
end

Така че чрез създаването на уникалния индекс index_users_on_email получавате две много добри предимства. Цялост на данните и добра производителност, тъй като уникалните индекси обикновено са много бързи.

Ако поставите unique:true в таблицата си с публикации за user_id, това няма да позволи въвеждането на дублиращи се записи със същия user_id.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Конкатениране на множество редове в масив с SQL на PostgreSQL

  2. Използвайте резултата от pg_dump като вход за pg_restore

  3. ValueError uподдържан формат на знака 'd' с psycopg2

  4. Създайте уникален индекс на неуникална колона

  5. Вмъкнете цялата стойност на масива DataTable в таблицата postgreSQL