98

私は次のような新しいレコードを作成します。

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

私のデータベースには現在、トラック用に数千のエンティティがありますが、いくつかのIDを使用できるように、それらのいくつかにIDを割り当てました。つまり、railsはid = 150のアイテムを作成し、正常に動作します。しかし、アイテムを作成してid = 151を割り当てようとしますが、そのIDはすでに存在している可能性があるため、次のエラーが表示されます。

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

次にアクションを実行すると、ID 152が割り当てられるだけで、その値がまだ取得されていない場合は正常に機能します。IDを割り当てる前に、IDがすでに存在するかどうかをレールで確認するにはどうすればよいですか?

ありがとう!

編集

トラックIDは複製されているものです。ユーザーはすでに存在し、この場合は定数です。それは実際に私が対処しなければならないレガシーの問題です。1つのオプションは、今回はすべてのIDを自動的に割り当てるletrailsでテーブルを再作成することです。他にもいくつか問題があるので、これが最良の選択かもしれないと思い始めていますが、Truckは他の多くのテーブルの外部キーであるため、これを行うための移行は非常に複雑になります。レールに、トラックの下にすでに保存されている同じデータを使用して、自動割り当てされたIDを使用し、既存のすべての関係を維持して、新しいテーブルを作成させる簡単な方法はありますか?

4

5 に答える 5

210

私はこれを行い、問題を解決しました。

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

于 2013-02-27T09:40:48.637 に答える
89

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ます。

別の解決策は、会社クラスのsave()メソッドをオーバーライドして、保存する前に新しい行の会社IDを手動で設定することです。

于 2012-06-17T04:43:40.890 に答える
27

@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
于 2015-09-09T16:34:36.407 に答える
6

次のコマンドでこの問題を解決しました。

Railsコンソールでこれを実行します

ActiveRecord::Base.connection.reset_pk_sequence!('table_name')
于 2019-07-03T06:08:24.183 に答える
4

Railsの問題ではなく、データベースの問題のように思えます。データベースの列に不適切なIDシードが含まれている可能性はありますidか?テストするには、データベースに直接いくつかの挿入を実行して、同じ動作が存在するかどうかを確認してください。

于 2012-06-17T04:12:35.787 に答える