10

SQLAlchemy Migrate を使用してデータベースの変更を追跡していますが、外部キーの削除に関する問題が発生しています。2 つのテーブルがあります。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で外部キーを削除する方法がわかりませんか? 外部キーを削除してから列を削除するにはどうすればよいですか?

4

4 に答える 4

7

sqlalchemy.migrate で実行できます。

それを機能させるために、Column('fk', ForeignKey('fk_table.field')) で暗黙的にではなく、明示的に外部キー制約を作成する必要がありました。

残念ながら、これを行う代わりに:

p2 = Table('tablename',
            metadata,
            Column('id', Integer, primary_key=True),
            Column('fk', ForeignKey('fk_table.field')),
            mysql_engine='InnoDB',
           )

それを行う:

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()

次に、削除プロセスは次のようになります。

def downgrade(migrate_engine):
     # First drop the constraint
     ForeignKeyConstraint(columns=[p2.c.fk], refcolumns=[p3.c.id]).drop()
     # Then drop the table
     p2.drop()
于 2011-03-28T17:01:19.940 に答える
3

これは、別のメタデータ インスタンスを作成し、Session.execute() を使用して生の SQL を実行することで実現できました。理想的には、sqlalchemy のみを使用するソリューションがあるため、MySQL 固有のソリューションを使用する必要はありません。しかし、今のところ、私はそのような解決策を認識していません。

于 2010-03-11T19:23:44.230 に答える
0

SQLAlchemy-Migrateでこれを達成できると思います。ForeignKeyは分離された列にあることに注意してください。ForeignKeyConstraintはテーブルレベルにあり、列を相互に関連付けます。列のForeignKeyオブジェクトを見ると、ForeignKeyConstraintを参照していることがわかります。

私が使用している2つのデータベースがMSSQLをSqlAlchemy-Migrateでサポートしておらず、sqliteが制約の「altertable」をサポートしていないため、このアイデアをテストできません。SQLAlchemyに、sqliteテーブルの参照制約を削除してFKを削除しようとしたので、見栄えがしました。YMMV。

于 2011-02-22T16:38:35.650 に答える
-1

まあ、これは sqlalchemy で実現できます:列のdrop()前にあるすべての制約だけですdrop()(理論的には、複数の制約があるかもしれません):

def drop_column(column):
    for fk in column.table.foreign_keys:
        if fk.column == column:
            print 'deleting fk ', fk
            fk.drop()
    column.drop()

drop_column(t_exists.c.new_id)
于 2010-03-15T20:12:48.490 に答える