在不解析错误消息的情况下获取有关完整性约束违规错误的信息

Posted

技术标签:

【中文标题】在不解析错误消息的情况下获取有关完整性约束违规错误的信息【英文标题】:Getting information about integrity constraint violation error without parsing error message 【发布时间】:2021-11-07 02:31:26 【问题描述】:

我正在使用 SQLAlchemy + psycopg2 构建一个公开数据库的 API。

我想在违反唯一或外键约束的情况下生成有用的错误消息。就像错误中涉及的字段的名称一样。

AFAIU,我应该能够从 PostgreSQL 获取约束名称。这将使我从约束名称中获取字段的工作。我现在关注的部分是获取该约束名称。

我捕获sqla.exc.IntegrityError,然后通过orig 属性访问底层的psycopg2 异常。例如,它可能是 psycopg2.errors.UniqueViolationpsycopg2.errors.ForeignKeyViolation

我不知道如何获得有关错误的额外信息。

This answer指向this PostgreSQL doc page,涉及SQL语句。

有没有办法让 psycopg2 为我执行此操作并将这些额外信息添加到异常中?

还有其他获取信息的方法吗?

我需要访问一些错误消息并对其进行解析吗?


编辑

感谢@Ian Wilson's answer,我想出了这个(以下示例仅详细说明违反唯一约束):

if isinstance(exc, sqla.exc.IntegrityError):
    if isinstance(exc.orig, ppe.UniqueViolation):
        # Get table and constraint name from diag info
        table_name = exc.orig.diag.table_name
        constraint_name = exc.orig.diag.constraint_name
        # Inspect DB to get constraint object
        inspector = sqla.inspect(db_engine)
        unique_constraints = inspector.get_unique_constraints(table_name)
        constraint = next(
            c for c in unique_constraints
            if c['name'] == constraint_name
        )
        # Get column names from object
        column_names = constraint['column_names']

【问题讨论】:

【参考方案1】:

您可以通过e.__cause__.diag.constraint_name 找到约束名称。我从未听说过,但发现我链接的一个相关问题似乎提供了您需要的信息。

IntegrityError: distinguish between unique constraint and not null violations

还想补充一点,我之前在使用 alembic 时遇到了隐式约束名称的问题,因此如果出现这种情况,您可能需要设置约定。我认为这主要与从 db 反射回来有关,但隐含的名称可能会使查找相关列变得困难。

configuring-constraint-naming-conventions

【讨论】:

看准了!谢谢。 diag 是我所追求的,我只是在互联网上找不到它。我确实看到了这个问题,但不知何故错过了答案的那一部分。我使用orig 来访问底层的 psycopg2 异常。我无法区分__cause__。我查看了代码,似乎没有一个被弃用而有利于另一个。 也感谢关于约束名称的有趣评论。最后我不需要它(请参阅我的问题编辑),但在考虑迁移时我会记住它。

以上是关于在不解析错误消息的情况下获取有关完整性约束违规错误的信息的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 7 错误 - SQLSTATE [23000]:完整性约束违规:1048 列 'first_name' 不能为空

Magento DB错误:完整性约束违规:1452无法添加或更新子行:外键约束失败

SQLSTATE [23000]:完整性约束违规:1452无法添加或更新子行:外键约束失败 - Laravel

完整性约束违规:1048 Column 'user_id' cannot be null 分配角色时发生错误(Laravel 5.3)

EF 6 代码首先,在导航属性上使用包含更改外键 ID 会导致“发生引用完整性约束违规”错误

Laravel 外键约束报错