zoukankan      html  css  js  c++  java
  • 牛腩新闻公布系统---外键约束下怎样删除记录

    一、为什么使用外键?

        查了些资料,八个字“保持完整性、一致性”,结合我之前做的重构机房收费系统,我的理解是“防止相关表中数据没有关联而变得孤立。终于导致数据冗余”。得出这个结论是上次让贾丽敏帮忙点系统时候我最深刻的感受,由于我的数据库关系图中辣么多张表却没有丝毫关系……

        既然官方解释是“完整性和一致性”,就先来说明一下:

        对于完整性和一致性,不少人都混为一谈了。

        完整性(integrity)很多其它是针对实际业务来说的。比方说一个职员ID。不能在一个表里是1。还有一个表里却是2;数据库引擎一般通过主外键、触发器等来维护完整性的。

        一致性(consistency)是事务一个特征,要底层一点。

    举例来说,针对这个语句:update a set col1=1,col2=2 where id=1(更改一行数据的两列)。数据库要保证在不论什么情况下,都绝不能出现仅仅更改了col1,或仅仅更改了col2的情况,这两列(col1和col2)要么一起被改,要么都没改。还包含内部的索引结构、内部数据字典等数据都要绝对保持一致。

        这个说明来自互联网,当然这一点还是要在项目中慢慢的去体会的。


    二、外键约束下怎样删除相关表中的信息?


        如上图所看到的,从左到右将其定义为1、2、3层,就像是我们三层里的U、B、D那样,一环扣一环。显然右側是最深的一层,或者称之为底层;左側是最浅的一层,或者称之为表层。

        非常显然。删除表层的数据是非常任意的。because它不会对其它层有不论什么影响,而删除中间层和底层的数据的时候,会影响上层建筑。就像我在王聚博客里看到的一个比喻,将其比喻为一座大厦,拆楼的时候是从上向下的,一层一层分解,假设直接去拆地下室,那么整个楼不就崩溃坍塌了吗?

     

         所以这就是第一种用于删除外键约束下的数据的方法的思想:逐层分解

        方法一:通过触发器实现

        就拿《牛腩新闻公布系统》的样例来说:

    -- =============================================
    -- Author:张振华
    -- Create date:2015年月日:01:29
    -- Description:	删除类别触发器
    -- =============================================
    ALTER TRIGGER trigCategoryDelete
       ON  Category
       instead of DELETE
    AS 
    BEGIN
       --声明一个
       declare @caId int 
       select @caId=id from deleted
       --删除评论(此处使用子查询,查询出的条件是多条,于是使用”in”而不是”=”)
       delete comment where newsId in (select newsId from news where caId=@caId)
       --删除新闻
       delete news where caId=@caId
       --删除类别
       delete category where id=@caId
    END
    GO
    

        这样的方法的优点:不会破坏主外键的约束,保证完整性和一致性的同一时候,保证数据不会产生冗余。也不会造成误删而出现数据残缺的现象。同一时候,这样的方法是在数据库里进行限制,使得在编程过程中直接使用该约束就OK。不用再次做其它逻辑上的约束。

     

       还有一种用于删除外键约束下数据的思想是:连根拔起

       方法二:级联删除

        这样的方法在重构机房的时候就接触过,仅仅是迫于当时时间压力,把表中全部外键删除掉了,发现反而在程序中做好多逻辑上的约束,反而效果不怎么好,防不胜防。

    这次正好将这样的方法学会。

    所谓级联删除。就是删除主表记录同一时候删除从表中有外键关系的记录。

    -- =============================================
    -- Author:张振华
    -- Create date:2015年7月5日
     -- Description:	级联删除举例
    -- =============================================
    
    create table category
    (
    id varchar(20) primary key,
    name varchar(20) not null
    )
    
    create table news
    (
    --自增字段充当主键
    id int identity(1,1) primary key,
    title varchar(50) not null,
    content varchar(50) not null,
    --表news创建了外键caId 相应category表的主键id,同一时候声明了级联删除
    caId varchar(20),
    --on delete:删除级联
    foreign key (caId) references category(id) on delete cascade
    )
    

        这样建表之后。假设在表中category中加入“体育新闻”,将其删除之后,在news表中全部关于caId是“体育新闻”的记录都会被删除。

        因为是刚刚接触级联删除,和上面“逐层删除”相比。这样的方法更像是将整栋楼“爆破”,从底层到上层建筑所有删掉,删除彻底,同一时候能保持数据的完整性以及一致性,我的感觉。有一点既是这样做的优点也是坏处就是,删除过于彻底,有点“连根拔起、一人犯罪,株连九族”的感觉。删除后没有冗余数据,可是过于彻底有可能会删除一些实用信息。

     

        最后介绍最简单的一种方法,我将其思想定义为:解除合约

       方法三:

        情景:假设须要删除底层的数据,可是表层的一些数据须要保留。也就是说只须要删除一部分数据,怎么办?

    临时接触外键约束,将底层表中数据删除之后再加上外键约束,可能这样做会有种“脱掉裤子放屁”的感觉,可是对于只删除一部分数据,尤其是底层数据的时候。这将是一种非常好的方法。当然假设数据量大的话,这样的方法还是不太好。可是至少这是解决这个问题的一种途径。

     


    三、Summary

       扩展:

        在设置外键约束的条件下,删除会受到约束的限制,那么“增、改、查”会受到外键的约束吗?

    我推測。“改”会受到限制。其它两个不会。大家也能够尝试去做做这种实验,当然不过自己的推測,有待验证。

     

       收获:

        在做重构机房收费系统的时候。就遗留了一个问题,设计数据库的过程中。由于主键冲突以及外键约束,导致我不得不删掉了当初设置的外键约束,而这样做的后果就是关系数据库的完整性和一致性遭到破坏。

    学习了牛腩的“删除外键约束条件下的数据”,让我解决掉了这个遗留问题。如今记录我的学习过程。




  • 相关阅读:
    GenericServlet和HttpServlet有什么区别?
    什么是RMI?
    【WPF学习】第十八章 多点触控输入
    【WPF学习】第十七章 鼠标输入
    【WPF学习】第十六章 键盘输入
    【WPF学习】第十五章 WPF事件
    【WPF学习】第十四章 事件路由
    【WPF学习】第十三章 理解路由事件
    【WPF学习】第十二章 属性验证
    【WPF学习】第十一章 理解依赖项属性
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7027996.html
Copyright © 2011-2022 走看看