ฉันจะสร้างคอลัมน์ที่ไม่ซ้ำกันและจัดทำดัชนีในการโยกย้าย Ruby on Rails ได้อย่างไร


416

ฉันต้องการสร้างคอลัมน์uniqueในสคริปต์การโยกย้าย Ruby on Rails วิธีที่ดีที่สุดที่จะทำคืออะไร? นอกจากนี้ยังมีวิธีการจัดทำดัชนีคอลัมน์ในตารางหรือไม่?

ผมอยากจะบังคับใช้คอลัมน์ในฐานข้อมูลเมื่อเทียบกับเพียงแค่ใช้unique:validate_uniqueness_of

คำตอบ:


686

คำตอบสั้น ๆ สำหรับ Rails รุ่นเก่า (ดูคำตอบอื่น ๆ สำหรับ Rails 4+):

add_index :table_name, :column_name, unique: true

ในการสร้างดัชนีหลายคอลัมน์ด้วยกันคุณจะต้องผ่านอาร์เรย์ชื่อคอลัมน์แทนที่จะเป็นชื่อคอลัมน์เดียว

add_index :table_name, [:column_name_a, :column_name_b], unique: true

หากคุณได้รับ "ชื่อดัชนี ... ยาวเกินไป" คุณสามารถเพิ่มname: "whatever"วิธี add_index เพื่อทำให้ชื่อสั้นลง

สำหรับการควบคุมแบบละเอียดมีวิธี " execute" ที่เรียกใช้ SQL แบบตรง

แค่นั้นแหละ!

หากคุณกำลังทำสิ่งนี้แทนการตรวจสอบความถูกต้องของรุ่นเก่าปกติตรวจสอบเพื่อดูว่ามันทำงานอย่างไร การรายงานข้อผิดพลาดไปยังผู้ใช้อาจไม่ดีเท่าที่ควรหากไม่มีการตรวจสอบระดับโมเดล คุณสามารถทำได้ทั้งสองอย่าง


36
+1 สำหรับการแนะนำการใช้งาน validates_uniqueness_of ต่อไป จัดการข้อผิดพลาดที่มีการทำความสะอาดมากใช้วิธีนี้สำหรับค่าใช้จ่ายของการจัดทำดัชนีแบบสอบถามเดียวผมจะแนะนำให้เขาทำทั้งสอง
สตีฟ Weet

1
ฉันพยายามที่มันดูเหมือนจะไม่ทำงาน! ฉันสามารถแทรกสองระเบียนด้วย column_name ที่ฉันกำหนดให้ไม่ซ้ำกัน! ฉันใช้ Rails 2.3.4 และ MySql แล้ว
Tam

ฉันใช้คำแนะนำที่สองโดยใช้ execute: execute "ALTER TABLE users เพิ่ม UNIQUE (email)" และใช้งานได้! ไม่แน่ใจว่าทำไมคนแรกที่ไม่ได้จะมีความสนใจในการรู้
Tam

1
หากคุณได้รับindexed columns are not uniqueข้อผิดพลาดเมื่อพยายามสร้างดัชนีที่ไม่ซ้ำกันอาจเป็นเพราะข้อมูลในตารางมีข้อมูลที่ซ้ำกันอยู่แล้ว ลองลบข้อมูลที่ซ้ำกันและเรียกใช้การย้ายข้อมูลอีกครั้ง
Hartley Brody

5
ถ้าคุณได้รับ "ชื่อดัชนี ... ยาวเกินไป" คุณสามารถเพิ่ม, :name => "whatever"กับadd_indexวิธีการที่จะทำให้ชื่อสั้น
Rick Smith

129

รางสร้างการโยกย้าย add_index_to_table_name column_name: uniq

หรือ

รางสร้างการย้ายถิ่น add_column_name_to_table_name column_name: string: uniq: index

สร้าง

class AddIndexToModerators < ActiveRecord::Migration
  def change
    add_column :moderators, :username, :string
    add_index :moderators, :username, unique: true
  end
end

หากคุณกำลังเพิ่มดัชนีในคอลัมน์ที่มีอยู่ให้ลบหรือแสดงความคิดเห็นadd_columnบรรทัดหรือใส่ในการตรวจสอบ

