Tho*_*pel 30 elixir ecto phoenix-framework
我有这个已经运行并向上游发送的原始迁移:
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])
Run Code Online (Sandbox Code Playgroud)
现在我希望将外键user_id改为级联删除,这样当用户被删除时,他的所有相关视频也将被删除.
我尝试过以下迁移:
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
Run Code Online (Sandbox Code Playgroud)
但这会引发错误:
(Postgrex.Error) ERROR (duplicate_object): constraint "videos_user_id_fkey" for relation "videos" already exists
Run Code Online (Sandbox Code Playgroud)
如何根据我的要求制定将更改此外键的迁移脚本?
UPDATE
我最终得到了以下解决方案:
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
Run Code Online (Sandbox Code Playgroud)
这会在ecto尝试重新创建之前删除约束.
Max*_*rke 29
我不确定这是什么时候添加到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
Run Code Online (Sandbox Code Playgroud)
Gaz*_*ler 18
您可以在调用之前删除索引alter:
drop_if_exists index(:videos, [:user_id])
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
Run Code Online (Sandbox Code Playgroud)
相反的做法有点棘手:
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
create_if_not_exists index(:videos, [:user_id])
Run Code Online (Sandbox Code Playgroud)
我最终得到了以下解决方案:
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
Run Code Online (Sandbox Code Playgroud)
这会在ecto尝试重新创建之前删除约束
复制自问题.
“如果:from值为 a %Reference{},适配器将在修改类型之前尝试删除相应的外键约束。”
modify :user_id, references(:users, on_delete: :delete_all), from: references(:users)
Run Code Online (Sandbox Code Playgroud)
应该管用。在进行回滚时,我发现这可以清除 FK 并删除该列:
remove :user_id, references(:users)
Run Code Online (Sandbox Code Playgroud)