如何在 SQLAlchemy 中删除外键约束?
我正在使用 SQLAlchemy Migrate 来跟踪数据库更改,但在删除外键时遇到了问题。我有两个表,t_new 是一个新表,t_exists 是一个现有表。我需要添加 t_new,然后向 t_exists 添加外键。然后我需要能够反转操作(这就是我遇到麻烦的地方)。
t_new = sa.Table("new", meta.metadata,
sa.Column("new_id", sa.types.Integer, primary_key=True)
)
t_exists = sa.Table("exists", meta.metadata,
sa.Column("exists_id", sa.types.Integer, primary_key=True),
sa.Column(
"new_id",
sa.types.Integer,
sa.ForeignKey("new.new_id", onupdate="CASCADE", ondelete="CASCADE"),
nullable=False
)
)
这工作正常:
t_new.create()
t_exists.c.new_id.create()
但这不行:
t_exists.c.new_id.drop()
t_new.drop()
尝试删除外键列会出现错误:1025,“将'.\my_db_name\#sql-1b0_2e6'重命名为'.\my_db_name\exists'时出错(errno:150) “
如果我使用原始 SQL 执行此操作,我可以手动删除外键,然后删除该列,但我一直无法弄清楚如何使用 SQLAlchemy 删除外键?如何删除外键,然后删除列?
I'm using SQLAlchemy Migrate to keep track of database changes and I'm running into an issue with removing a foreign key. I have two tables, t_new is a new table, and t_exists is an existing table. I need to add t_new, then add a foreign key to t_exists. Then I need to be able to reverse the operation (which is where I'm having trouble).
t_new = sa.Table("new", meta.metadata,
sa.Column("new_id", sa.types.Integer, primary_key=True)
)
t_exists = sa.Table("exists", meta.metadata,
sa.Column("exists_id", sa.types.Integer, primary_key=True),
sa.Column(
"new_id",
sa.types.Integer,
sa.ForeignKey("new.new_id", onupdate="CASCADE", ondelete="CASCADE"),
nullable=False
)
)
This works fine:
t_new.create()
t_exists.c.new_id.create()
But this does not:
t_exists.c.new_id.drop()
t_new.drop()
Trying to drop the foreign key column gives an error: 1025, "Error on rename of '.\my_db_name\#sql-1b0_2e6' to '.\my_db_name\exists' (errno: 150)"
If I do this with raw SQL, i can remove the foreign key manually then remove the column, but I haven't been able to figure out how to remove the foreign key with SQLAlchemy? How can I remove the foreign key, and then the column?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以使用 sqlalchemy.migrate 来完成此操作。
为了使其工作,我必须显式创建外键约束,而不是使用 Column('fk',foreignKey('fk_table.field')) 隐式创建外键约束:
唉,而不是这样做:
这样做:
然后删除过程如下所示:
You can do it with sqlalchemy.migrate.
In order to make it work, I have had to create the foreign key constraint explicitly rather than implicitely with Column('fk', ForeignKey('fk_table.field')):
Alas, instead of doing this:
do that:
Then the deletion process looks like this:
我通过创建一个单独的元数据实例并使用 Session.execute() 运行原始 SQL 来完成此任务。理想情况下,会有一个专门使用 sqlalchemy 的解决方案,这样我就不必使用特定于 MySQL 的解决方案。但到目前为止,我还不知道有这样的解决方案。
I was able to accomplish this by creating a separate metadata instance and using Session.execute() to run raw SQL. Ideally, there would be a solution that uses sqlalchemy exclusively, so I wouldn't have to use MySQL-specific solutions. But as of now, I am not aware of such a solution.
我相信您可以通过 SQLAlchemy-Migrate 实现这一目标。请注意,ForeignKey 位于隔离列上。 foreignKeyConstraint 位于表级别并将列关联在一起。如果您查看列上的ForeignKey 对象,您将看到它引用了ForeignKeyConstraint。
我无法测试这个想法,因为我使用的两个数据库 MS SQL 不受 SqlAlchemy-Migrate 支持,并且 sqlite 不支持约束的“alter table”。我确实让 SQLAlchemy 尝试通过删除 sqlite 表上的引用约束来删除 FK,所以它看起来不错。 YMMV。
I believe you can achieve this with SQLAlchemy-Migrate. Note that a ForeignKey is on an isolated column. A ForeignKeyConstraint is at the table level and relates the columns together. If you look at the ForeignKey object on the column you will see that it references a ForeignKeyConstraint.
I would unable to test this idea because of the two databases I use MS SQL isn't supported by SqlAlchemy-Migrate and sqlite doesn't support "alter table" for constraints. I did get SQLAlchemy to try to remove a FK via a drop on the references constraint on a sqlite table so it was looking good. YMMV.
好吧,您可以在 sqlalchemy 中实现此目的:只需在
drop()
列之前drop()
删除所有约束(理论上,您可能有多个约束):Well, you can achieve this in sqlalchemy: just
drop()
the all the constraints before youdrop()
the column (theoretically, you might have multiple constraints):