이미 존재하는 Rails 자동 할당 ID


92

다음과 같이 새 레코드를 만듭니다.

truck = Truck.create(:name=>name, :user_id=>2)

내 데이터베이스에는 현재 트럭에 대한 수천 개의 엔티티가 있지만 일부 ID를 사용할 수있는 방식으로 일부에 ID를 할당했습니다. 그래서 무슨 일이 일어나고 있는지 rails는 id = 150으로 항목을 만들고 잘 작동합니다. 그러나 항목을 만들고 할당하려고 시도하지만 ID = 151이 이미 존재할 수 있으므로 다음 오류가 표시됩니다.

ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint "companies_pkey" DETAIL: Key (id)=(151) already exists.

다음에 액션을 실행할 때 단순히 ID 152를 할당합니다. 해당 값이 아직 적용되지 않은 경우 제대로 작동합니다. ID를 할당하기 전에 ID가 이미 존재하는지 확인하기 위해 레일을 얻으려면 어떻게해야합니까?

감사!

편집하다

트럭 ID는 복제되는 것입니다. 사용자가 이미 존재하며이 경우 상수입니다. 사실 제가 다루어야 할 유산 문제입니다. 한 가지 옵션은 이번에는 rails가 모든 ID를 자동 할당하도록 테이블을 다시 만드는 것입니다. 몇 가지 다른 문제가 있기 때문에 이것이 최선의 선택이라고 생각하기 시작했지만 Truck은 다른 많은 테이블에서 외래 키이기 때문에이를 수행하는 마이그레이션은 매우 복잡 할 것입니다. 자동 할당 된 ID와 모든 기존 관계를 유지하면서 트럭에 이미 저장된 동일한 데이터를 사용하여 레일이 새 테이블을 생성하도록하는 간단한 방법이 있습니까?


레일이 자동으로 ID를 할당하지 않는 이유는 무엇입니까? 그러면 중복 위험이 없어집니다. 아니면 기존 ID를 유지해야하는 레거시 데이터 문제입니까? 새 개체를 만들 때 일반적인 비즈니스가 아니기 때문에 비즈니스 사례를 조금 이해하고 싶습니다.
MBHNYC

@MBHNYC D-Nice가 회사를 만들 때 user_id를 할당하고 있다고 생각합니다. 당신이 생각하는대로 id가 아니라 (저도 잠시 동안했습니다).
아닐

Ooo good catch Anil — 당신 말이 완전히 맞습니다. @ D-Nice, 이상한 점이있을 경우이 테이블에 대한 마이그레이션을 게시물에 추가 하시겠습니까? 그 USER_ID에서 편집을 유혹하는 것은 혼란을 제거하기 위해 ..
MBHNYC

아니오, 불분명해서 죄송합니다. 중복되는 회사 ID입니다. 사용자가 이미 존재하며이 경우 상수입니다. 사실 제가 다루어야 할 유산 문제입니다. 더 많은 정보와 윌 편집 포스트
D-니스

테이블을 다시 만들 필요가 없습니다. 시퀀스를 재설정하려면 내 대답을 참조하십시오.
DONDI 마이클 기질

답변:


87

Rails는 아마도 내장 PostgreSQL 시퀀스를 사용하고있을 것입니다. 시퀀스의 개념은 한 번만 사용된다는 것입니다.

가장 간단한 해결책은 다음과 같은 쿼리를 사용하여 company.id 열의 시퀀스를 테이블에서 가장 높은 값으로 설정하는 것입니다.

SELECT setval('company_id_seq', (SELECT max(id) FROM company));

시퀀스 이름 "company_id_seq", 테이블 이름 "company"및 열 이름 "id"를 추측하고 있습니다 ... 올바른 이름으로 바꾸십시오. 시퀀스 이름을 얻 SELECT pg_get_serial_sequence('tablename', 'columname');거나로 테이블 정의를 볼 수 있습니다 \d tablename.

