为什么 Flask-SQLAlchemy 在“DROP TABLE IF EXISTS”找不到表时不引发异常?

问题描述 投票:0回答:1

我使用 Flask-SQLAlchemy(版本 2.5.1)和 Python 3.11 连接到 PostgreSQL 15 数据库。

我想使用 DROP TABLE IF EXISTS ... CASCADE 删除表(如果存在)。这是我的代码:

from sqlalchemy import text
from sqlalchemy.exc import SQLAlchemyError

try:
    sql = text("DROP TABLE IF EXISTS {table_name} CASCADE")
    db.session.execute(sql)
    db.session.commit()

except Exception as e:
    logger.error(f"Failed to drop {table_name} table: {str(e)}")

except SQLAlchemyError as e:
    db.session.rollback()
    logger.error(f"An error occurred: {str(e)}")

但是,当表不存在时,即使 PostgreSQL 日志显示以下内容,我也没有看到 Python 中引发任何异常:

LOG:  statement: DROP TABLE IF EXISTS devices CASCADE
NOTICE:  table "devices" does not exist, skipping
LOG:  statement: COMMIT

由于该表不存在,PostgreSQL 会记录一条通知,但在我的 Python 代码中没有传播任何异常。

我的问题是:

  1. 当表没有出现异常时,我是否应该预期会引发异常? 存在,传递“原始”SQL 语句?
  2. 有没有办法将数据库的状态消息绑定到我的Python 代码,这样我就可以更明确地处理这种情况?
  3. 在执行
    execute()
    commit()
    命令后,我是否应该手动检查数据库中的错误代码?
sqlalchemy flask-sqlalchemy
1个回答
0
投票
  1. 当表不存在时,我是否应该期望引发异常并传递“原始”SQL 语句?

    • 否:如果 PostgreSQL 这样做,SQLAlchemy 将引发异常,并且由于已指定
      IF EXISTS
      ,如果表不存在,PostgreSQL 将不会出错。
  2. 有没有办法将数据库的状态消息绑定到我的Python代码,以便我可以更明确地处理此类情况?

    • 如果需要,您可以记录
      NOTICE
      消息,但如果不检查日志则无法直接访问它们(或者至少没有记录的方法可以执行此操作)。请参阅注意日志记录的文档。
  3. 在execute()和commit()命令之后我应该手动检查数据库中的错误代码吗?

    • 没有理由这样做,除非由于某种原因您需要知道数据库已跳过删除不存在的表。

这是一个简单的例子:

import logging

import sqlalchemy as sa

logging.basicConfig()
logging.getLogger('sqlalchemy')
logging.getLogger('sqlalchemy.dialects.postgresql').setLevel(logging.INFO)

engine = sa.create_engine('postgresql+psycopg2:///so')

with engine.begin() as conn:
    conn.execute(sa.text("""DROP TABLE IF EXISTS t"""))

这会产生以下输出:

INFO:sqlalchemy.engine.Engine:select pg_catalog.version()
INFO:sqlalchemy.engine.Engine:[raw sql] {}
INFO:sqlalchemy.engine.Engine:select current_schema()
INFO:sqlalchemy.engine.Engine:[raw sql] {}
INFO:sqlalchemy.engine.Engine:show standard_conforming_strings
INFO:sqlalchemy.engine.Engine:[raw sql] {}
INFO:sqlalchemy.engine.Engine:BEGIN (implicit)
INFO:sqlalchemy.engine.Engine:DROP TABLE IF EXISTS t
INFO:sqlalchemy.engine.Engine:[generated in 0.00009s] {}
INFO:sqlalchemy.dialects.postgresql:NOTICE:  table "t" does not exist, skipping
INFO:sqlalchemy.engine.Engine:COMMIT
© www.soinside.com 2019 - 2024. All rights reserved.