【发布时间】:2019-08-25 13:43:27
【问题描述】:
我有一个表格,用于为客户定义默认和自定义选项。如果custom_id 字段有一个值,那么它代表一个独特的自定义作业的记录。如果为空,则记录代表客户端的默认选项。
我的问题是我想在两种情况下强制执行唯一性:
-
custom_id、client和option都是非空的 -
client和option不为空,但custom_id为空
下面的表定义适用于第一种情况,但不适用于第二种情况,因为 null 不被视为值。有没有办法让 null 被视为一个值?
class OptionTable(Base):
__tablename__ = "option_table"
__table_args__ = (
UniqueConstraint("custom", "client", "option", name="uix_custom_client_option"),
)
id = Column(Integer, primary_key=True)
custom_id = Column(Integer, ForeignKey("custom.id"), nullable=True)
client = Column(String, nullable=False)
option = Column(String, nullable=False)
这是一些示例数据以及按顺序添加时的结果:
+----+----------+----------+--------+---------------------------------------------+
| id | CustomID | Client | Option | result |
+----+----------+----------+--------+---------------------------------------------+
| 1 | 123 | MegaCorp | Apple | OK |
| 2 | 123 | MegaCorp | Apple | not unique |
| 3 | NULL | MegaCorp | Apple | OK |
| 4 | NULL | MegaCorp | Google | OK |
| 5 | NULL | MegaCorp | Google | this one should fail, but currently doesn't |
+----+----------+----------+--------+---------------------------------------------+
这个related answer 使用MySQL 完成了我正在寻找的工作。理想的解决方案是使用 sqlalchemy。
【问题讨论】:
-
您能否提供示例数据来帮助您解释您的目标?
-
documentation 表明这是标准 SQL 行为; NULL 不能违反唯一性约束。您需要一个实际值来指示缺少自定义 ID。
-
@chepner 是的,这绝对是标准的 SQL 行为。我在问是否有办法使用 sqlalchemy 解决它
-
有一个相关的问题,它在 MySQL 的插入和更新语句之前实现了我正在寻找的内容。添加到问题中。
-
问题是您的数据库本身(SQLAlchemy 只是一个接口)允许第 5 行。我建议使用不可为空的布尔值“has_custom”列而不是自定义 ID 本身在唯一性约束中。 (当然,问题就变成了阻止记录具有两列的 True/Null 组合。)
标签: python postgresql sqlalchemy