66

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

4

6 に答える 6

173

これは(私が考える)SQLiteの不具合です。このエラーは、テーブルにレコードがあるかどうかに関係なく発生します。

テーブルを最初から追加する場合は、NOT NULLを指定できます。これは、「:null=>false」表記で行っていることです。ただし、列を追加するときにこれを行うことはできません。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データベースで機能します。

于 2011-07-15T16:34:52.963 に答える
49

表には既に行があり、新しい列を追加していますdivision_id。既存の各行の新しい列に何かが必要です。

通常、SQLite は NULL を選択しますが、NULL にできないと指定した場合はどうすればよいでしょうか? それは知る由もありません。

見る:

そのブログの推奨事項は、not null 制約なしで列を追加することであり、すべての行に NULL が追加されます。次に、 に値を入力し、division_idを使用change_columnして not null 制約を追加できます。

この 3 段階のプロセスを実行する移行スクリプトの説明については、リンク先のブログを参照してください。

于 2010-07-03T07:33:41.693 に答える
0

デフォルト値で列を追加できます。

ALTER TABLE table1 ADD COLUMN userId INTEGER NOT NULL DEFAULT 1
于 2021-02-17T03:14:04.727 に答える