复合唯一约束与函数

3 投票
2 回答
1010 浏览
提问于 2025-04-15 14:45

我有一个关于SQLAlchemy的小问题...

我有一个叫“Document”的类,它有两个属性:“Number”和“Date”。我想确保在同一年里,数字“Number”不能重复。请问有没有办法在“Number”和“Date”的年份上设置一个唯一约束?我应该用唯一索引吗?那我该怎么声明这个功能部分呢?

(SQLAlchemy 0.5.5,PostgreSQL 8.3.4)

谢谢大家!

2 个回答

-1

我很确定,唯一约束只能应用在已经有数据的列上,而不能应用在运行时计算的表达式上。因此,你需要创建一个额外的列,专门存放你的date中的year部分,然后你可以在这个列和number列上设置唯一约束。为了更好地使用这种方法,或许你可以把date拆分成三个单独的列,分别存放日期的天、月和年部分。这可以通过在表的定义中设置默认约束来实现。

4

你应该使用一个功能性唯一索引来应用这个约束。可惜的是,SQLAlchemy中的数据库通用模式定义工具还不支持功能性索引。你需要使用DDL结构来注册自定义的模式定义条款。如果你是用声明式的方法来定义你的模式,可以在你的类定义后面添加以下内容:

DDL(
    "CREATE UNIQUE INDEX doc_year_num_uniq ON %(fullname)s "
    "(EXTRACT(YEAR FROM date), number)"
).execute_at('after-create', Document.__table__)

这个方法效果很好,但在v0.7版本中会抛出一个SADeprecation警告。我成功使用的语法如下:

from sqlalchemy import event

event.listen(ModelObject.__table__,
         'after_create',
          DDL("CREATE UNIQUE INDEX term_year ON %(fullname)s "
              "(EXTRACT(YEAR FROM start_date), term)",
              on = 'postgresql'
              )
         )

撰写回答