sqlalchemy:从相关表中删除行从多到许多关系中删除行

发布于 2025-01-28 09:51:18 字数 1475 浏览 1 评论 0原文

我注意到,在删除一个条目时,未删除辅助表中的相应行。在这里我的模型:

cashflows_tags_table = Table(
    "cashflows_tags",
    Base.metadata,
    Column("cashflow_id", ForeignKey("cashflows.id"),primary_key=True),
    Column("tag_id", ForeignKey("tags.id"), primary_key=True),
)

class Tag(Base):
    __tablename__ = "tags"

    id = Column(Integer, primary_key=True)
    tag = Column(String, nullable=False, unique=True)

class Cashflow(Base):
    __tablename__ = "cashflows"

    id = Column(Integer, primary_key=True)

    date = Column(DateTime, nullable=False)
    amount = Column(Float, nullable=False)
    description = Column(String, nullable=False)

    ### Many to Many ###
    tags = relationship("Tag", secondary=cashflows_tags_table)
    #######


我从文档中了解的内容( https://docs.sqlalchemy.org/en/14/orm/basic_relationships.html#deleting-rows-rows-from-the-the-the-the-the-the-many-to-many-t-many-table )删除应自动传播。其他级联/删除/删除 - 孔口会导致另一个“许多”侧的元素删除,这不是我想要的。

我正在使用sqlite,以及删除的以下ORM语法:

with Session(db_engine) as session:
            ddd = delete(Cashflow).where(Cashflow.id.in_(id_list))
            session.execute(ddd)
            session.commit()

最后

我在删除之前手动选择了该条目并清空标签集合(如其他线程中建议)。我仍然会把问题打开,因为我尚不清楚这是预期的行为

I noticed that when deleting one entry, the corresponding rows from the secondary table are not deleted. here my models:

cashflows_tags_table = Table(
    "cashflows_tags",
    Base.metadata,
    Column("cashflow_id", ForeignKey("cashflows.id"),primary_key=True),
    Column("tag_id", ForeignKey("tags.id"), primary_key=True),
)

class Tag(Base):
    __tablename__ = "tags"

    id = Column(Integer, primary_key=True)
    tag = Column(String, nullable=False, unique=True)

class Cashflow(Base):
    __tablename__ = "cashflows"

    id = Column(Integer, primary_key=True)

    date = Column(DateTime, nullable=False)
    amount = Column(Float, nullable=False)
    description = Column(String, nullable=False)

    ### Many to Many ###
    tags = relationship("Tag", secondary=cashflows_tags_table)
    #######


What I understand from the documentation (https://docs.sqlalchemy.org/en/14/orm/basic_relationships.html#deleting-rows-from-the-many-to-many-table) is that the deletion should be propagated automatically. Additional cascade/delete/delete-orphan would cause the deletion of the elements on the other "many" side, which is not what I want.

I am using sqlite, and the following ORM syntax for the deletion:

with Session(db_engine) as session:
            ddd = delete(Cashflow).where(Cashflow.id.in_(id_list))
            session.execute(ddd)
            session.commit()

EDIT

in the end I solved it manually selecting the entry and emptying the tag collection before the deletion (as suggested in other threads). I will still leave the question open, since it is not clear to me if this is the expected behaviour

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

因为看清所以看轻 2025-02-04 09:51:18

如果您不想设置级联反应, session.delete 将同时删除cashflow和相关的多对多记录。

cfs = s.scalars(sa.select(Cashflow).where(Cashflow.id.in_(id_list)))
for cs in cfs:
    session.delete(cf)

它将首先发射delete语句,然后CashFlow s。

另外,您也可以 >并将“级联”设置为 onDelete行为当使用 sqlachemy.delete

from sqlalchemy.engine import Engine

# Enable foreign keys (from the SQLAlchemy docs)

@sa.event.listens_for(Engine, 'connect')
def set_sqlite_pragma(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute('PRAGMA foreign_keys=ON')
    cursor.close()

cashflows_tags_table = sa.Table(
    'cashflows_tags',
    Base.metadata,
    sa.Column('cashflow_id', sa.ForeignKey('cashflows.id', ondelete='CASCADE'), primary_key=True),
    sa.Column('tag_id', sa.ForeignKey('tags.id'), primary_key=True),
)

If you don't want to set a cascade, session.delete will remove both the CashFlow and the associated many-to-many records.

cfs = s.scalars(sa.select(Cashflow).where(Cashflow.id.in_(id_list)))
for cs in cfs:
    session.delete(cf)

It will emit a DELETE statement for the many-to-many records first, then the CashFlows.

Alternatively, you can enable foreign keys in SQLite and set "CASCADE" as the ondelete behaviour for the foreign key in the association table - only rows associated with the CashFlow to be deleted will be deleted when using sqlachemy.delete.

from sqlalchemy.engine import Engine

# Enable foreign keys (from the SQLAlchemy docs)

@sa.event.listens_for(Engine, 'connect')
def set_sqlite_pragma(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute('PRAGMA foreign_keys=ON')
    cursor.close()

cashflows_tags_table = sa.Table(
    'cashflows_tags',
    Base.metadata,
    sa.Column('cashflow_id', sa.ForeignKey('cashflows.id', ondelete='CASCADE'), primary_key=True),
    sa.Column('tag_id', sa.ForeignKey('tags.id'), primary_key=True),
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文