私はすでに実行されてアップストリームに送信されたこのオリジナルの移行を持っています:
create table(:videos) do
add :url, :string
add :title, :string
add :description, :text
add :user_id, references(:users, on_delete: :nothing)
timestamps
end
create index(:videos, [:user_id])
次に、user_id
の外部キーをカスケード削除に変更して、ユーザーが削除されると、関連付けられている動画もすべて削除されるようにします。
次の移行を試しました:
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
ただし、これによりエラーが発生します。
(Postgrex.Error) ERROR (duplicate_object): constraint "videos_user_id_fkey" for relation "videos" already exists
要件に応じてこの外部キーを変更する移行スクリプトを作成するにはどうすればよいですか?
[〜#〜]更新[〜#〜]
私は次の解決策に終わりました:
def up do
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
end
def down do
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
alter table(:videos) do
modify :user_id, references(:users, on_delete: :nothing)
end
end
これにより、ectoが制約の再作成を試みる前に制約が削除されます。
alter
を呼び出す前にインデックスを削除できます:
drop_if_exists index(:videos, [:user_id])
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
反対のことは少しトリッキーです:
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
create_if_not_exists index(:videos, [:user_id])
これがEctoにいつ追加されたかはわかりませんが、少なくとも2.1.6では、生のSQLは必要なくなりました。 drop/1
現在 制約をサポート (drop_if_exists/1
はしません):
def up do
drop constraint(:videos, "videos_user_id_fkey")
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
end
def down do
drop constraint(:videos, "videos_user_id_fkey")
alter table(:videos) do
modify :user_id, references(:users, on_delete: :nothing)
end
end
私は次の解決策に終わりました:
def up do
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
end
def down do
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
alter table(:videos) do
modify :user_id, references(:users, on_delete: :nothing)
end
end
これは、ectoが制約を再作成しようとする前に制約を削除します
質問からコピーしました。
alter table
では実現できないと思います。たとえば この答え に従って、PostgresはALTER TABLE
ステートメントの制約を変更することを許可していません。 MySQLでは制約の変更も許可されていません 。
最も簡単な方法は、フィールドを削除して、データがない場合はフィールドを元に戻すことです。それ以外の場合は、生のSQLを execute
で使用する必要があります