How do I delete a foreign key constraint in SQLAlchemy?
Solution 1
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:
p2 = Table('tablename',
metadata,
Column('id', Integer, primary_key=True),
Column('fk', ForeignKey('fk_table.field')),
mysql_engine='InnoDB',
)
do that:
p2 = Table('tablename',
metadata,
Column('id', Integer, primary_key=True),
Column('fk', Integer, index=True),
mysql_engine='InnoDB',
)
ForeignKeyConstraint(columns=[p2.c.fk], refcolumns=[p3.c.id]).create()
Then the deletion process looks like this:
def downgrade(migrate_engine):
# First drop the constraint
ForeignKeyConstraint(columns=[p2.c.fk], refcolumns=[p3.c.id]).drop()
# Then drop the table
p2.drop()
Solution 2
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.
Comments
-
Travis about 2 years
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?
-
Travis over 14 yearsI tried this out, but got an error: 'ForeignKey' object has no attribute 'drop'. I checked out the docs but didn't see any way to do this: sqlalchemy.org/docs/reference/sqlalchemy/…
-
van over 14 yearsthis is fair, but show me the documentation of SA where Column has drop(): sqlalchemy.org/docs/reference/sqlalchemy/…
-
OrganicPanda over 13 years'SQLAlchemy-Migrate' adds drop(), create() and other niceties but it needs to be installed separately. See packages.python.org/sqlalchemy-migrate/index.html
-
Ben over 13 yearsSQLAlchemy-Migrate adds drop() and create() to ForeignKeyConstraint not ForeignKey.
-
a paid nerd about 13 yearsOut of curiosity, what was the SQL you executed?
-
mjallday over 11 yearsFor anyone who may run into this - ForeignKeyConstraint needs to be imported from
migrate
not fromsqlalchemy
.