zoukankan      html  css  js  c++  java
  • 数据库完整性约束

    完整性约束

              ——数据库完整性约束简介

    • 理解数据库完整性约束的作用;
    • 理解数据库中的各种约束的作用。

     

    • 完整性约束是保证用户对数据库所做的修改不会破坏数据的一致性,是保护数据正确性和相容性的一种手段.

     

    • 维护完整性
    • 在一个DBMS之中,为了能够维护数据库的完整性,必须能够提供以下的几种支持:

    提供定义完整性约束条件机制

    在数据表上定义规则,这些规则是数据库中的数据必须满足的语义约束条件;

    提供完整性检查的方法

    在更新数据库时检查更新数据是否满足完整性约束条件;

    违约处理

    DBMS发现数据违反了完整性约束条件后要采取的违约处理行为,如拒绝(NO ACTION)执行该操作,或者级联(CASCADE)执行其他操作。

    • 主要约束分类

    开发之中可以使用以下的五种约束进行定义:

    非空约束:

    如果使用了非空约束的话,则以后此字段的内容不允许设置成null;

    唯一约束:

    即:此列的内容不允许出现重复;

    主键约束:

    表示一个唯一的标识,例如:人员ID不能重复,且不能为空;

    检查约束:

    用户自行编写设置内容的检查条件;

    -外键约束(参照完整性约束):

    是在两张表上进行的关联约束,加入关联约束之后就产生父子的关系。

    隐式约束

    例如数据类型

     

    —— 非空约束:NK

    • 在正常情况下,NULL是每个属性的合法数据值。如果说现在某个字段不能为NULL,且必须存在数据,那么就可以依靠非空约束来进行控制,这样在数据更新时,此字段的内容出现NULL时就会产生错误。
    • 非空约束不允许字段为null
    • 非空约束出现错误时会提示完整的错误位置。
    • 使用非空约束:只需要在定义列的时候后面增加一个NOT NULL即可.
      • 定义member表,其中姓名不允许为空

    DROP TABLE member PURGE ;

    CREATE TABLE member(

       mid     NUMBER   ,

        name    VARCHAR2(200)   NOT NULL

    ) ;

      • member表中插入数据,name栏位不能为空

    INSERT INTO member(mid,name) VALUES(1,'wendy')

     

    —— 唯一约束:UKCONSTRAINT子句

    唯一约束,CONSTRAINTconstraint约束)

    • 唯一约束(UNIQUE,简称UK)表示的是在表中的数据不允许出现重复的情况
    • 唯一约束可以设置NULL
    • 唯一约束的列不允许重复
    • 只需要在定义列的时候后面增加一个UUNIQUE即可.
      • 定义member表,其中姓名不允许为空

    DROP TABLE member PURGE ;

    CREATE TABLE member(

        mid     NUMBER   ,

        name    VARCHAR2(200)   NOT NULL ,

        email   VARCHAR2(50)    UNIQUE

    ) ;

    向表中添加数据:

    INSERT INTO member(mid,name,email) VALUES(1,'t','z@qq.com')

    INSERT INTO member(mid,name,email) VALUES(2,'w','z@qq.com')

    当添加第二个数据时候出现错误:ORA-00001: 违反唯一约束条件 (SCOTT.SYS_C0011099)

    • 因为约束在数据库中也是一个对象,每个对象都有自己的名字,如果用户没有指定名字,那么就由系统动态分配一个,所以如上出现的错误是SYS_C0011099
    • 对于约束的名字,建议写法:“约束简写_字段名”

    为唯一约束指定一个名字

    CONSTRAINT uk_email UNIQUE(email)

    DROP TABLE member PURGE ;

    CREATE TABLE member(

        mid     NUMBER   ,

        name    VARCHAR2(200)    NOT NULL ,

        email   VARCHAR2(50) ,

        CONSTRAINT uk_email      UNIQUE (email)

    ) ;

    唯一约束是不受空类型控制.

    如下两条记录都可以执行

    INSERT INTO member(mid,name,email) VALUES(1,'t',null)

    INSERT INTO member(mid,name,email) VALUES(2,'w',null)

     

    主键约束:PK

     

    • 主键约束:PK
      • 如果一个字段即要求唯一,又不能设置为null,则可以使用主键约束主键约束 = 非空约束 + 唯一约束),
      • 主键约束使用PRIMARY KEY(简称PK进行指定.

    在member表中的mid字段应该表示一个成员的唯一编号,

    而这个编号即不能为空,也不能重复。

    设置member表中的mid为主键

    DROP TABLE member PURGE ;

    CREATE TABLE member(

        mid     NUMBER          PRIMARY KEY ,

        name    VARCHAR2(200)   NOT NULL ,

        email   VARCHAR2(50) ,

        CONSTRAINT uk_email UNIQUE (email)

    ) ;

    指定主键约束的名称

    DROP TABLE member PURGE ;

    CREATE TABLE member(

        mid     NUMBER       ,

        name    VARCHAR2(200)   NOT NULL ,

        email   VARCHAR2(50) ,

        CONSTRAINT pk_mid PRIMARY KEY (mid) ,

        CONSTRAINT uk_email UNIQUE (email)

    ) ;

     

    • 复合主键
      • 在实际的开发之中,一般在一张表中只会设置一个主键,但是也允许为一张表设置多个主键,这个时候将其称为复合主键。在复合主键中,只有两个主键字段的内容完全一样,才会发生违反约束的错误

    建议使用复合主键

     

       检查约束:CK

    • 检查约束指的是对数据增加的条件过滤,表中的每行数据都必须满足指定的过滤条件。
    • 在进行数据更新操作时,如果满足检查约束所设置的条件,数据可以成功更新,如果不满足,则不能更新,
    • SQL语句中使用CHECK(简称CK)设置检查约束的条件
    • 检查约束会设置多个过滤条件,所以检查约束过多时会影响数据更新性能
    • member表中增加age字段(年龄范围是0~200岁)和sex字段(只能是男或女)

    DROP TABLE member PURGE ;

    CREATE TABLE member(

        mid     NUMBER       ,

        name    VARCHAR2(200)   NOT NULL ,

        email   VARCHAR2(50) ,

        age     NUMBER          CHECK (age BETWEEN 0 AND 200) ,

        sex     VARCHAR2(10) ,

        CONSTRAINT pk_mid_name PRIMARY KEY (mid,name) ,

        CONSTRAINT uk_email UNIQUE (email) ,

        CONSTRAINT ck_sex   CHECK (sex IN ('',''))

    ) ;

     

    -外键约束:FK(重要)

    • 级联操作:ON DELETE CASCADEON DELETE SET NULL
    • 使用外键约束后删除表时应先删除子表再删除父表;
    • 在进行外键设置的时候,对应的字段,在父表中必须是主键或是唯一约束.
    • 如果A表和B表被设置为互为外键,那么一张表都无法删除.
      • 这个时候只能强制删除:DROP TABLE member CASCADE CONSTRAINT;
      • 不建议使用,在设计表的时候就应该考虑好先后关系
    • 外键约束的产生分析
      • 例如,现在公司要求每一位成员为公司发展提出一些更好的建议,并且希望将这些建议保存在数据表之中,那么根据这样的需求,可以设计出如图所示的设计模型。
      • 一个成员可以提出多个建议,这是一个一对多的关系.
      • 设计出了两张数据表,两张表的作用如下:
        • 人员表:用于保存成员的基本信息(编号、姓名);
        • 建议表:保存每一个成员提出的建议内容,所以在此表之中保存在了一个成员编号,即:通过此成员编号就可以和成员表进行数据的关联。

    建立member和advice表

    DROP TABLE member PURGE ;

    DROP TABLE advice PURGE ;

    CREATE TABLE member(

        mid     NUMBER       ,

        name    VARCHAR2(200)   NOT NULL ,

        CONSTRAINT pk_mid PRIMARY KEY (mid)

    ) ;

    CREATE TABLE advice(

        adid     NUMBER       ,

        content    CLOB   NOT NULL ,

            mid     NUMBER,

        CONSTRAINT pk_adid PRIMARY KEY (adid)

    ) ;

    增加一组正确的数据;

    WENDY提出了2个意见,GAGA提出了3个意见

    INSERT INTO member(mid,name) VALUES(1,'WENDY');

    INSERT INTO member(mid,name) VALUES(2,'GAGA');

    INSERT INTO advice(adid,content,mid) VALUES(1,'Miss Blair, we must go or we'll be late',1);

    INSERT INTO advice(adid,content,mid) VALUES(2,'I've been invited to a charity event',1);

    INSERT INTO advice(adid,content,mid) VALUES(3,'Okay, so whose mess is it?',2);

    INSERT INTO advice(adid,content,mid) VALUES(4,'Can i borrow you for a minutes?',2);

    INSERT INTO advice(adid,content,mid) VALUES(5,'There is nothing I can do',2);

    查询每个成员的完整信息和所提出的意见的数量

    确定所需要的数据表:

    member表

    advice表:统计建议数量

    确定关联字段:m.mid=a.mid

    SELECT m.mid,m.name,COUNT(a.mid)

    FROM member m,advice a

    WHERE m.mid=a.mid

    GROUP BY m.mid,m.name;

    增加一个建议,member表中并不存在99的信息,这时候就会出现错误数据

    INSERT INTO advice(adid,content,mid) VALUES(6,q'[nothing]',99);

    现在对于表可以分为父表(member)和子表(advice),因为子表中的数据必须参考member的数据。建议提出的成员编号应该是在member表中mid列上存在的数据.

    为了保证表的数据的有效性,只能利用外键约束完成.

    外键使用FOREIGN KEY来进行设置

    增加外键配置

    DROP TABLE member PURGE ;

    DROP TABLE advice PURGE ;

    CREATE TABLE member(

        mid     NUMBER       ,

        name    VARCHAR2(200)   NOT NULL ,

        CONSTRAINT pk_mid PRIMARY KEY (mid)

    ) ;

    CREATE TABLE advice(

        adid     NUMBER       ,

        content    CLOB   NOT NULL ,

            mid     NUMBER,

        CONSTRAINT pk_adid PRIMARY KEY (adid) ,

     CONSTRAINT fk_adid FOREIGN KEY (mid) REFERENCES member(mid)

    ) ;

    执行错误的数据插入:

    INSERT INTO advice(adid,content,mid) VALUES(6,q'[nothing]',99);

    ORA-02291: 违反完整约束条件 (SCOTT.FK_ADID) - 未找到父项关键字

     

    一旦为表中增加了外键约束,就会有新的问题:

    级联操作问题

    问题一:删除父表数据前需要先清出所有子表的对应数据

    DELECT FROM member WHERE mid=1;

    RA-02291: 违反完整约束条件 (SCOTT.FK_ADID) - 未找到父项关键字

    如果要删除这条记录,就必须要删除子表的记录,但是这样的做法并不可取.

    DELETE FROM advice WHERE mid=1;

    DELETE FROM member WHERE mid=1;

    解决方法:根据业务需求选择合适的级联操作

    【级联操作一】级联删除(ON DELETE CASCADE)

    当主数据表被删除后,对应的子表数据也应该同时被清理.这样不行,比如一个公司部门取消,不能将雇员都删除.

    【级联操作二】级联设置NULL(ON DELETE SET NULL)

    当主表数据被删除后,对应的子表数据的相应字段的内容会设置为null.

    级联删除配置(ON DELETE CASCADE)

    DROP TABLE advice PURGE ;

    DROP TABLE member PURGE ;

    CREATE TABLE member(

        mid     NUMBER       ,

        name    VARCHAR2(200)   NOT NULL ,

        CONSTRAINT pk_mid PRIMARY KEY (mid)

    ) ;

    CREATE TABLE advice(

        adid     NUMBER       ,

        content    CLOB   NOT NULL ,

            mid     NUMBER,

        CONSTRAINT pk_adid PRIMARY KEY (adid) ,

     CONSTRAINT fk_adid FOREIGN KEY (mid) REFERENCES member(mid) ON DELETE CASCADE

    ) ;

    现在删除父表记录,父表记录以及子表记录的信息都被删除.

    DELETE FROM member WHERE mid=1;

    级联更新:级联设置NULL(ON DELETE SET NULL)

    DROP TABLE advice PURGE ;

    DROP TABLE member PURGE ;

    CREATE TABLE member(

        mid     NUMBER       ,

        name    VARCHAR2(200)   NOT NULL ,

       CONSTRAINT pk_mid PRIMARY KEY (mid)

    ) ;

    CREATE TABLE advice(

        adid     NUMBER       ,

        content    CLOB   NOT NULL ,

            mid     NUMBER,

        CONSTRAINT pk_adid PRIMARY KEY (adid) ,

     CONSTRAINT fk_adid FOREIGN KEY (mid) REFERENCES member(mid) ON DELETE SET NULL

    ) ;

    删除父表中的记录,这个时候父表中的记录会被删除,而子表中的记录会变为null空.

    DELETE FROM member WHERE mid=1;

    问题二:删除父表时需要先将子表删除

     

    查看约束

     

    • 约束依然属于数据库对象,可以直接利用数据字典查看。
    • 约束是由数据库自己创建的兑现个,所有对象都会在数据字典中进行保存
    • 可以利用user_constraints数据字典或者user_cons_columns数据字典查看.

    创建一张member表,主键不设置名字

    CREATE TABLE member(

        mid     NUMBER       PRIMARY KEY ,

        name    VARCHAR2(200)   NOT NULL ,

    ) ;

    向表中插入数据,

    INSERT INTO member(mid,name) VALUES(1,'WENDY');

    INSERT INTO member(mid,name) VALUES(1,'GAGA');

      当插入第二条数据时候会报错,ORA-00001: 违反唯一约束条件 (SCOTT.SYS_C0011147)

      • 因为约束在数据库中也是一个对象,每个对象都有自己的名字,如果用户没有指定名字,那么就由系统动态分配一个,所以如上出现的错误是SYS_C0011099
      • SYS_C0011099就是数据库对象(约束)的名称

    user_constraints查看约束信息,就能看到SYS_C0011099

    Constraints_type字段可以看到约束的类型,P为主键,C为检查

      SELECT * FROM user_constraints;

      • 查看全部的约束名称、类型、约束设置对应的表名称

      SELECT constraint_name,constraint_type,table_name FROM user_constraints ;

      • 查询emp表上的全部约束

      SELECT constraint_name,constraint_type,table_name

      FROM user_constraints WHERE table_name='EMP' ;

    要查询约束所对应的字段,这时候查user_cons_columns

    SELECT * FROM user_cons_columns;

     

    修改约束(了解)

    • 约束在建立表的时候一定要同时建立;
    • 对于约束不建议对其进行修改。

     

    • 为表中增加约束

        • 语法:ALTER TABLE 表名称 ADD CONSTRAINT 约束名称 PRIMARY KEY(约束字段) ;
        • 范例:member表的mid字段增加主键约束
          • ALTER TABLE member ADD CONSTRAINT pk_mid PRIMARY KEY(mid) ;
        • 范例:member表的age增加检查约束
          • ALTER TABLE member ADD CONSTRAINT ck_age CHECK(age BETWEEN 0 AND 200) ;

      启用/禁用约束

        • 禁用约束
          • ALTER TABLE 表名称 DISABLE CONSTRAINT 约束名称 [CASCADE];
          • 范例:禁用advice表中的adid主键约束“pk_adid
            • ALTER TABLE advice DISABLE CONSTRAINT pk_adid ;
        • 启用约束
          • ALTER TABLE 表名称 ENABLE CONSTRAINT 约束名称 ;
          • 范例:禁用member表中的“pk_mid”约束,此字段在advice表中是外键
            • ALTER TABLE member DISABLE CONSTRAINT pk_mid ;

      删除约束

        • ALTER TABLE 表名称 DROP CONSTRAINT 约束名称 [CASCADE];
        • 范例:删除advice表之中的“pk_adid”约束 —— 无关联外键
          • ALTER TABLE advice DROP CONSTRAINT pk_adid ;
        • 范例:删除member表之中的“pk_mid”约束 —— 有关联外键
          • ALTER TABLE member DROP CONSTRAINT pk_mid CASCADE ;

     

     

     

  • 相关阅读:
    directUI
    PyLucene测试成功
    MFC笔记(1)CPaintDC, CClientDC
    sprintf缓冲区溢出
    2.5 攻击示例:对Microsoft C++编译器的攻击 ZZ
    C++笔记(3)类中与类外的运算符重载
    C++笔记(2)public,private,protected关键字
    RTSP协议
    使用虚函数,减少累赘的if/else/switch
    C++笔记(4)成员函数定义在类内与类外
  • 原文地址:https://www.cnblogs.com/thescentedpath/p/constraint.html
Copyright © 2011-2022 走看看