在PostgreSQL中,对主键的基本CHECK约束是否合理/必要?

时间:2018-07-11 11:30:05

标签: postgresql database-design check-constraints

因此,我们几乎整个后端都使用了postgres数据库。我们在各列上都有很多检查约束,以确保输入的任何数据都是有效的。

但是,如何检查主键?一般而言,postgres或SQL标准是否会自动施加任何特定条件?在我看来,设置SERIAL PRIMARY KEY仅具有值必须唯一的约束,但是至少存在ID大于零的一般原则。这个可以覆盖有类似

的约束
ALTER TABLE table_name ADD CONSTRAINT check_id_positive CHECK ( id > 0 );

从理论上讲是有道理的,但对我来说似乎有点过头了。有指导吗?再次,就像我说的,我们要尽可能地最大化数据验证,并在此处给出用例。我只是不确定这是否完全疯狂和过度。

2 个答案:

答案 0 :(得分:1)

通常,您应在数据库中实施尽可能多的相关规则,否则将违反它们。与声明性约束相比,在数据库中强制执行完整性要比在某些应用程序或UI层中按过程进行操作更为简单,可靠和高效。根据您的DMBS在语义优化方面的熟练程度,它甚至可以使查询更快。

更具体地说,您似乎在问有关代理键的约束,而不一定是键。密钥是否为主键与任何事物都没有多大关系,所以我建议您编辑问题。

再说一遍,对键(或键列)的约束当然是有效和有用的。如果您的DBMS支持用户定义的类型,则自然键通常具有应在数据库中强制执行的特定格式,最好作为类型约束。

但是代理键本身通常没有任何含义或结构,它唯一的要求是其值必须唯一。甚至没有逻辑上的理由使它成为整数。尽管实际上出于实际原因经常选择整数,但它可以是任何东西。因此,对于“纯”代理键,根据定义,除了唯一性和琐碎的类型约束(您的DBMS已经处理过)之外,没有其他规则可以强制执行。

您想要强制使用正值ID的原因似乎很美,而不是基于现实世界的要求。如果您遇到ID为零或负值的ID,这实际上是一个错误(不一致)吗?如果是这样,则一定要添加约束(但要记录对它的需求)。如果没有,那就不要。

最后一件事:如果曾经手动输入代理键值(例如,在某些UI或临时查询中),则自动递增整数代理是危险的。只需要一个简单的输入错误(省略,加法,换位)即可识别错误的元组。在这种情况下,您的代理ID应包含一个或多个校验数字/字符,以捕获大多数(当然不是全部)此类错误;并且这些ID的有效性绝对应通过约束进行检查。

答案 1 :(得分:0)

您正在寻求指导,但没有提供许多评估建议的方法,因此,与其他任何东西一样,这是很多意见...

SQL(和postgres)对主键的唯一要求就是唯一。常规做法要求它是不变的。

在主键上添加除唯一性之外的其他约束是一个坏主意-将业务规则(本质上可能会发生变化)嵌入到数据库的架构中。这就是为什么大多数人推荐自动生成的代理密钥的原因-输入错误(哦,我在您的社会保险号中切换了两位数字)或业务变更(我们现在允许两个人共享相同的社会保险号)的风险较小系统中有来自国外的人,并且不能保证加拿大的社会保险号与美国的社会保险号是唯一的。

添加约束,因为感觉有些“不对劲”似乎是不合理的-它使您的数据库更难以用于那些不喜欢您的人-那些可怜的前端开发人员试图弄清楚为什么看起来看起来非常合理的插入语句失败了现在必须阅读更多手册。

使用约束会降低性能-这不是一个大问题,但仍然值得注意。

最后,作为一般规则,我倾向于通过数据库机制强制执行“关系”逻辑-不能在外键表中找到null,唯一性-而是将业务逻辑留在数据库之外(必须> 0,应包含至少一个数字和一个特殊字符,必须符合正则表达式)。

业务规则的波动性往往比我们想象的要大得多,与更改数据库外部的代码相比,更改数据库架构的风险更大。