sql >> Databáze >  >> RDS >> PostgreSQL

Uvádí, jaký je rozdíl v jedinečném indexu a validates_uniqueness_of

Zde je rozdíl mezi jedinečným indexem a validates_uniqueness_of

Toto je oprava, která umožní ActiveRecord identifikovat chyby generované db pro jedinečná porušení omezení. Například umožňuje následující práci bez deklarace 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"

Výhody jsou rychlost, snadné použití a úplnost --

Rychlost

S tímto přístupem nemusíte provádět vyhledávání v db, abyste zkontrolovali jedinečnost při ukládání (což může být někdy docela pomalé, když chybí index -- https://rails.lighthouseapp.com/projects/8994/tickets/2503-validate.. . ). Pokud vám opravdu záleží na ověření jedinečnosti, budete muset stejně použít omezení databáze, takže databáze ověří jedinečnost bez ohledu na to, co a tento přístup odstraní další dotaz. Kontrola indexu dvakrát není pro DB problém (ukládá se do mezipaměti již podruhé), ale uložení zpáteční cesty DB z aplikace je velká výhra.

Snadné použití

Vzhledem k tomu, že pro skutečnou jedinečnost stejně musíte mít omezení db, tento přístup umožní, aby se vše stalo automaticky, jakmile budou omezení db na místě. Pokud chcete, stále můžete použít validates_uniqueness_of.

Úplnost

validates_uniqueness_of byl vždy tak trochu hack – neumí správně zacházet se závodními podmínkami a výsledkem jsou výjimky, které je třeba řešit pomocí poněkud nadbytečné logiky zpracování chyb. (Viz část „Souběh a integrita“ v http://api.rubyonrails .org/classes/ActiveRecord/Validations/ClassMe... )

validates_uniqueness_of nestačí k zajištění jedinečnosti hodnoty. Důvodem je to, že ve výrobě může více pracovních procesů způsobit závody:

  1. Dva souběžné požadavky se pokusí vytvořit uživatele se stejným jménem (a my chceme, aby uživatelská jména byla jedinečná)

  2. Požadavky jsou na serveru přijímány dvěma pracovními procesy, které je nyní budou zpracovávat paralelně

  3. Oba požadavky prohledají tabulku uživatelů a zjistí, že jméno je k dispozici

  4. Oba požadavky projdou ověřením a vytvoří uživatele se zdánlivě dostupným jménem

Pro lepší pochopení zkontrolujte toto

Pokud pro sloupec vytvoříte jedinečný index, znamená to, že máte zaručeno, že tabulka nebude mít pro daný sloupec více než jeden řádek se stejnou hodnotou. Použití pouze validates_uniqueness_of validace ve vašem modelu nestačí k vynucení jedinečnosti, protože mohou existovat souběžní uživatelé, kteří se snaží vytvořit stejná data.

Představte si, že se dva uživatelé pokusí zaregistrovat účet se stejným e-mailem, kam jste do svého uživatelského modelu přidali validates_uniqueness_of :email. Pokud současně stisknou tlačítko „Zaregistrovat se“, Rails vyhledá daný e-mail v uživatelské tabulce a odpoví, že je vše v pořádku a že je v pořádku uložit záznam do tabulky. Rails pak uloží dva záznamy do uživatelské tabulky se stejným e-mailem a teď máte opravdu zatracený problém, který musíte řešit.

Abyste tomu zabránili, musíte vytvořit jedinečné omezení také na úrovni databáze:

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

Takže vytvořením jedinečného indexu index_users_on_email získáte dvě velmi pěkné výhody. Integrita dat a dobrý výkon, protože jedinečné indexy bývají velmi rychlé.

Pokud do tabulky příspěvků pro user_id zadáte jedinečné:true, neumožní to zadávat duplicitní záznamy se stejným user_id.



  1. Dotaz na počítání různých slov všech hodnot ve sloupci

  2. MySQL se Sequelize:ER_BAD_DB_ERROR:Neznámá databáze

  3. Jak použít stránkování na výsledek SQL dotazu s Joins?

  4. Zpráva:count():Parametr musí být pole nebo objekt, který implementuje Countable codeigniter na centos