add_column :moderators, :username, :string unless column_exists? :moderators, :username

5
ฉันลงทะเบียนเพราะฉันต้องการแบบฟอร์มบรรทัดคำสั่ง แต่มันเป็นเรื่องโง่ที่จะเพิ่มคอลัมน์แม้ในขณะที่ฉันระบุและไม่ได้add_index... add_column...
Tyler Collier

1
อาจจะเป็นเวอร์ชั่นถัดไป
d.danailov

49

เนื่องจากยังไม่ได้กล่าวถึง แต่ตอบคำถามที่ฉันพบเมื่อพบหน้านี้คุณสามารถระบุว่าดัชนีควรจะไม่ซ้ำกันเมื่อทำการเพิ่มผ่านt.referencesหรือt.belongs_to:

create_table :accounts do |t|
  t.references :user, index: { unique: true } # or t.belongs_to

  # other columns...
end

(ราว Rails อย่างน้อย4.2.7)


42

หากคุณกำลังสร้างตารางใหม่คุณสามารถใช้ทางลัดแบบอินไลน์:

  def change
    create_table :posts do |t|
      t.string :title, null: false, index: { unique: true }
      t.timestamps
    end
  end

14

ฉันใช้ Rails 5 และคำตอบข้างต้นนั้นยอดเยี่ยม นี่เป็นอีกวิธีหนึ่งที่ใช้งานได้สำหรับฉัน (ชื่อตารางคือ:peopleและชื่อคอลัมน์:email_address)

class AddIndexToEmailAddress < ActiveRecord::Migration[5.0]
  def change
    change_table :people do |t|
      t.index :email_address, unique: true
    end
  end
end

1

คุณอาจต้องการเพิ่มชื่อสำหรับคีย์ที่ไม่ซ้ำกันหลายครั้งที่ชื่อ Unique_key เริ่มต้นโดยทางรถไฟอาจยาวเกินไปซึ่ง DB สามารถโยนข้อผิดพลาด

หากต้องการเพิ่มชื่อสำหรับดัชนีของคุณเพียงใช้name:ตัวเลือก แบบสอบถามการโยกย้ายอาจมีลักษณะเช่นนี้ -

add_index :table_name, [:column_name_a, :column_name_b, ... :column_name_n], unique: true, name: 'my_custom_index_name'

ข้อมูลเพิ่มเติม - http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index


1
add_index :table_name, :column_name, unique: true

ในการทำดัชนีหลายคอลัมน์ด้วยกันคุณจะต้องผ่านอาร์เรย์ชื่อคอลัมน์แทนชื่อคอลัมน์เดียว


0

หากคุณพลาดที่จะเพิ่มเฉพาะคอลัมน์ DB เพียงเพิ่มการตรวจสอบนี้ในรูปแบบเพื่อตรวจสอบว่าเขตข้อมูลไม่ซ้ำกัน:

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name
end

อ้างอิงที่นี่ ด้านบนมีวัตถุประสงค์เพื่อการทดสอบเท่านั้นโปรดเพิ่มดัชนีโดยการเปลี่ยนคอลัมน์ฐานข้อมูลตามที่ @Nate แนะนำ

โปรดอ้างอิงกับดัชนีนี้สำหรับข้อมูลเพิ่มเติม


2
ฉันจะไม่แนะนำเพียงแค่เพิ่มการตรวจสอบโดยไม่มีดัชนีที่สอดคล้องกัน ตัวเลือกที่ดีกว่าคือการล้างรายการซ้ำที่มีอยู่แล้วเพิ่มดัชนี มิฉะนั้นคุณอาจเสี่ยงต่อการทำให้ข้อมูลที่มีอยู่ไม่ถูกต้อง (ซึ่งจะทำให้การอัปเดตใด ๆ ในแถวเหล่านั้นล้มเหลว) และคุณยังคงสามารถทำซ้ำได้หากคุณมีรหัสที่ข้ามการตรวจสอบความถูกต้องของ Rails (เช่นเมื่อเรียกใช้ update_all หรือแทรก SQL โดยตรง)
เนท
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.