【Rails】エラー対処法:PG::DuplicateTable: ERROR: relation already exists

rails-prograshi(プロぐらし)-kv Rails
記事内に広告が含まれていることがあります。
[PR]

PG::DuplicateTable: ERROR: relation <テーブル名> already existsは、rails db:migrateの実行時に発生するエラーです。

これは既にテーブルが生成済みの場合に再度生成しようとして発生するエラーです。

エラー内容

rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::DuplicateTable: ERROR:  relation "article_rankings" already exists
/app/db/migrate/20211508103382_create_article_rankings.rb:3:in `change'
/app/bin/rails:4:in `<main>'


上記例だと、article_rankingsというテーブルが既にあるのに、再度生成しようとしているため怒られています。


対処法1(既存のテーブルと関連がない場合)

全く関係のないテーブルを作成しようとしている場合は、作成しようとしているテーブル名を変更することで対応できます。

その際、マイグレションファイルのファイル名と中で生成しようとしているテーブル名を命名規則にあった形で修正する必要があります。

実例

例えば、20211508103382_create_article_rankings.rbというマイグレーションファイルであれば、

ファイル名を次のように変更します。

20211508103382_create_article_rankings.rb
↓
20211508103382_create_review_rankings.rb

ファイルの中身も修正します。

class CreateArticleRankings < ActiveRecord::Migration[6.1]
  def change
    create_table :article_rankings do |t|
      t.integer :article_id, null: false
      t.integer :score
      t.string :tag_slug, null: false # daily, cumlativ
      t.timestamps
    end
    add_index :article_rankings, [:article_id, :tag_slug], unique: true
    remove_column :article_rankings, :id, :bigint
  end
end


↓ 中身を修正(article_rankings → review_rankingsへ)

class CreateReviewRankings < ActiveRecord::Migration[6.1]
  def change
    create_table :review_rankings do |t|
      t.integer :article_id, null: false
      t.integer :score
      t.string :tag_slug, null: false # daily, cumlativ
      t.timestamps
    end
    add_index :reivew_rankings, [:article_id, :tag_slug], unique: true
    remove_column :review_rankings, :id, :bigint
  end
end


対処法2(DBの再生成)

個人プロジェクトやテーブルが少なく過去に何が行われているかもはっきりしている場合は、DBを全て消して再生成する方法があります。(※テーブルに挿入されているデータは消えます

railsコマンドのみで対応できます。

rails db:migrate:reset
rails db:migrate


対処法3(対象のテーブルのみ削除する)

3つ目の対処法は重複しているテーブルのみ削除する方法です。他への影響がないため、複数人の複雑なプロジェクトであれば、こちらの方法を採用するべきです。

データベースのSQLのコマンドラインを開いて次を入力します。

DROP TABLE IF EXISTS <テーブル名>

テーブルを削除できたら、rails db:migrateを再度実行します。


実行例

# rails db:migrate

(省略)
== 20211508103382 CreateArticleRankings: migrated (0.0201s) ===================

D, [2021-11-22T03:58:12.883899 #351] DEBUG -- :   ActiveRecord::SchemaMigration Create (0.6ms)  INSERT INTO "schema_migrations" ("version") VALUES ('20211508103382') RETURNING "version"
D, [2021-11-22T03:58:12.884683 #351] DEBUG -- :   ↳ lib/active_record/connection_adapters/postgresql_adapter_patch.rb:28:in `execute_and_clear'
D, [2021-11-22T03:58:12.886554 #351] DEBUG -- :   TRANSACTION (1.6ms)  COMMIT
D, [2021-11-22T03:58:12.891498 #351] DEBUG -- :   ActiveRecord::InternalMetadata Load (0.8ms)  SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = 'environment' LIMIT 1
D, [2021-11-22T03:58:12.892001 #351] DEBUG -- :   ↳ lib/active_record/connection_adapters/postgresql_adapter_patch.rb:28:in `execute_and_clear'
D, [2021-11-22T03:58:12.897437 #351] DEBUG -- :    (1.3ms)  SELECT pg_advisory_unlock(2167604979718042620)
D, [2021-11-22T03:58:12.936563 #351] DEBUG -- :    (2.0ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
D, [2021-11-22T03:58:12.936872 #351] DEBUG -- :   ↳ lib/active_record/connection_adapters/postgresql_adapter_patch.rb:28:in `execute_and_clear'

#

マイグレーションが終われば無事完了です。

タイトルとURLをコピーしました