明留

将何所持,将何所往?此刻惜之!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

约束:其可以对表中的数据做一些过滤,约束的主要功能是保证表中数据合法性,按照约束分类:共分5种约束:非空、唯一、主键、检查、主-外键约束。
    1、非空约束(NK):当数据表中的某个字段上的内容不希望设置为null,则可以使用not null进行指定。
 2、唯一约束(unique),UK:指每个列上的数据不允许重复。例如:email varchar(50)  unique,此语句如果违反唯一约束条件,此时由系统默认分配一个违反约束代号,难以观察。但是也可以为唯一约束字段指定约束名称,其使用Constraint来定义,建议约束的名字格式“约束类型_字段”。
    email   varchar(50), constraint UK_email unique(email);
 3、主键约束(primary key,PK):主键约束=非空+唯一约束,在之前设置唯一约束的时候发现可以设置为null,而如果使用了主键约束之后怎不能为空,并且主键一般作为数据的唯  一的一个标记出现。例如:ID number primary key;如果出现错误的数据则提示的信息和单一的非空、唯一约束提示的信息一样。所以这里也可以跟唯一约束一样,使用同样的命名方法,例如:constraint PK_ID primary key(ID);
   (1)、在正常的开发角度而言,一张表一般只设置一个主键,但是从SQL语法的规定而言,一张表可以设置多个主键,这种做法称为复合主键。例如:
     mid number, name vachar(50) not null,
  constraint pk_mid_name primary key(mid, name);
 在复合主键的使用中,只有两个字段的内容都一样的情况下,才被称为重复数据。
 4、检查约束(Check,CK):指的是为表中的数据增加一些过滤条件。
    create table member(
        mid  number, name varchar(50) not null
     sex varchar(50) not null, age number(3),
     constraint pk_mid primary key(mid),
     constraint ck_sex check(sex in('男','女','中'),
     constraint ck_age check(age between 1 to 250) );
 5、主-外键约束:是建立在两张表中进行的,而且这两张表存在父子关系的,即:子表中某个字段的取值范围由父表所决定。
    Drop table member purge;(删除不经过回收站)
    Create table member( mid  number,
    name  varchar(50) not null;
    constraint pk_mid primary key(mid) );
   
    create table book( bid  number,
    title  varchar(50) not null, mid  number,
    constraint pk_bid primary key(bid),
       constraint fk_mid foreign key(mid) references member(mid) );
 此时,只是增加了一个约束,这样一来如果输入的数据有误,则会出现如下的提示:Scott.fk_mid未找到父项关键字。因为member.mid没有指定的数据,所以book.mid如果有数据错误,则无法执行更新操纵。不过,使用外键的最大好处是控制子表中某些数据的取值范围,但是在删除表的数据带来了不少的问题;
    1、删除数据的时候,如果主表中的数据有对应的子表数据,则无法删除主表的对应数据;
       例如:delete from member where mid=1;会提示违反约束,子表中有记录。此时,只能先删除子表记录,之后再删除父表记录。例如:Delete from book where mid=1;
            delete from member where mid=1;
     基于这种操作的不方便,可以通过建立外键约束的时候指定一个级联删除的功能,修改数据库创建脚本。
    Drop table member purge;(删除不经过回收站)
    Create table member( mid  number,
    name  varchar(50) not null;
    constraint pk_mid primary key(mid) );
   
    create table book( bid  number,
    title  varchar(50) not null, mid  number,
    constraint pk_bid primary key(bid),
       constraint fk_mid foreign key(mid) references member(mid) [on delete cascade]|[on delete set null] );
  此时由于存在级联删除的操作,所以主表中的数据删除之后,对应子表中的数据也都会被同时删除掉。
    2、删除数据的时候,让子表中对应的数据设置为null,而不是删除,此时继续修改数据库创建脚本[on delete set null]。
    3、删除父表之前首先删除对应的子表,否则无法删除。 例如:Drop table book purge;
                 drop table member purge;
  但这样做比较麻烦,因为这样做必须知道表之间的父子关系。在Oralce之中专门提供了一个强制性删除表的操作,即:不再关心约束,在删除的时候写上一句“Cascade constraint”。
  例如:Drop table member cascade constraint purge;       这样,不关心子表是否存在,直接强制性删除父表。不过,在以后进行数据表删除的时候,最好的惯用思想先删子表,后删父表。
 6、修改约束         约束本身也属于数据库对吸纳,那么也肯定可以进行修改操作,而且只要修改都使用Alter指令,约束的修改主要指的是以下两种操作:
  .为表增加约束:
  Alter table 表名 ADD constraint 约束名 约束类型(字段);
  .删除表中的约束:
  Alter table 表名 drop constraint 约束名;
 可以发现,如果要维护约束,肯定需要一个正确的名字才可以,可是在这五种约束之中,非空约束作为一个特殊的约束无法操作,例如:
     drop table member cascade constraint purge;
  create table member( mid number,
  name varchar(50) not null, age number(3) );
 范例:为表中增加主键约束
     Alter table member Add constraint pk_mid primary key(mid);
  alter table member add constraint ck_age check(age between 1 to 250);
 范例:删除表主键约束
     Alter table member drop constraint pk_mid;
 7、查询约束
    在oracle之中所有的对象都会在数据字典保存,而约束也是一样的,所以如果想要知道有哪些约束,可以直接查询“user_constraint”数据字典:select * from user_constraints;但是这个查询出来的约束只是列出名字,而并没有告诉在哪个字段上有此约束,所以此时可以查看另外一张数据字典表“user_cons_columns”;注另外种格式化:Col 字段名 for A列数;
        col owner for A15;
     col constraint_name for A15;
     col table_name  for A15;
     col column_name for A15;
     select owner,constraint_name,table_name,column_name from user_cons_columns;
---------------------------------------------------
    数据库脚本:
   1、建表:
        DROP TABLE grade PURGE;
     DROP TABLE  sproter PURGE;
     DROP TABLE item    PURGE;
     CREATE TABLE sporter(
     sproterid  number(4)  primary key,
     name   varchar(20)  not null,
     sex    varchar(10)  check(sex in('男','女'),
     department varchar(20)  not null);
    
     CREATE TABLE item(
     itemid  varchar(4)  primary key,
     itemName varchar(20) not null,
     location varchar(20) not null);
    
     CREATE TABLE grade(
     sproterid  number(4) references sporter(sporterid) on delete cascade,
     itemid    varchar(4)  references item(itemid) on delete cascade,
     mark    number(1)  check(mark in(0,2,4,6));
  2、增加数据
     运动员(1001,李明,男,计算机系
      1002,张三,男,数学系
      1003,李四,男,计算机系
      1004,王二,男,物理系
      1005,李娜,女,心理系
      1006,孙俪,女,数学系)
         insert into sporter(sproterid, name,sex,department) values(1001,'李明','男','计算机系');
   ... ...
   项目(x001,男子五千米,一操场
   ... ...)
   insert into item(itemid, itemName, location) values('x001','男子五千米','一操场');
   ... ...
   积分(1001,x001, 6
   ... ...)
   insert into grade(sporterid, itemid, mark) values(1001,'x001', 6);
   ... ...
  3、数据操作
      。求出目前积分最高的系名,及其积分
      .确定所需的数据表:
         |-sporter表;
      |-grade表;
      .确定已知关联字段:
     sproter.sproterid=grade.sporterid
            执行:select s.department,   sum(g.mark)
         from sporter s, grader g
      where s.sporterid=g.sporterid
     【得到系和积分。】
      group by s.department
     【得到系和总积分】
      做法一:不考虑相同积分的问题,所有数据由高->低,取第一个数据; 
      select * from( select s.department,sum(g.mark)
         from sporter s, grader g
      where s.sporterid=g.sporterid
      group by s.department, sum desc) where rownum=1;
      做法二:考虑相同积分的问题,则必须首先进行分组函数的嵌套,求出最高积分是多少,而后再用此内容与之前的分组进行过滤。
      select s.department, sum(g.mark) sum from sproter s, grade g where s.sporterid=g.sporterid group by s.department having sum(g.mark)=(select Max(sum(g.mark)) sum from sporter s, grade g where s.sporterid=g.spoeterid
        group by s.department);
--------------------------------------------------

posted on 2012-06-25 22:05  明留  阅读(890)  评论(0编辑  收藏  举报