Ruby on Rails ActiveRecord 마이그레이션에서 너무 긴 색인 이름을 어떻게 처리합니까?


391

네 개의 관련 테이블의 외래 키에서 생성되는 고유 인덱스를 추가하려고합니다.

add_index :studies,
  ["user_id", "university_id", "subject_name_id", "subject_type_id"],
  :unique => true

인덱스 이름에 대한 데이터베이스 제한으로 인해 마이그레이션이 실패합니다. 오류 메시지는 다음과 같습니다.

테이블 'studies'의 인덱스 이름 'index_studies_on_user_id_and_university_id_and_subject_name_id_and_subject_type_id'가 너무 깁니다. 한도는 64 자입니다

이것을 어떻게 처리 할 수 ​​있습니까? 다른 색인 이름을 지정할 수 있습니까?

답변:


589

다음 과 같은 :name옵션을 제공하십시오 add_index.

add_index :studies,
  ["user_id", "university_id", "subject_name_id", "subject_type_id"], 
  :unique => true,
  :name => 'my_index'

블록 에서 :index옵션을 사용하는 경우 값 과 동일한 옵션 해시를 사용합니다.referencescreate_tableadd_index

t.references :long_name, index: { name: :my_index }

2
APIdock에 따르면 이름은 기호가 아닌 문자열이어야합니다.
Jaco Pretorius

7
이를위한 다운 문법은 remove_index :studies, :name => 'my_index'그것을 필요로하는 사람을위한 것입니다
Kirk

On Rails 4.2.6는와 함께 작동합니다 index: { name: :my_index }. 만 name작동하지 않았다.
monteirobrena

174

create_table블록 내의 열 정의에서 색인 이름을 변경할 수도 있습니다 (예 : 마이그레이션 생성기에서 가져옴).

create_table :studies do |t|
  t.references :user, index: {:name => "index_my_shorter_name"}
end

5
이것은 원래 질문에서 다중 열 인덱스를 생성하지 않습니다. 그것은 단지에서 긴 색인 이름을 단축하는 방법을 보여주고 있습니다create_table
Craig Walker

6
이것은 인덱스 t.references :searchable, polymorphic:true, index: {:name => "index_searches_on_searchable"}가 있는 네임 스페이스 테이블에서 다형성 참조를 만들려고 할 때 도움이되었습니다. 이 경우 인덱스는 실제로 다중 열 (searchable_id 및 searchable_type)이며 생성 된 이름에 네임 스페이스 추가가 매우 길어졌습니다. .
mkrinblk

나를위한 멋진 컴팩트 솔루션. 감사합니다!
Sergio Belevskij

3
또한 foreign_key: true레일 생성기 model:references형식으로 생성 된 마이그레이션 파일이있을 때 사용하기가 가장 쉽기 때문에이 솔루션은 훌륭한 솔루션 입니다.
Abram

39

PostgreSQL 에서 기본 제한은 63 자 입니다. 인덱스 이름은 고유해야하기 때문에 약간의 규칙을 사용하는 것이 좋습니다. 나는 (더 복잡한 구조를 설명하기 위해 예를 조정했다) :

def change
  add_index :studies, [:professor_id, :user_id], name: :idx_study_professor_user
end

일반적인 색인은 다음과 같습니다.

:index_studies_on_professor_id_and_user_id

논리는 다음과 같습니다.

  • index 된다 idx
  • 단수 테이블 이름
  • 참여 단어가 없습니다
  • 아니 _id
  • 알파벳 순서

일반적으로 어떤 일을합니까?


1
공유해 주셔서 감사합니다. 제한 사항에 대한 Postgres 설명서를 연결할 수 있다면 좋을 것입니다.
JJD

인덱스가 해당 테이블에 속하기 때문에 인덱스 이름에 테이블 이름이 필요합니까? 내가 보지 못한 곳에서 그것이 유익한 지 궁금합니다.
Joshua Pinter

인덱스 이름을 원하는대로 지정할 수 있지만 인덱스 이름의 테이블 이름은 인덱스 이름을 고유하게 유지하는 데 도움이되고 (필수적인) 범위를 정하고 오류 메시지 가독성을 향상시킵니다.
ecoologic


