SqlAlchemy如何处理表定义中的唯一约束

dud*_*ein 6 sqlalchemy unique

我有一个表格,其中包含以下声明性定义:

class Type(Base):
    __tablename__ = 'Type'
    id = Column(Integer, primary_key=True)
    name = Column(String, unique = True)
    def __init__(self, name):
        self.name = name
Run Code Online (Sandbox Code Playgroud)

列"name"有一个唯一的约束,但我能做到

type1 = Type('name1')
session.add(type1)
type2 = Type(type1.name)
session.add(type2)
Run Code Online (Sandbox Code Playgroud)

因此,可以看出,根本没有检查唯一约束,因为我已经在会话中添加了2个具有相同名称的对象.

当我这样做时session.commit(),我得到一个mysql错误,因为约束也在mysql表中.

是否有可能sqlalchemy提前告诉我,我无法制作或识别它,并且不会插入两个具有相同"名称"columm的条目?如果没有,我应该在内存中保留所有现有名称,以便在创建对象之前我可以检查它们是否存在吗?

Den*_*ach 9

SQLAlechemy不处理uniquness,因为它不可能做得很好.即使您跟踪创建的对象和/或检查是否存在具有此类名称的对象,也存在竞争条件:其他进程中的任何人都可以使用您刚检查的名称插入新对象.唯一的解决方案是在检查之前锁定整个表并在插入后释放锁(某些数据库支持这种锁定).

  • @duduklein它没有处理唯一性.我的答案描述了原因. (4认同)

小智 6

AFAIK,sqlalchemy不处理python行为中的唯一性约束.那些"unique = True"声明仅用于强制实施数据库级表约束,并且只有在使用sqlalchemy命令创建表时才会使用,即

Type.__table__.create(engine)
Run Code Online (Sandbox Code Playgroud)

或者其他一些.如果针对实际上不存在此约束的现有表创建SA模型,则它就好像它不存在一样.

根据您的具体用例,您可能需要使用类似的模式

try:
  existing = session.query(Type).filter_by(name='name1').one()
  # do something with existing
except:
  newobj = Type('name1')
  session.add(newobj)
Run Code Online (Sandbox Code Playgroud)

或者变体,或者你只需​​捕获mysql异常并从那里恢复.