25

我想处理存在主键或唯一键冲突的情况,即重复条目。为此,我正在捕获IntegrityError,它可以很好地捕获错误。问题是,我似乎找不到任何简单的错误消息或错误代码来检查。我得到的只是IntegrityError.message属性,它是一个如下所示的字符串:

(IntegrityError)(1062,“重复条目'foobar'键'name'”)

这不是很有帮助。使用它,我将不得不开始为他们的代码和消息解析错误消息。调用dir异常仅显示以下属性:

'args'、'connection_invalidated'、'instance'、'message'、'orig'、'params'、'statement'

args只是一个包含上述字符串的单项元组,并且params是我尝试插入的数据。我似乎找不到任何方法来确定这实际上是一个重复的键错误,而不必开始使用正则表达式或其他东西解析错误消息。

任何人都可以对这个问题有所了解吗?

4

2 回答 2

44

通过更仔细地阅读文档,我在编写问题时发现了这一点。我仍然会发布这个,因为它可能对某人有帮助。

在 SQLAlchemy DBAPIError的文档中, IntegrityError是从该文档中继承的,它解释了异常只是底层数据库 API 错误的包装,并且原始错误保存为orig异常。果然,调用e.orig.args我得到一个组织良好的元组:

(1062,“重复条目 'foobar' 键 'name'”)

于 2012-07-26T04:13:34.320 回答
1

据我所知,唯一的方法是解析异常中的错误字符串。我找不到任何指定错误的元组、违反唯一性约束的列和值。

具体来说,可以使用子字符串搜索运算符或正则表达式来搜索异常消息。例如:

    db.session.add(SupplierUser(supplier_id=supplier_id, username=username, password=password, creator=user))
    try:
        db.session.commit()
    except IntegrityError as err:
        db.session.rollback()
        if "UNIQUE constraint failed: user.username" in str(err):
            return False, "error, username already exists (%s)" % username
        elif "FOREIGN KEY constraint failed" in str(err):
            return False, "supplier does not exist"
        else:
            return False, "unknown error adding user"

但是,这些字符串可能会很长,因为包含 SQL 语句,例如:

(sqlite3.IntegrityError) UNIQUE constraint failed: user.username [SQL: 'INSERT INTO user (username, password_hash, created_time, creator_id, role, is_active, supplier_id) VALUES (?, ?, ?, ?, ?, ?, ?)'] [parameters: ('bob', ...

因此,如果您搜索数据库错误消息,您将最小化解析异常的错误处理延迟,而无需从 sqlalchemy 添加信息。这可以通过检查 err.args 来完成,它应该更小:

'(sqlite3.IntegrityError) UNIQUE constraint failed: supplier_user.username',)

更新的示例:

    db.session.add(SupplierUser(supplier_id=supplier_id, username=username, password=password, creator=user))
    try:
        db.session.commit()
    except IntegrityError as err:
        db.session.rollback()
        err_msg = err.args[0]
        if "UNIQUE constraint failed: supplier_user.username" in err_msg:
            return False, "error, supplier username already exists (%s)" % username
        elif "FOREIGN KEY constraint failed" in err_msg:
            return False, "supplier does not exist"
        else:
            return False, "unknown error adding user"

注意我在这里使用的错误语法是针对 sqlite3 的。解析 mysql 异常错误消息,例如:

(1062, "Duplicate entry 'usr544' for key 'username'")

可以使用适当的正则表达式来完成。请注意,它看起来像一个元组,但它实际上是一个字符串(sqlalchemy 版本 1.1.3 和 mysql 5.5)。

例如:

    except IntegrityError as err:
        db.session.rollback()
        if re.match("(.*)Duplicate entry(.*)for key 'username'(.*)", err.args[0]):
    .... etc .... 
于 2016-12-13T11:24:44.123 回答