2010-05-12 6 views
2

MySQL에는 INSERT 문에 대한 매우 유용한 옵션이 있습니다. 이것은 id 열이없는 조인 테이블에 특히 유용합니다. 레코드를 삽입하지만 키가 기존 레코드와 충돌하는 경우 오류를 던지는 대신 해당 레코드가 업데이트됩니다. 예를 들면 다음과 같습니다.저장된 레코드에 동일한 키가 있으면 기존 레코드를 업데이트하는 방법은 무엇입니까?

INSERT INTO table (key1,key2,data) VALUES (1,2,3) 
    ON DUPLICATE KEY UPDATE data=3; 

액티브 레코드와 동일한 방법은? 생성 된 코드는 다음과 같을 것이다 : 그

class Model < ActiveRecord::Base 
    belongs_to :key1 
    belongs_to :key2 
end 

record = Model.new 
record.key1 = key1 
record.key2 = key2 
record.data = 'new data' 
record.WHAT? #Inserts or updates `data` for the existing record 

답변

3

을 j에 의한 대답은 올바른 생각이지만, 객체에 대한 다중 저장을 피하기 위해 find_or_initialize_by를 사용하려고합니다. 예 : 그것의 소리에 의해

record = Model.find_or_initialize_by_key1_and_key2 new 
record.data = 'new data' 
record.save 

은 또한 검증 중복을 허용하지 않는 모델이 너무 조인 있는지 확인하려면 :

class Model < ActiveRecord::Base 
    belongs_to :key1 
    belongs_to :key2 
    validates_uniqueness_of :key1, :scope => :key2 
end 
0

먼저 지금까지의 내가 구문이 다른 SQL-서버에서 작동하지 않는 것을 알고, MySQL의 특정 솔루션입니다. 토론에서는 보통 Upsert이라고합니다.

save_or_update이라는 새로운 방법을 만든 다음 중복 키 예외가 발생하면 저장이 실패하고로드가 update_params이 될 것입니다.

+0

귀하의 솔루션은별로 효과가 없습니다. 'save'가 실패하면 주목할만한 크기의 트랜잭션을 롤백 할 수 있으며 데이터를 다시로드해야합니다. MySQL에 관해서는, 미안, 문제가 해결되었습니다. –

+0

'find' 자체는'AR :: RecordNotFound'를 리턴하지만'find_by_ *'는'nil'을 리턴합니다. – theIV

2

당신은 다음을 수행 할 수

record = Model.find_or_create_by_key1_and_key2(:key1 => key1, :key2 => key2) 
record.update_attribute(:data, "new data") 

편집 아이디어가 좋아 보이는

zaius, 당신은 여러가 저장되지 않도록 find_or_initialize_by를 사용한다 그가 말한대로 :]

+0

오, 멋지다! [DynamicFinderMatch # new] (http://railsapi.com/doc/rails-v2.3.5/classes/ActiveRecord/DynamicFinderMatch.html#M001202)에서 문서를 찾았으며 "소스보기"를 클릭하십시오. – gaqzi

+0

그냥 덧글 :이 조언은 그것이 제시된 방식으로 인해 보일지도 모르겠다보다 더 심오한 것으로 나타납니다 ... –

+0

나는 당신의 의견을 이해하지 못했습니다 ... –

관련 문제