@@ -199,6 +199,18 @@ def has_table(table_name: str) -> bool:
199199 return table_exists
200200
201201
202+ def get_foreign_key_names (table_name : str ) -> set [str ]:
203+ """
204+ Get the set of foreign key constraint names for a table.
205+
206+ :param table_name: The table name
207+ :returns: A set of foreign key constraint names
208+ """
209+ connection = op .get_bind ()
210+ inspector = Inspector .from_engine (connection )
211+ return {fk ["name" ] for fk in inspector .get_foreign_keys (table_name )}
212+
213+
202214def drop_fks_for_table (
203215 table_name : str , foreign_key_names : list [str ] | None = None
204216) -> None :
@@ -211,13 +223,12 @@ def drop_fks_for_table(
211223 If None is provided, all will be dropped.
212224 """
213225 connection = op .get_bind ()
214- inspector = Inspector .from_engine (connection )
215226
216227 if isinstance (connection .dialect , SQLiteDialect ):
217228 return # sqlite doesn't like constraints
218229
219230 if has_table (table_name ):
220- existing_fks = { fk [ "name" ] for fk in inspector . get_foreign_keys (table_name )}
231+ existing_fks = get_foreign_key_names (table_name )
221232
222233 # What to delete based on whether the list was passed
223234 if foreign_key_names is not None :
@@ -523,6 +534,18 @@ def create_fks_for_table(
523534 )
524535 return
525536
537+ if foreign_key_name in get_foreign_key_names (table_name ):
538+ logger .info (
539+ "Foreign key %s%s%s already exists on table %s%s%s. Skipping..." ,
540+ GREEN ,
541+ foreign_key_name ,
542+ RESET ,
543+ GREEN ,
544+ table_name ,
545+ RESET ,
546+ )
547+ return
548+
526549 if isinstance (connection .dialect , SQLiteDialect ):
527550 # SQLite requires batch mode since ALTER TABLE is limited
528551 with op .batch_alter_table (table_name ) as batch_op :
0 commit comments