SQLite3에서 "기본 값이 NULL 인 NOT NULL 열을 추가 할 수 없음"을 해결하는 방법은 무엇입니까?
기존 테이블에 NOT NULL 열을 추가하는 동안 다음 오류가 발생합니다. 왜 일어나고 있습니까?. rake db : reset은 기존 레코드가 문제라고 생각했지만 DB를 재설정해도 문제가 지속됩니다. 이걸 알아 내도록 도와주세요.
마이그레이션 파일
class AddDivisionIdToProfile < ActiveRecord::Migration
def self.up
add_column :profiles, :division_id, :integer, :null => false
end
def self.down
remove_column :profiles, :division_id
end
end
에러 메시지
SQLite3 :: SQLException : 기본값이 NULL 인 NOT NULL 열을 추가 할 수 없습니다. ALTER TABLE "profiles"ADD "division_id"integer NOT NULL
표에 이미 행이 있고 새 열을 추가하고 있습니다 division_id
. 각 기존 행의 새 열에 무언가가 필요합니다.
SQLite는 일반적으로 NULL을 선택하지만 NULL이 될 수 없다고 지정 했으므로 무엇이어야합니까? 알 방법이 없습니다.
보다:
- Rails 마이그레이션에서 기본값이없는 null이 아닌 열 추가 (2009 년, 더 이상 사용할 수 없으므로 이는 archive.org의 스냅 샷임)
- 기존 테이블에 NOT NULL 열 추가 (2014)
해당 블로그의 권장 사항은 not null 제약 조건없이 열을 추가하는 것이며 모든 행에 NULL로 추가됩니다. 그런 다음에 값을 입력 한 division_id
다음를 사용 change_column
하여 null이 아닌 제약 조건을 추가 할 수 있습니다.
이 3 단계 프로세스를 수행하는 마이그레이션 스크립트에 대한 설명은 링크 된 블로그를 참조하십시오.
이것은 (내가 생각하는) SQLite의 결함입니다. 이 오류는 테이블에 레코드가 있는지 여부에 관계없이 발생합니다.
처음부터 테이블을 추가 할 때 ": null => false"표기법으로 수행하는 작업 인 NOT NULL을 지정할 수 있습니다. 그러나 열을 추가 할 때는이 작업을 수행 할 수 없습니다. SQLite의 사양에 따르면 이에 대한 기본값이 있어야하며 이는 잘못된 선택입니다. 기본값을 추가하는 것은 NOT NULL 외래 키를 갖는 목적, 즉 데이터 무결성을 무효화하므로 옵션이 아닙니다.
이 문제를 해결하는 방법은 다음과 같습니다. 동일한 마이그레이션에서 모든 작업을 수행 할 수 있습니다. 참고 : 이것은 데이터베이스에 아직 레코드가없는 경우에 해당됩니다.
class AddDivisionIdToProfile < ActiveRecord::Migration
def self.up
add_column :profiles, :division_id, :integer
change_column :profiles, :division_id, :integer, :null => false
end
def self.down
remove_column :profiles, :division_id
end
end
NOT NULL 제약 조건없이 열을 추가 한 다음 즉시 제약 조건을 추가하기 위해 열을 변경합니다. SQLite는 열을 추가하는 동안 분명히 매우 우려되지만 열 변경에 대해서는 그렇게 까다 롭지 않기 때문에 이렇게 할 수 있습니다. 이것은 내 책에서 분명한 디자인 냄새입니다.
확실히 해킹이지만 여러 마이그레이션보다 짧으며 프로덕션 환경에서 더 강력한 SQL 데이터베이스에서 계속 작동합니다.
기존 행이있는 테이블이있는 경우 null
제약 조건을 추가하기 전에 기존 행을 업데이트해야합니다 . 마이그레이션에 대한 가이드 과 같이, 로컬 모델을 사용하는 것이 좋습니다 :
Rails 4 이상 :
class AddDivisionIdToProfile < ActiveRecord::Migration
class Profile < ActiveRecord::Base
end
def change
add_column :profiles, :division_id, :integer
Profile.reset_column_information
reversible do |dir|
dir.up { Profile.update_all division_id: Division.first.id }
end
change_column :profiles, :division_id, :integer, :null => false
end
end
레일즈 3
class AddDivisionIdToProfile < ActiveRecord::Migration
class Profile < ActiveRecord::Base
end
def change
add_column :profiles, :division_id, :integer
Profile.reset_column_information
Profile.all.each do |profile|
profile.update_attributes!(:division_id => Division.first.id)
end
change_column :profiles, :division_id, :integer, :null => false
end
end
'Nice programing' 카테고리의 다른 글
Windows에서 "make"를 설치하고 사용하는 방법은 무엇입니까? (0) | 2020.12.31 |
---|---|
-1에서 시작하는 루프는 아무것도 인쇄하지 않습니다. (0) | 2020.12.31 |
EL의 문자열 연결 (0) | 2020.12.31 |
Xcode 6의 새 스토리 보드에서 초기보기 컨트롤러를 설정하는 방법이 없습니다. (0) | 2020.12.31 |
포착되지 않은 예외 :이 클래스는 키 값 코딩을 준수하지 않습니다. (0) | 2020.12.31 |