Ruby on Rails 마이그레이션에서 열을 고유하게 만들고 색인화하려면 어떻게해야합니까?


416

uniqueRuby on Rails 마이그레이션 스크립트에서 열을 만들고 싶습니다 . 가장 좋은 방법은 무엇입니까? 또한 테이블에서 열을 인덱싱하는 방법이 있습니까?

unique사용하는 대신 데이터베이스에 열 을 적용하고 싶습니다 :validate_uniqueness_of.

답변:


686

이전 버전의 Rails에 대한 간단한 답변

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
validates_uniqueness_of를 계속 사용할 것을 제안하면 +1입니다. 오류 처리는 단일 인덱스 쿼리 비용으로이 방법을 사용하는 것이 훨씬 깔끔합니다
Steve Weet

1
작동하지 않는 것 같습니다! 고유 한 것으로 정의 된 column_name으로 두 개의 레코드를 삽입 할 수 있습니다! Rails 2.3.4와 MySql을 사용하고 있습니까?
Tam

execute : "ALTER TABLE users ADD 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

(적어도 레일즈 기준 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에 의해 제안 변경 DB 컬럼에 의해

자세한 내용 은 색인 을 참조하십시오


2
해당 색인없이 유효성 검사를 추가하는 것은 권장하지 않습니다. 더 나은 옵션은 기존 중복을 정리 한 다음 색인을 추가하는 것입니다. 그렇지 않으면 기존 데이터가 무효화 될 수 있으며 (그러면 해당 행에 대한 업데이트가 실패 할 수 있음) Rails 유효성 검사를 건너 뛰는 코드가 있으면 여전히 중복으로 끝날 수 있습니다. (예 : update_all 또는 직접 SQL 삽입 실행시)
Nate
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.