我有这个原始的迁移已经运行并发送到上游:
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尝试重新创建它之前删除约束。
答案 0 :(得分:25)
我不确定何时将其添加到Ecto,但至少在2.1.6中不再需要原始SQL。 drop/1
现在supports constraints(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
答案 1 :(得分:18)
您可以在致电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])
答案 2 :(得分:8)
我最终得到了以下解决方案:
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尝试重新创建它之前删除约束
从问题中复制。
答案 3 :(得分:2)
我认为它不能用alter table
实现。例如,根据this answer Postgres不允许在ALTER TABLE
语句中修改约束。 MySQL also doesn't allow modifying constraints
最简单的方法是删除字段并在没有任何数据时将其添加回去。否则,您需要使用带有execute
答案 4 :(得分:2)
“如果:from
的值为%Reference{}
,则适配器将在修改类型之前尝试删除相应的外键约束。”
modify :user_id, references(:users, on_delete: :delete_all), from: references(:users)
应该工作。在进行回滚时,我发现这可以清除FK并删除列:
remove :user_id, references(:users)
答案 5 :(得分:0)
...
import { Home, SomeOtherComponent } from './pages';
...
选项是在 Ecto 3.0 中引入的,因此您可以以更优雅的方式设置迁移:
from