这是一个简单的问题。 我一直在玩SQLAlchemy而我现在处理表中的唯一约束。 因此,当违反Unique Constraint时,会引发IntegrityError异常。如果我为表定义了多个唯一约束,我如何通过引发的异常来区分它们?
编辑: 我在下面使用sqlite3。
最终编辑: AVC答案通过检查违反约束的列的消息错误来提供替代解决方案。它不是一个优雅的解决方案,但它完成了工作。
答案 0 :(得分:1)
完整性错误将告诉您哪个列违反了约束。对于example:
IntegrityError: (IntegrityError) insert or update on table "my_table"
violates foreign key constraint "my_table_some_column_fkey"
在你的情况下,你正在声明你的约束:
UniqueConstraint('datapath_port_id', 'datapath_id',
'controller_id', name='unique_registration')
你在这里做的是不声明多个唯一性约束。这看起来像这样:
Column('datapath_port_id', unique=True)
Column('datapath_id', unique=True)
Column('controller_id', unique=True)
相反,您已经创建了多列或复合唯一性约束,这意味着所有三列的组合必须是唯一的。
因此,如果您的数据库行A, B, C
具有多列唯一性约束,即使第一行中已存在值A, A, A
,您仍可以插入A
。同样,B, B, B
和C, C, C
也是有效插入。但是失败的是尝试再次插入A, B, C
。这是因为所有列都与现有行匹配,这就是您查看的唯一性错误列出所有列的原因。
以下是代码示例:
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer
from sqlalchemy import UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()
class Test(Base):
__tablename__ = 'test'
__table_args__ = (
UniqueConstraint('a', 'b', name='ab_constraint'),
UniqueConstraint('b', 'c', name='bc_constraint'))
id = Column(Integer, primary_key=True)
a = Column(Integer)
b = Column(Integer)
c = Column(Integer)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
session.add(Test(a=1, b=1, c=1))
session.add(Test(a=2, b=2, c=2))
从那里我们可以尝试违反不同的唯一性约束来看看会发生什么。如果尝试运行此命令:
session.add(Test(a=1, b=1, c=2))
session.commit()
我们得到:
sqlalchemy.exc.IntegrityError: (IntegrityError) UNIQUE constraint failed: test.a, test.b u'INSERT INTO test (a, b, c) VALUES (?, ?, ?)' (1, 1, 2)
然后如果我们试图违反第二个约束:
session.add(Test(a=1, b=2, c=2))
session.commit()
我们反而得到:
sqlalchemy.exc.IntegrityError: (IntegrityError) UNIQUE constraint failed: test.b, test.c u'INSERT INTO test (a, b, c) VALUES (?, ?, ?)' (1, 2, 2)
第一个案例指定test.a
和test.b
违反了约束,第二个案例指定了test.b
和test.c
。
我为这些约束选择的名称(ab_constraint
和bc_constraint
)不包含在响应中。然而,它们 存在于数据库级别。我们可以通过回显数据库创建命令来看到这一点:
CREATE TABLE test (
id INTEGER NOT NULL,
a INTEGER,
b INTEGER,
c INTEGER,
PRIMARY KEY (id),
CONSTRAINT ab_constraint UNIQUE (a, b),
CONSTRAINT bc_constraint UNIQUE (b, c)
)
但是,即使在数据库级别(我使用SQLite),错误消息中也没有使用约束名称:
sqlite> INSERT INTO test (a, b, c) VALUES (1, 1, 1);
sqlite> INSERT INTO test (a, b, c) VALUES (2, 2, 2);
sqlite> INSERT INTO test (a, b, c) VALUES (1, 1, 2);
Error: UNIQUE constraint failed: test.a, test.b