PostgreSQL 中的主键 reasonable/necessary 是否有基本的 CHECK 约束?
Are basic CHECK constraints on primary keys reasonable/necessary in PostgreSQL?
因此,我们几乎将 postgres 数据库用作整个后端。我们在各个列上有很多检查约束,以确保输入的任何数据都是有效的。
但是,如何检查主键呢? postgres 或 SQL 标准通常会自动施加任何特定条件吗?在我看来,设置 SERIAL PRIMARY KEY 仅具有值必须唯一的约束,但至少有 ID 大于零的一般原则。这个 可以 被像
这样的约束覆盖
ALTER TABLE table_name ADD CONSTRAINT check_id_positive CHECK ( id > 0 );
这在理论上是有道理的,但对我来说似乎有点矫枉过正。任何指导?同样,就像我说的那样,我们希望尽可能多地进行数据验证,因为我们可以在这里给出用例。我只是不确定这是否完全疯狂和过度。
您是在寻求指导,但没有提供很多方法来评估建议,所以这与其他任何意见一样多...
SQL(和 postgres)只需要主键是唯一的。通常的做法要求它是不可变的。
在主键的唯一性之外添加额外的约束是一个坏主意 - 它会将业务规则(本质上会发生变化)嵌入到数据库的架构中。这就是为什么大多数人推荐自动生成代理键的原因 - 输入错误的风险较小(哦,我在您的社会安全号码中切换了两位数)或业务变更(我们现在允许两个人共享相同的社会安全号码,因为我们有来自国外的人在系统中,并且不能保证加拿大社会安全号码与美国社会安全号码是唯一的。
添加约束是因为某些感觉 "icky" 似乎不合理 - 它使您的数据库更难用于那些不同意您的特殊感觉的人 - 那些可怜的前端开发人员试图弄清楚为什么一个完全合理的寻找插入语句失败现在必须阅读更多手册。
使用约束会导致性能下降 - 这应该不是什么大问题,但仍值得注意。
最后,作为一般规则,我赞成通过数据库机制执行 "relational" 逻辑 - 不是空的,唯一的,可以在外键表中找到 - 但将业务逻辑留在数据库之外(必须 > 0,至少应包含 1 个数字和 1 个特殊字符,必须符合正则表达式)。
业务规则往往比我们想象的更易变,数据库架构更改比更改数据库外部代码的风险更大。
一般来说,您应该在数据库中执行尽可能多的相关规则,否则它们将被违反。与在某些应用程序或 UI 层中以程序方式执行相比,在数据库中使用声明性约束来实施完整性要简单、可靠和高效得多。它甚至可以使查询更快,具体取决于您的 DMBS 在语义优化方面的熟练程度。
更具体地说,您似乎在询问 surrogate 键的约束,不一定是 primary 键。一个键是否是主键与任何事情都没有什么关系,所以我建议你编辑你的问题。
再笼统地说,对键(或键列)的约束当然是有效和有用的。如果您的 DBMS 支持用户定义的类型,自然键通常具有应在数据库中强制执行的特定格式,最好作为类型约束。
但是代理键本身通常没有任何意义或结构——它唯一的要求是它的值是唯一的。甚至没有任何合乎逻辑的理由让它成为一个整数;它可以是任何东西,尽管通常出于实际原因选择整数。因此,对于 "pure" 代理键,根据定义,除了您的 DBMS 已经处理的唯一性和琐碎的类型约束之外,没有任何规则可以强制执行。
您想要强制执行正值 ID 的原因似乎是出于审美考虑,而不是基于现实世界的要求。如果你遇到一个零值或负值的 id,它实际上是一个错误(不一致)吗?如果是这样,一定要添加约束(但要记录对它的需求)。如果没有,就不要。
最后一件事:如果曾经手动输入代理键值(例如,在某些 UI 或临时查询中),自动递增整数代理是危险的。只需要一个微不足道的打字错误——遗漏、添加、换位——就可以识别出错误的元组。在这种情况下,您的代理 ID 应该包含一个或多个检查 digits/characters 以捕获大多数(当然不是全部)此类错误;并且这些 id 的有效性绝对应该通过约束来检查。
因此,我们几乎将 postgres 数据库用作整个后端。我们在各个列上有很多检查约束,以确保输入的任何数据都是有效的。
但是,如何检查主键呢? postgres 或 SQL 标准通常会自动施加任何特定条件吗?在我看来,设置 SERIAL PRIMARY KEY 仅具有值必须唯一的约束,但至少有 ID 大于零的一般原则。这个 可以 被像
这样的约束覆盖ALTER TABLE table_name ADD CONSTRAINT check_id_positive CHECK ( id > 0 );
这在理论上是有道理的,但对我来说似乎有点矫枉过正。任何指导?同样,就像我说的那样,我们希望尽可能多地进行数据验证,因为我们可以在这里给出用例。我只是不确定这是否完全疯狂和过度。
您是在寻求指导,但没有提供很多方法来评估建议,所以这与其他任何意见一样多...
SQL(和 postgres)只需要主键是唯一的。通常的做法要求它是不可变的。
在主键的唯一性之外添加额外的约束是一个坏主意 - 它会将业务规则(本质上会发生变化)嵌入到数据库的架构中。这就是为什么大多数人推荐自动生成代理键的原因 - 输入错误的风险较小(哦,我在您的社会安全号码中切换了两位数)或业务变更(我们现在允许两个人共享相同的社会安全号码,因为我们有来自国外的人在系统中,并且不能保证加拿大社会安全号码与美国社会安全号码是唯一的。
添加约束是因为某些感觉 "icky" 似乎不合理 - 它使您的数据库更难用于那些不同意您的特殊感觉的人 - 那些可怜的前端开发人员试图弄清楚为什么一个完全合理的寻找插入语句失败现在必须阅读更多手册。
使用约束会导致性能下降 - 这应该不是什么大问题,但仍值得注意。
最后,作为一般规则,我赞成通过数据库机制执行 "relational" 逻辑 - 不是空的,唯一的,可以在外键表中找到 - 但将业务逻辑留在数据库之外(必须 > 0,至少应包含 1 个数字和 1 个特殊字符,必须符合正则表达式)。
业务规则往往比我们想象的更易变,数据库架构更改比更改数据库外部代码的风险更大。
一般来说,您应该在数据库中执行尽可能多的相关规则,否则它们将被违反。与在某些应用程序或 UI 层中以程序方式执行相比,在数据库中使用声明性约束来实施完整性要简单、可靠和高效得多。它甚至可以使查询更快,具体取决于您的 DMBS 在语义优化方面的熟练程度。
更具体地说,您似乎在询问 surrogate 键的约束,不一定是 primary 键。一个键是否是主键与任何事情都没有什么关系,所以我建议你编辑你的问题。
再笼统地说,对键(或键列)的约束当然是有效和有用的。如果您的 DBMS 支持用户定义的类型,自然键通常具有应在数据库中强制执行的特定格式,最好作为类型约束。
但是代理键本身通常没有任何意义或结构——它唯一的要求是它的值是唯一的。甚至没有任何合乎逻辑的理由让它成为一个整数;它可以是任何东西,尽管通常出于实际原因选择整数。因此,对于 "pure" 代理键,根据定义,除了您的 DBMS 已经处理的唯一性和琐碎的类型约束之外,没有任何规则可以强制执行。
您想要强制执行正值 ID 的原因似乎是出于审美考虑,而不是基于现实世界的要求。如果你遇到一个零值或负值的 id,它实际上是一个错误(不一致)吗?如果是这样,一定要添加约束(但要记录对它的需求)。如果没有,就不要。
最后一件事:如果曾经手动输入代理键值(例如,在某些 UI 或临时查询中),自动递增整数代理是危险的。只需要一个微不足道的打字错误——遗漏、添加、换位——就可以识别出错误的元组。在这种情况下,您的代理 ID 应该包含一个或多个检查 digits/characters 以捕获大多数(当然不是全部)此类错误;并且这些 id 的有效性绝对应该通过约束来检查。