我对数据库表的列有很多不同的约束。插入到数据库中的数据通常包含数字数组(在这些数字上设置了约束),例如(DDL的一部分):
CREATE TABLE "Object" (
id INTEGER NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(id) REFERENCES "Generic" (id) // Inheritance
);
CREATE TABLE "ObjectData" (
id INTEGER NOT NULL,
x FLOAT NOT NULL,
y FLOAT NOT NULL,
d FLOAT NOT NULL,
a FLOAT NOT NULL,
e FLOAT NOT NULL,
object_id INTEGER NOT NULL,
PRIMARY KEY (id),
CONSTRAINT "duplicate x, y values" UNIQUE (x, y, object_id),
CONSTRAINT "x must be >= -1.0" CHECK (x >= 0.0),
CONSTRAINT "x must be <= 1.0" CHECK (x <= 1.0),
CONSTRAINT "y must be >= -1.0" CHECK (y >= -1.0),
CONSTRAINT "y must be <= 1.0" CHECK (y <= 1.0),
CONSTRAINT "d must be >= -1.0" CHECK (d >= 0.0),
CONSTRAINT "d must be <= 1.0" CHECK (d <= 1.0),
CONSTRAINT "a must be >= -270.0" CHECK (a >= -270.0),
CONSTRAINT "a must be <= 270.0" CHECK (a <= 270.0),
CONSTRAINT "e must be >= -1.0" CHECK (e >= -1.0),
CONSTRAINT "e must be <= 1.0" CHECK (e <= 1.0),
FOREIGN KEY(object_id) REFERENCES "Object" (id)
);
插入数据如下所示(解析为插入数据库的输入文本文件的一部分):
DATA:
-1.0 -1.0 1.0 242.0 0.0
-1.0 -2.0 1.0 124.0 0.0
-1.0 -1.0 1.0 109.0 0.0
...........................
-1.0 -1.0 1.0 242.0 0.0
-1.0 -2.0 1.0 124.0 0.0
-1.0 -1.0 1.0 109.0 0.0
因此,如果这些值中的任何一个违反了约束之一并且没有消息显示,则很难确定哪个值是坏的。为此,给出了约束的描述性名称。通过 SQLAlchemy ORM 执行 SQLite3 数据库,当sqlalchemy.exc.IntegretyError发生时,此库完全切断违反约束的名称。
在SQLite3中的IntegrityError异常中存在约束名称的Google搜索结果已从[版本3.3.2] [1]开始。这显示了Python REPL中的简短测试:
>>> import sqlite3
>>> conn = sqlite3.connect('test/test.db')
>>> c = conn.cursor()
>>> c.execute("""INSERT INTO "ObjectData" (x, y, d, a, e, object_id) VALUES (?, ?, ?, ?, ?, ?)""", (-2.0, -1.0, 1.0, 242.0, 0.0, 1))
Traceback (most recent call last):
File "<input>", line 1, in <module>
IntegrityError: CHECK constraint failed: x must be >= -1.0
但是当我尝试使用SQLAlchemy插入数据时,我只收到无法描述错误的消息。这里是dir(错误)的结果:
detail = []
params = (-2.0, -1.0, 1.0, 242.0, 0.0, 1)
statement = INSERT INTO "ObjectData" (x, y, d, a, e, object_id) VALUES (?, ?, ?, ?, ?, ?)
instance = <bound method type.instance of <class 'sqlalchemy.exc.IntegrityError'>>
args = ('(IntegrityError) constraint failed',)
orig = constraint failed
orig.message = constraint failed
所以问题是有没有办法强制SQLAlchemy返回违反的约束名称,因为它大大简化了代码并允许向用户显示有关错误的信息性消息?或者可能存在其他方式?
答案 0 :(得分:1)
我发现SQLAlchemy库使用有什么问题。当我在调试模式下运行软件并在引发IntegrityError异常时断开(在SQLAlchemy库的DBAPIError.instance方法中设置断点)然后我意识到原始错误类型是类'pysqlite2._sqlite.Error'而不是sqlite3。似乎在site-package库中,pysqlite2已经安装在我的Python环境中,但这与sqlite3不同。我尝试使用简单的解决方法:从site-package中删除pysqlite2目录。之后,原始异常类型变为类'sqlite3.Error',而异常中的orig.message包含我期望的内容。很明显SQLAlchemy默认使用pysqlite2库而不是内置的sqlite3库。