다른 해결책은 저장하기 전에 새 행에 대한 회사 ID를 수동으로 설정하도록 회사 클래스의 save () 메소드를 재정의하는 것입니다.


현재 가장 높은 값 + 1로 자동 할당이 시작되는 것이 무엇인지 추측하고 있습니다.
D-니스

나는 이것이 내 질문에 대한 최선의 대답이라고 생각하지만, 관련없는 이유로 내가 OP 편집에서 설명한 전략을 사용하는 방법을 찾아야 할 것입니다
D-Nice

왜 이런 일이 시작되었는지 이해할 수 없습니까? 이것은 나에게 일어 났고 이것이 어떻게 가능했는지 이해하고 싶습니다.
Hunt Burdick

2
@Websitescenes, PostgreSQL에 SERIAL 열이있는 경우 (직렬 열은 기본값이 시퀀스의 다음 값인 경우) 테이블을 해당 열의 하드 값으로 채우면 시퀀스가 ​​자동으로 업데이트되지 않습니다. 예 : create table t (id serial not null primary key); insert into t values (1); insert into t values (default); ERROR: duplicate key value violates unique constraint "t_pkey" DETAIL: Key (id)=(1) already exists.
Dondi Michael Stroma 2014 년

204

나는 이것을 위해 문제를 해결했습니다.

ActiveRecord::Base.connection.tables.each do |t|
  ActiveRecord::Base.connection.reset_pk_sequence!(t)
end

reset_pk_sequence를 찾았습니다! 이 스레드에서. http://www.ruby-forum.com/topic/64428


4
감사합니다. 최고의 솔루션입니다. 데이터베이스 전송 후 동일한 문제가 발생했습니다.
Oleg Pasko 2013

61
또는 한 줄에 해당하는 것 (레일 콘솔 복사 / 붙여 넣기 목적) :ActiveRecord::Base.connection.tables.each { |t| ActiveRecord::Base.connection.reset_pk_sequence!(t) }
Raf

이것이 어떻게 동기화되지 않는지 아십니까?
키가 큰 폴

25

@Apie 답변을 기반으로 합니다.

다음을 사용하여 작업을 만들고 필요할 때 실행할 수 있습니다.

rake database:correction_seq_id

다음과 같은 작업을 생성합니다.

rails g task database correction_seq_id

그리고 생성 된 파일 ( lib/tasks/database.rake)에 다음을 입력합니다.

namespace :database do
    desc "Correction of sequences id"
    task correction_seq_id: :environment do
        ActiveRecord::Base.connection.tables.each do |t|
            ActiveRecord::Base.connection.reset_pk_sequence!(t)
        end
    end
end

4

레일스 문제가 아닌 데이터베이스 문제처럼 들립니다. 데이터베이스에 id열에 부적절한 ID 시드가있을 수 있습니까? 테스트하려면 데이터베이스에 직접 몇 개의 삽입을 수행하고 동일한 동작이 있는지 확인하십시오.


3
왜 반대 투표입니까? 이것은 증분 시퀀스를 다른 기존 값보다 낮은 값으로 설정하여 데이터를 삽입 할 때 가끔 충돌이 발생하는 경우 발생하는 정확한 동작입니다. 포스터는 이미이 사건에 해당하는 기존 데이터가 있다고 말했습니다.
mynameiscoffey

잘 삽입 할 수 있습니다. 이 오류가 발생한 후 시퀀스의 다음 ID가 아직 수행되지 않은 경우 실제로 동일한 작업을 다시 실행하고 작동하도록 할 수 있습니다.
D-니스

이것이 내 상황 인 것 같습니다. 문제가 발생했지만 삽입 한 다음 레코드가 제대로 작동 했으므로 올바른 위치에 씨앗을 넣었을 것입니다.
Ben Wheeler

3

다음 명령으로이 문제를 해결했습니다.

Rails 콘솔에서 실행

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