V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
ljk
V2EX  ›  程序员

是什么理由让你彻底抛弃数据库的外键?

  •  1
     
  •   ljk · 2016-11-22 14:28:29 +08:00 · 25563 次点击
    这是一个创建于 2960 天前的主题,其中的信息可能已经有所发展或是发生改变。

    初涉后台开发未深,诚惶诚恐看 <SQL 反模式>,学习最佳实践。

    发现现在这个项目应用了不少反模式,其中最让我困惑的是,完全不使用外键,涉及到外键的逻辑全部在应用代码里实现。

    询问项目负责人,告知不使用数据库外键主要有两原因:

    1. 多台服务器不停机升级时,有可能数据库新加入的外键限制导致新程序没办法在旧数据库上跑
    2. 运维人员对数据库外键深恶痛绝(举例说唯品会就是这样做的)

    听起来只要是分布式的服务器热升级(第一点原因)、或者团队里有运维人员,就应该抛弃数据库外键了。

    业界都是这样做的吗?书上说的当真脱离了实际?

    谢不吝赐教。

    第 1 条附言  ·  2016-11-23 10:54:52 +08:00
    指教不少,收获颇多,先谢各位了。

    另外再请问一下,如果在代码里实现约束的话,那么当我要插入一条 student 的纪录时,想先验证它的 class_id 字段是否有效,这时是否要先来一句 SELECT sql 查一下 class 表里有没这个 class_id ,确认 class_id 存在再进行 INSERT ?

    如果是这样实现约束的话,开销会不会有点大?毕竟每个约束都来一句 SQL 验证的话, N 个约束就是 N 句 SQL ……
    117 条回复    2019-01-08 06:16:29 +08:00
    1  2  
    SpicyCat
        1
    SpicyCat  
       2016-11-22 14:44:44 +08:00
    没有设计过数据库,比较好奇完全不用外键的数据库怎么搞。就拿课本上的例子来说吧,一个选课系统,有学生信息,课程信息,还有选课信息。学生信息和课程信息可以没有外键,是独立的,那选课信息怎么搞?
    6IbA2bj5ip3tK49j
        2
    6IbA2bj5ip3tK49j  
       2016-11-22 14:47:15 +08:00
    @SpicyCat 存学生和课程的 id 啊。
    windowsma
        3
    windowsma  
       2016-11-22 14:48:21 +08:00   ❤️ 3
    约束一般在逻辑里实现。
    SpicyCat
        4
    SpicyCat  
       2016-11-22 14:50:25 +08:00
    @xgfan 那不是有外键了?
    slowindy
        5
    slowindy  
       2016-11-22 14:54:18 +08:00
    @SpicyCat 说的是不在数据里设置外键,而是通过逻辑关联来实现外键
    BakCshi
        6
    BakCshi  
       2016-11-22 14:54:41 +08:00
    @SpicyCat 那个是中间表
    ljk
        7
    ljk  
    OP
       2016-11-22 14:54:59 +08:00
    @windowsma 所以新浪的数据库也是不用外键的?
    tabris17
        8
    tabris17  
       2016-11-22 14:58:00 +08:00
    对数据一致性要求不严格的场景都不应该使用外键
    xrlin
        9
    xrlin  
       2016-11-22 14:59:00 +08:00
    外键会用,但约束在程序逻辑中实现。
    helloccav
        10
    helloccav  
       2016-11-22 14:59:13 +08:00
    除了大学学数据库的时候了解过外键,工作几年来写代码从来没用过外键
    ljk
        11
    ljk  
    OP
       2016-11-22 15:00:05 +08:00
    @tabris17 请问理由?
    windowsma
        12
    windowsma  
       2016-11-22 15:01:29 +08:00
    @ljk 企业内应用一般会用外键、触发器、存储过程等,互联网服务很少用,维护起来复杂。目前数据库能用到的约束也就是唯一索引了。
    ljk
        13
    ljk  
    OP
       2016-11-22 15:01:45 +08:00
    @xrlin 外键用了,自然有约束了。为什么你还要在程序逻辑中实现约束呢?
    ljk
        14
    ljk  
    OP
       2016-11-22 15:05:01 +08:00
    @windowsma 请问不使用外键的话,数据库里出现的一些垃圾数据,比如一些"外键"指向不存在的记录,怎么处理?定时执行脚本清理吗?
    tabris17
        15
    tabris17  
       2016-11-22 15:06:11 +08:00
    @ljk 理由就是不要“作”
    tabris17
        16
    tabris17  
       2016-11-22 15:06:31 +08:00
    @ljk 人生苦短,不要作
    allenhu
        17
    allenhu  
       2016-11-22 15:08:55 +08:00
    @ljk 如果出现你说的垃圾数据,那是代码逻辑有问题,比如,你删除记录的时候,忘记删除某些关联的数据
    hyuwang
        18
    hyuwang  
       2016-11-22 15:10:31 +08:00   ❤️ 3
    性能啊
    这都分布式了 当然不考虑外键
    外键本身是为了实现强一致性 跟大规模并发和分布式都是冲突的

    我觉得完全取决于架构如何设计
    一些对性能没追求或者数据极其重要,可靠性要求高的业务外键是不可少的
    windowsma
        19
    windowsma  
       2016-11-22 15:18:00 +08:00
    @ljk 额,你这是有数据库数据洁癖啊~~也没有绝对的舍弃外键,像金融、供应链等场景还是需要优先保证数据完整性的。不过在互联网业务场景下,会尽量减少连接查询,降低表之间的逻辑耦合,当所谓的外键记录不存在时,指定默认值或者直接报错。
    ljk
        20
    ljk  
    OP
       2016-11-22 15:19:24 +08:00
    @hyuwang 多谢赐教。

    再问一下,如果不使用数据库外键,程序中想在插入一条记录时验证某个"外键"是否合法有效,一般的做法是怎样?

    是先做一次 sql 查询外键有有效性,再做一次 sql 插入?抑或是一句 sql 把校验和插入给完成了?
    aias
        21
    aias  
       2016-11-22 15:21:57 +08:00
    一般都是在逻辑里实现的..
    ljk
        22
    ljk  
    OP
       2016-11-22 15:23:48 +08:00
    @windowsma 见笑啦也不算洁癖,只是觉得数据库里的垃圾数据总得处理吧。

    那么按照你说的"指定默认值或者直接报错",其实最终也是没打算删除这些垃圾数据,只是在读到的时候做一些处理吧?
    windowsma
        23
    windowsma  
       2016-11-22 15:32:11 +08:00
    @ljk 报错就会有日志,有日志就会有警报,有警报就得去处理。如果频繁出现垃圾数据,肯定是逻辑有问题,不得去优化逻辑么。。。从来不会无缘无故产生垃圾数据。
    HypoChen
        24
    HypoChen  
       2016-11-22 15:32:27 +08:00
    @ljk 写之前先查一下,看场景,或直接报错或者写默认值
    QK8wAUi0yXBY1pT7
        25
    QK8wAUi0yXBY1pT7  
       2016-11-22 15:35:31 +08:00
    SET FOREIGN_KEY_CHECKS=0;
    liprais
        26
    liprais  
       2016-11-22 15:37:32 +08:00
    因为 mysql 外键性能垃圾,另外你们所谓的避免 join 也是因为 mysql join 性能垃圾.......
    Zzzzzzzzz
        27
    Zzzzzzzzz  
       2016-11-22 15:40:32 +08:00
    主要是互联网领域井喷期当时 mysql 3.xx 和 4.0x 时期并不支持外键、子查询、事务、视图。。。。
    jessynt
        28
    jessynt  
       2016-11-22 15:43:03 +08:00
    incompatible
        29
    incompatible  
       2016-11-22 15:44:57 +08:00   ❤️ 3
    保证约束需要消耗额外的计算资源。应用服务器相对数据库服务器来说更容易水平扩展,因此约束就放在业务逻辑里做了。
    augustG
        30
    augustG  
       2016-11-22 15:47:21 +08:00
    当数据达到一个量级需要分表分库时 外键绝对让你欲仙欲死
    Ouyangan
        31
    Ouyangan  
       2016-11-22 15:50:29 +08:00
    @SpicyCat 只是不采用数据库的外键 , 一般表关联采用逻辑关联 , 双向就建一张中间表 .列定义两张表的 id. 其实是一样的,只是人为实现了数据库本身提供的功能 , 好处看楼上回帖就好了. 没有谁对谁错 ,工作经验多了自然知道自己该选择哪种方式了,都是看场景.
    Mogugugugu
        32
    Mogugugugu  
       2016-11-22 16:14:02 +08:00
    通过事务控制吧
    6IbA2bj5ip3tK49j
        33
    6IbA2bj5ip3tK49j  
       2016-11-22 16:14:35 +08:00
    @ljk 我学生用 mysql 存的,课程放在 redis 里面。怎么用外键?
    Ouyangan
        34
    Ouyangan  
       2016-11-22 16:19:35 +08:00
    @xgfan 你这个需求怎么来的啊 .
    eslizn
        35
    eslizn  
       2016-11-22 16:20:30 +08:00
    性能开销和维护成本,还不利于扩展
    sunsh217
        36
    sunsh217  
       2016-11-22 16:29:09 +08:00
    大概只有学生才会讨论这种问题。
    sunsh217
        37
    sunsh217  
       2016-11-22 16:31:02 +08:00
    也只有学生才会严格按教科书的做法去设计表吧。 其实教科书上的规范,根本不是业界的做法。 也可能中国的教科书,都是一帮不思进取的老帮瓜写的。
    guoqiao
        38
    guoqiao  
       2016-11-22 16:41:29 +08:00
    刚毕业的时候,我也觉得既然数据库提供了外键,就应该尽量使用它,这样可以让数据库自动保持数据的完整性。
    不过后来发现,一旦使用了外键,那么当数据库变得庞大,就没法进行拆分。
    比如说在 Django 里,可以支持多个数据库,但是却不支持夸数据库的外键。
    这也意味着,如果你计划在将来将数据存放到多个数据库里,就应该一开始避免外键。
    ljk
        39
    ljk  
    OP
       2016-11-22 16:45:29 +08:00
    @sunsh217 [<SQL 反模式>]( https://book.douban.com/subject/6800774/ )不是教科书,也不是中国人写的。
    ljk
        40
    ljk  
    OP
       2016-11-22 16:46:17 +08:00
    @ljk 原来评论不支持 markdown 呵
    pangliang
        41
    pangliang  
       2016-11-22 16:53:27 +08:00
    约束在表结构里,
    那逻辑变动 约束就会变动,
    而 约束变动, 表结构就要变动
    而表结构变动, 就要死人
    Midnight
        42
    Midnight  
       2016-11-22 16:57:47 +08:00
    所谓的抛弃外键不是说连关系都不要了,只是没有在表上建外键这个属性,场景不同方案不同啦,分布式的话有外键同步会很麻烦,单数据库应用就无所谓啦
    mko0okmko0
        43
    mko0okmko0  
       2016-11-22 17:14:14 +08:00   ❤️ 2
    没抛弃过,但如果不用外键甚至不用拆表我就满足了性能,体积,设计复杂度.我何必用外键?
    应该说,我何必用传统标准资料库?

    例如 TokuDB,这是 Mysql 体系可选用的一个核心.本身是列式仓储.具有资料本身就是索引,结构本身就是有压缩的树状仓储.用了它,很多拆表的意义就没了.没有拆表何来外键?

    例如 XML/json 文档式资料库.保持了包含关系也不需要序列号,每份文档的位置都已经代表他自己.或是每个 KEY 跟 VALUE 在资料库底层都已经有他自己的唯一值了.
    而且文档资料库还解决了相同目标栏位不同内容物的问题,

    标准资料库如果相同栏位要放不同子表的内容,设计上你会想死.
    如果唯一键不是数字,又要给该表一个序列号,这样有比较省吗?各方面大都没有.

    将标准资料库 /nosql 资料库一起比较关联查询,为什么这样说?因为就是有需求阿,尤其初期就没考虑到的东西突然发现要查他们关联后的条件查询结果.尤其是其中有些表没有序列号了,关联的值就是用文字.

    那时候都有性能一样低下的问题.....一样低下的结果,那又何必分有拆表没拆表?有序列号没序列号?

    用过更好的解决办法,你还会回头用标准资料库或是放弃更好的非标准资料库吗?

    以上工作实务经验,依照每个人经验不同应该会有不同的解答,以上纯分享.
    tumbzzc
        44
    tumbzzc  
       2016-11-22 17:18:19 +08:00
    以用 flask 写网站为例,逻辑都是自己写的,没必要用外键
    hyuwang
        45
    hyuwang  
       2016-11-22 17:21:06 +08:00
    @ljk 不是专业后端,从运维角度来说的,我数据库开发经验不多,我个人是不会在写入数据时候做效验的,我只会效验数据本身,然后写好测试,测试能跑通的数据验证过了就好
    akira
        46
    akira  
       2016-11-22 17:26:53 +08:00
    不用外键
    少用存过
    少用特定数据库特定版本才有的特性
    z5864703
        47
    z5864703  
       2016-11-22 17:54:04 +08:00
    为什么一定要用数据库的外键,改动还麻烦。
    在程序业务逻辑中实现外键约束,可以灵活很多
    tonghuashuai
        48
    tonghuashuai  
       2016-11-22 18:03:51 +08:00
    除了在大学里用过外键,实际工作中在设计数据库结构的时候都不约而同的不适用外键(一个眼神就不约而同了),外键的好处可能有很多,但是外键的不好你遇到过几次就会彻底抛弃它,改用逻辑约束。
    Felldeadbird
        49
    Felldeadbird  
       2016-11-22 18:05:50 +08:00 via iPhone
    用过外键,然后测试时发现数据特别麻烦,而且又不是一定要严格的模式,就没理他了
    jianghu52
        50
    jianghu52  
       2016-11-22 18:42:00 +08:00
    当初我们设计新系统的时候,还就要不要外键做过争论。我们的项目是 PHP+mysql 。
    开始我属于强烈要求用外键的。在不考虑分库的情况下,外键的制约可以有效的让项目人员不用测那些奇葩的数据。(即业务之内不可能出现的那种)。另外就是,外键的存在在很大程度上让我们设计库的时候尽可能的多思考项目扩展的问题,如果没有外键的话,很多时候设计数据库就是有什么业务就设计成什么样子,很少考虑后期业务增加的时候,数据库是否容易扩展的问题。事实上因为我们最后选择了无外键的数据库设计,这些问题在后期都爆发了。当然,最后我也没办法袖手旁观,该填的坑还是得填。
    跟我针锋相对的一个同事他的观点也很容易理解,在要求开发速度的情况下,外键不仅是一个困扰,更加是一种折磨。为什么这么说,越是严谨的外键设计,你在做测试的时候前置工作越多,越浪费时间不说,很多时候当你只想测试某一个小部分的业务逻辑的时候,你不得不从头开始填入数据库的表,你吭哧吭哧的花了半小时填了 5 个表,仅仅只为了测试其中的一个字段。这种花费在我们那时看来确实有点太大了。
    另外外键还有一个隐性的成本,就是教学成本。这是我的一点经历。以前有个项目进了一个新人,我负责给他培训。当时的业务还不算复杂,我给他讲的时候,对外键讲的也不是很细,就告诉他如果表有这样的字段的话,那么程序会如何如何显示。结果等他下课自己做的时候,就发现动不动就是这个表插不进去,然后就要去看关联的外键是什么,之后又一堆找关联的表的字段信息,该插入什么样的数据。
    往往一小段程序,会关联出很大一块儿的业务,你给他讲吧。他也不能马上就全记住,浪费时间。不给他讲吧,你就得给他做好前置的数据准备工作,也得花时间。
    我到现在决定,外键适合那种不太大的业务,配上严谨的文档,严格的开发流程的团队。可惜我现在做的项目,只跟项目大小沾边,后面几个条件完全无法满足。
    zhouquanbest
        51
    zhouquanbest  
       2016-11-22 19:04:01 +08:00
    我的理解是 数据库只做“存储” 因此外键的逻辑 就应该放到代码里
    没了外键 你发现分布式啥的都舒服了 天下太平
    没了外键 你发现重构成本降低了 再也不怕 PM 改改改
    没了外键 你发现如果每张表都设计了冗余字段 把外键提供的信息多存一份逻辑反而更简单性能更好了
    cjyang1128
        52
    cjyang1128  
       2016-11-22 19:06:58 +08:00
    对于大的系统来说,能不用外键就不用外键,全靠代码逻辑,好定位 BUG !!!
    codeyung
        53
    codeyung  
       2016-11-22 19:08:55 +08:00
    目前做的 没有在用外键 都是逻辑 和 中间表 做的 - -
    heww
        54
    heww  
       2016-11-22 19:11:52 +08:00 via iPhone
    看了上面好多人的项目一上来就是好几百亿的项目!
    xiaowangge
        55
    xiaowangge  
       2016-11-22 19:33:05 +08:00
    游戏行业的路过,几乎连数据库( MySQL )都不在用的。

    凡是能用 Memcached (腾讯云的 Memcached 的可落地永久存储),就不用 MySQL 。
    anubiskong
        56
    anubiskong  
       2016-11-22 19:47:01 +08:00   ❤️ 3
    其实是个很简单的道理
    外键就是程序逻辑, 逻辑应该都放在一起, 以方便维护, 当然是和程序放在一起才合理, 更何况程序还有更高的灵活性
    唯一例外的情况就是巨大的性能差异或者是代码维护方面的成本上的差异, 而这两个例外在外键这个简单需求上没有体现.
    数据层面的东西层级越少越好, 关系越少越好, 必要时为了性能适当的冗余数据, 用硬盘换性能
    很多系统在设计上有历史包袱, 有些陈旧的东西不应该再想太多, 尤其是 php 和 mysql 这种很普及但上年纪的产品
    hheedat
        57
    hheedat  
       2016-11-22 19:47:31 +08:00
    DBA 不让用, 666
    movtoy
        58
    movtoy  
       2016-11-22 20:22:55 +08:00
    根据自身情况呗,

    人家阿里有公关部,我开个豆腐店也要么
    lightening
        59
    lightening  
       2016-11-22 20:32:23 +08:00
    @SpicyCat 我想是指在 ORM (你的代码) 里实现,而不用数据库内置的外键约束。
    lightening
        60
    lightening  
       2016-11-22 20:38:41 +08:00
    我个人来说,是因为 ORM 本来就提供了约束,而且使用非常方便。没有必要的理由的话,我没必要加外键约束。
    bomb77
        61
    bomb77  
       2016-11-22 20:44:03 +08:00
    233 ,原来大家都不用外键
    echo111222
        62
    echo111222  
       2016-11-22 20:47:08 +08:00 via Android
    。。。。我记得我今年五月的时候,老师给我看看论文。。强行给我的数据库表加外键
    xiaoxiaoming
        63
    xiaoxiaoming  
       2016-11-22 20:52:15 +08:00
    做的都是互联网相关的业务.
    从来没有用外键,都是靠业务逻辑区约束.
    abcbuzhiming
        64
    abcbuzhiming  
       2016-11-22 21:39:06 +08:00
    首先要理解当年数据库为什么要设计这些,外键说白了就是为了维护数据强一致性的。当年的数据库在金融领域应用最多最早,所以强一致性要求很高。而现在绝大部分公司的业务,哪需要这么高的强一致性啊
    abcbuzhiming
        65
    abcbuzhiming  
       2016-11-22 21:41:54 +08:00
    @jianghu52 你的项目用了 PHP 就说明你们的项目试图快速成型而不是打算长期维护的严谨系统,这种系统费精力去用外键是给自己找不愉快,浪费在开发上的时间比你不用外键而需要填坑的时间还要长。不用外键本质是因为现在绝大部分业务压根就不需要那么严谨的一致性了。这玩意是有代价的
    icegreen
        66
    icegreen  
       2016-11-22 21:45:18 +08:00
    从来不用, 逻辑全部在代码中体现, 便于维护.
    你的问题是为什么抛弃了外键; 不妨从另一个角度想想,为什么用外键. 把约束从代码转移到数据库, 有什么好处.
    odirus
        67
    odirus  
       2016-11-22 21:49:18 +08:00 via Android
    如果没有专业的 DBA ,还是少用
    aldenchang
        68
    aldenchang  
       2016-11-22 22:09:20 +08:00
    对于业务规则不够完善,经常需要工程师手动调整数据的库来说,外键简直是灾难。
    jjx
        69
    jjx  
       2016-11-22 22:25:44 +08:00   ❤️ 1
    看了这个讨论让人瞠目结舌, 虽说互联网应用对数据一致性要求不高, 但看到如此漠视, 所以这可能才是企业软件招不到合适的人的原因了
    eyp82
        70
    eyp82  
       2016-11-22 22:29:30 +08:00   ❤️ 2
    数据库其实也从来没有要求大家用外键, 用外键只是为了满足某个范式的要求而已, 实际上范式根据严格程度不同有多重, 你甚至连第一范式都可以不满足(比如时下流行的 KV 数据库). 这并不是说数据库理论脱离实际.
    所有的设计都是根据实际情况做各方面的妥协的, 比如企业应用(金融电信制造等等), 业务逻辑复杂但是并发量**相对**不高, 以前一般倾向于 scale-up, 不会做分库分表, 这样通过外键, trigger 等确保逻辑一致性是很合适的做法, 反之通过业务逻辑重复造轮子就不科学了.
    互联网应用更多的是高并发, 单个业务逻辑本身一般并不复杂, 这样在业务逻辑内重复实现一个约束相对简单, 而由于分布式的要求, 外键是一个严重的阻碍, 所以不适用外键也在情理之中.

    另外不同意楼上有人说的数据库的外键消耗更多系统资源的说法, 实际上数据库的外键经过这么多年的优化, 绝大多数情况下比业务代码里对关系数据库半懂不懂的人写的约束更高效. 你自己写的约束其实只是让你后面自己折腾起来更灵活而已.
    icegreen
        71
    icegreen  
       2016-11-22 22:56:46 +08:00
    没有外键也还有事务, 放弃了外键 不等于 放弃了一致性.
    不要歪题
    iyaozhen
        72
    iyaozhen  
       2016-11-22 23:14:21 +08:00 via Android
    关键是不方便维护,其它都是次要的。后面接手的人容易搞出事故。不要说外键了,字段不能为 null 的限制都能出问题。存储过程什么的也一样,好多时候不知道别人设置了这些,容易踩坑。

    不过更多的是业务不需要,没需求、没收益。使用上主要矛盾集中在索引优化、主从一致等,哪有精力倒腾外键。
    IwfWcf
        73
    IwfWcf  
       2016-11-22 23:16:00 +08:00
    最主要的原因就是为了可扩展性吧,未来可能需要分表
    colatin
        74
    colatin  
       2016-11-22 23:31:25 +08:00
    关键楼上都是搞分布式大系统的
    yeqiu
        75
    yeqiu  
       2016-11-22 23:45:23 +08:00   ❤️ 1
    @anubiskong
    完全同意你的说法,关系就是逻辑,逻辑放在程序里封装成变化,天经地义。

    这里有一个大写的但是

    建立外键和代码实现外键哪个是确保数据一致性的最低成本的方法?
    我想这个问题的结果无疑是建立外键。

    那么有没有一种既能使用外键的低成本,又能很好的封装变化的方式呢?
    当然有, entity framework 的 code first 就是我知道一种方式,按理说所有的 orm 框架应该都能干这事
    skywatcher
        76
    skywatcher  
       2016-11-22 23:48:22 +08:00
    我们 DBA 团队的也强烈建议不要外键,数据库同步、迁移、分表、分库时各种约束很麻烦。之前一次想同步一个表的数据到 beta 环境,各种外键约束,最后基本整个库都快被同步下来了,我特么只要一个表而已😠(别问为啥不直接 dump ,线上数据库规定不允许 dump 影响业务)
    guyskk
        77
    guyskk  
       2016-11-23 00:02:22 +08:00 via Android
    @ljk 软删除,一定时间后彻底删除。企业需要应对比如盗号,用户误删数据,管理员误操作,以及司法取证这些问题。
    exoticknight
        78
    exoticknight  
       2016-11-23 00:04:06 +08:00
    请教一下不用外键如何用业务逻辑区约束?
    wind3110991
        79
    wind3110991  
       2016-11-23 00:13:39 +08:00   ❤️ 3
    外键这个东西和触发器是一样的道理,平时工作上省事了,一旦出了问题,定位半天找不到原因;
    举个最简单的例子:
    假设有 学生表 Student 和 班级表 Class
    学生表中关联了一个外键,字段是班级的 id ,
    现在系统里有个学生 A 读了四年大学,所在班级为 B ,准备读研,读研就要换到班级 C 中,这个关联的班级 id 就要更新对吧;
    但是这个时候假设学校教务系统不保留毕业班级的信息,会把毕业班级信息清除或者删除掉。这个时候就删掉了这个学生原来的班级 B (把班级表里 B 班级整条记录都删除了)。
    A 学生到了研究生注册那天,去到报名处修改班级信息。这时候修改这个自己的班级时就会发现 DB 外键关联报错,而且不是代码逻辑的错误。

    讲了半天。。就是让你,多写两行代码关联逻辑,少操份定位时想死的心。。
    wind3110991
        80
    wind3110991  
       2016-11-23 00:15:00 +08:00
    @exoticknight 新建并维护一个 map 表 C ,把 A 和 B 的关联记录到 C 中
    duola
        81
    duola  
       2016-11-23 00:50:53 +08:00
    @wind3110991 这是不是所说的 中间表 呢?
    feather12315
        82
    feather12315  
       2016-11-23 01:04:29 +08:00 via Android
    @wind3110991 这是数据库设计的问题,删除异常。并不是外键的锅
    vibbow
        83
    vibbow  
       2016-11-23 01:31:24 +08:00
    ifhwhlwpto
        84
    ifhwhlwpto  
       2016-11-23 03:09:02 +08:00
    @sunsh217 跟中国的教科书有什么关系,国外的教科书难道就不教你规范?
    beidouxun
        85
    beidouxun  
       2016-11-23 03:39:40 +08:00 via Android
    @wind3110991 删除 b 班级肯定把关联此班级学生表的外键清空!等待分配班级!程序的问题!
    q397064399
        86
    q397064399  
       2016-11-23 05:41:46 +08:00
    realpg
        87
    realpg  
       2016-11-23 08:04:51 +08:00 via Android
    @ljk 合格的程序根本不会出现这种情况
    我公司曾开除多次搞出这种问题的程序员
    ebony0319
        88
    ebony0319  
       2016-11-23 08:20:50 +08:00
    我觉得外键大多数存在于教科书。实际项目中比较少(基本上不用)外键,主要是表多了不好维护。用一定的存储过程,一定的视图等。很少在数据库中(至少在我见到的十几万行 sql 中)使用控制流语句。数据库不适合干复杂的事情。
    sunsh217
        89
    sunsh217  
       2016-11-23 09:06:25 +08:00 via Android
    @ifhwhlwpto 国外就没有教科书一说
    ren2881971
        90
    ren2881971  
       2016-11-23 09:08:08 +08:00
    因为 drop 的时候太麻烦。。。
    wupher
        91
    wupher  
       2016-11-23 09:09:11 +08:00
    除非小项目,基本不使用外键。外键关系使用程序代码来维护,在数据库中不体现。

    后期如果需要数据清理,数据调整时,有外键关系(尤其是复杂的外键关系)会造成表数据非常难以修改、维护。
    bi168
        92
    bi168  
       2016-11-23 09:58:32 +08:00 via Android
    外键确实在实际生产环境中比较少用,一般都在程序中实现逻辑 避免维护修改数据的复杂性
    barbery
        93
    barbery  
       2016-11-23 10:02:18 +08:00
    唯品会的确是不允许外键, db 变更如果有外键的话, 99.9%是要被驳回的。。。原因的话,我猜想是互联网企业,性能优先,使用物理外键的话,以后分表分库都会有问题。
    iyangyuan
        94
    iyangyuan  
       2016-11-23 10:03:12 +08:00   ❤️ 1
    逻辑层面统一,物理层面分离,保障以后的可伸缩性
    bi168
        95
    bi168  
       2016-11-23 10:11:12 +08:00
    确实一方面给性能带来负担,一方面在交易系统中,删除数据就会自动删除外键数据,这个也会经常出现问题。
    关于数据库,数据仓库、大数据、数据分析的问题,我这有个社区 www.bi168.cn 欢迎大家多多交流
    nandaye
        96
    nandaye  
       2016-11-23 10:13:01 +08:00
    有的主键都不要得,不奇怪,看你的应用场景了
    blacklee
        97
    blacklee  
       2016-11-23 12:05:07 +08:00
    在 2016 年这个节点,我觉得更早的 2006 年就差不多可以这么说了:

    数据库使用外键,属于教条主义!
    fortunezhang
        98
    fortunezhang  
       2016-11-23 13:46:30 +08:00
    从来没有用过外键:)
    killerv
        99
    killerv  
       2016-11-23 14:03:43 +08:00
    我觉的业务逻辑最好还是写在代码中,外键约束有时候不够灵活,排查问题也不方便
    Balthild
        100
    Balthild  
       2016-11-23 14:57:52 +08:00 via Android
    @sunsh217 有一個英文單詞叫做 textbook
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   992 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 20:36 · PVG 04:36 · LAX 12:36 · JFK 15:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.