@
ryd994 我没有数据库应用必须强制一定要用外键的想法, 这看应用的类型. 你用不用是你的事情, 如果你觉得对你自己有益. 在一些应用类型中, 正确的使用外键是必要的, 这些应用类型典型的例子就是进销存, erp . 而且,这些软件当前也正在互联网化, 但不能用所谓的全部的互联网思维去做的. 就好比学 nodejs 就是后端的想法一样.
具体分析一下
外键的三个作用
1. 值必须存在
2. 级联更新
3. 级联删除
由于最近几年只用 postgresql , 我只知道我的 postgresql 默认生成的外键 2 和 3 都是 no action, 也就是根本不用考虑 ls 一些帖子所谓的级联删除的问题. 这个设置现在多在 orm 配置层面比方说 sqlalchemy 的 cascade 选项, 也就是说还是在业务逻辑层面上,出现了级联删除和更新,是你的业务代码如此定义了
那么讨论 1 值必须存在, 如果表中插入一个不存在的值会怎么样, 显然针对这个表的统计都会出错, 对于某些应用类型, 这些应用通常是
1. 实时统计. 报表不是定时生成的(定时生成的会对数据清理), 而是实时统计当前数据
2. 各种关系到钱的, 错不得
为了达到防止插入一个不存在的值, 解决方案就是在插入和更新时检查, 这里有个最大的问题就是, 你假定了所有的操作都会通过你的业务代码. 但实际企业应用场景. 维护, 第三方等都可能会接触你的数据库, 修改你的数据库, 你自己的应用随着逻辑的增加(这很正常)都可能会忘了检查, 导致这个逻辑被跳过,
这里同时要反驳一下 自己检查的性能和开发效率会高于 数据库, 简单的举个例子,
举一个 erp 中一个销售单据, 一般最少会引用多少个相关表
sale_orders
* employee_id 员工
* department_id 部门
* store_id 仓库
* partner_id 客户 /供应商
* logistics_company_id 物流公司
* logistics_product_type_id 物流公司产品类型
* 各种收款账户和类型
sale_order_lines
* product_id
* measure_unit_id
你自己的代码要 select 多少次, 企业软件通常是个大的整体应用, 表很多, 一般都用几百个, 像 axapta/oracle 这样的有几千个, 每个表基本都会引用一个或多个相关表, 没有外键, 自己每个表的更新插入都写业务逻辑, 不可想象
外键对同步的问题是显而易见的, 表同步时必须按顺序同步, 如果一个表示父子关系, 则必须按父子顺序同步.
erp 对同步要求比较少, 是因为 erp 这种应用, 就是你做 saas, 建议方案也是一租户一数据库(或一 schema), 自然的在分库分表, 而且 erp 软件通常会不会超过几年结转一次, 老的帐作为归档数据库仅仅用于查询. 分布式压力基本比较少. 但不同库中同步数据的需求还是有的, 有外键在的确是比较麻烦. 但这个就像上面所说的, 你对表的依赖性心里有数, 其实也不是个问题. 当然, 这个层面上不同应用有不同应用的策略. 我个人不在意这些.
外键更多的在我看来是一种防护, 如果你的应用对数据比较敏感, 报表必须实时生成, 而你又不能 100%保证数据是正确的,
我的建议, 还是用!
再次重申, 我没有让你们一定用外键的想法, 这关我什么事情呢? 只是外事得看场合