6

이전 답변과 비슷합니다. 일반 add_index 줄과 함께 'name'키를 사용하십시오.

def change
  add_index :studies, :user_id, name: 'my_index'
end

2

이러한 솔루션 중 어느 것도 나를 위해 일한 것이 두렵습니다. 아마도 내가 belongs_tocreate_table 마이그레이션에서 다형성 연관을 사용했기 때문일 것 입니다.

아래에 코드를 추가하고 다형성 연결과 관련하여 '색인 이름이 너무 깁니다'를 검색 할 때 다른 사람이 우연히 발견하는 경우 도움이되는 솔루션에 대한 링크를 추가하겠습니다.

다음 코드는 저에게 효과적이지 않았습니다.

def change
  create_table :item_references do |t|
    t.text :item_unique_id
    t.belongs_to :referenceable, polymorphic: true
    t.timestamps
  end
  add_index :item_references, [:referenceable_id, :referenceable_type], name: 'idx_item_refs'
end

이 코드는 저에게 효과적입니다.

def change
  create_table :item_references do |t|
    t.text :item_unique_id
    t.belongs_to :referenceable, polymorphic: true, index: { name: 'idx_item_refs' }

    t.timestamps
  end
end

이것은 나를 도와 준 SO Q & A입니다 : https://stackoverflow.com/a/30366460/3258059


1

이 문제가 있었지만 timestamps기능이 있습니다. updated_at에서 63 자 제한을 초과하는 인덱스를 자동 생성했습니다.

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps
  end
end

테이블 'toooooooooo_loooooooooooooooooooooooooooooong'의 색인 이름 'index_toooooooooo_loooooooooooooooooooooooooooooong_on_updated_at'이 (가) 너무 깁니다. 한도는 63 자입니다

timestamps색인 이름을 지정하는 데 사용하려고했습니다 .

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps index: { name: 'too_loooooooooooooooooooooooooooooong_updated_at' }
  end
end

그러나,이 모두에 인덱스 이름을 적용하려고 updated_at하고 created_at필드 :

테이블 'toooooooooo_loooooooooooooooooooooooooooooong'의 색인 이름 'too_long_updated_at'이 이미 존재합니다

마침내 나는 포기 timestamps하고 타임 스탬프를 먼 길로 만들었습니다.

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.datetime :updated_at, index: { name: 'too_long_on_updated_at' }
    t.datetime :created_at, index: { name: 'too_long_on_created_at' }
  end
end

이것은 효과가 있지만 timestamps방법으로 가능하다면 듣고 싶습니다 !


0

create_table : you_table_name do | t | t.references : studant, index : {이름 : 'name_for_studant_index'} t.references : teacher, 인덱스 : {name : 'name_for_teacher_index'} 끝


0

발전기를 많이 사용하는 프로젝트가 있고 이것을 자동으로 필요로했기 때문에 index_name레일 소스에서 함수를 복사하여 재정의했습니다. 나는 이것을 다음에 추가했다 config/initializers/generated_index_name.rb:

# make indexes shorter for postgres
require "active_record/connection_adapters/abstract/schema_statements"
module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module SchemaStatements
      def index_name(table_name, options) #:nodoc:
        if Hash === options
          if options[:column]
            "ix_#{table_name}_on_#{Array(options[:column]) * '__'}".slice(0,63)
          elsif options[:name]
            options[:name]
          else
            raise ArgumentError, "You must specify the index name"
          end
        else
          index_name(table_name, index_name_options(options))
        end
      end
    end
  end
end

그것은 같은 인덱스를 만듭니다 ix_assignments_on_case_id__project_id 하고 여전히 너무 길면 63 자로 잘립니다. 테이블 이름이 매우 길면 여전히 고유하지 않지만 열 이름과 별도로 테이블 이름을 줄이거 나 실제로 고유성을 확인하는 등의 복잡성을 추가 할 수 있습니다.

이것은 Rails 5.2 프로젝트에서 가져온 것입니다. 이 작업을 수행하기로 결정한 경우 버전에서 소스를 복사하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.