MySQL第八篇------DQL之约束(对表中字段的限定)

版权声明:未经本人同意不得转载 https://blog.csdn.net/object_oriented_/article/details/87891003

   约束:
           对表中的数据(字段)进行限定,保证数据的正确性、有效性和完整性。非法的数据不能够添加到数据库中
        分类: 
              1) 主键约束:primary key
              2) 非空约束:not null
              3) 唯一约束:unique
              4) 外键约束:foreign key

1.  主键约束:primary key

       主键是给数据库和程序使用的,不是给最终的客户使用的。主键有没有含义没有关系,只要不重复,非空即可。
      通常不用业务字段作为主键,单独给每张表设计一个 id 的字段,把 id 作为主键,不建议使用学号身份证号等作为主键
        1) 注意:
                   1) 含义:非空且唯一
                   2)一张表只能有一个字段为主键
                   3) 主键就是表中记录的唯一标识

        2) 在创建表时,添加主键约束

字段名 字段类型 PRIMARY KEY

                       create table stu(
                               id int primary key,-- 给id添加主键约束
                               name varchar(20)
                        );

        3) 删除主键
            -- 错误 alter table stu modify id int ;
            ALTER TABLE stu DROP PRIMARY KEY;

        4) 创建完表后,添加主键

ALTER TABLE 表名 ADD PRIMARY KEY(字段名);  -- 格式1 对字段直接添加主键
ALTER TABLE stu MODIFY id INT PRIMARY KEY;  -- 格式2 对字段修改成主键

         5) 自动增长(主键):

AUTO_INCREMENT 表示自动增长(字段类型必须是整数类型)

                    1) 概念:如果某一列是数值类型的,使用 auto_increment 可以来完成值得自动增长

                     2)在创建表时,添加主键约束,并且完成主键自增长
                           create table stu(
                                   id int primary key auto_increment,-- 给id添加主键约束
                                   name varchar(20)
                         );

                     3) 删除自动增长
                               ALTER TABLE stu MODIFY id INT;
                     4)  添加自动增长
                               ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;

                     5) 默认地 AUTO_INCREMENT 的开始值是 1,如果修改起始值,请使用下列 SQL 语法
                        a) 创建表时指定起始值

CREATE TABLE 表名(
列名 int primary key AUTO_INCREMENT
) AUTO_INCREMENT=起始值;
-- 指定起始值为 100
create table stu (
id int primary key auto_increment,
name varchar(20)
) auto_increment = 100;

insert into st4 values (null, '张三'); -- 插入数据
                         b) 创建好后修改初始值
ALTER TABLE 表名 AUTO_INCREMENT=起始值;
alter table stu auto_increment = 200;
insert into stu values (null, '李四');
   删除表,两种关键字对主键的影响:
DELETE 删除所有的记录之后,自增长没有影响。之前自增长到5删除后,继续从6开始
TRUNCATE 删除以后,自增长又重新开始。从1开始

2. 非空约束:not null

  某一列的值不能为null,限制了一列不能有null值

字段名 字段类型 NOT NULL

        1) 创建表时添加约束
            create table stu(
                id int,
                name varchar(20) not null    -- name为非空
            );
           
        2) 创建表完后,添加非空约束
            ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;

        3) 删除name的非空约束
            ALTER TABLE stu MODIFY NAME VARCHAR(20);    

3. 唯一约束:unique

某一列的值不能重复

字段名 字段类型 UNIQUE

                 1. 注意:
                         * 唯一约束可以有NULL值,null 没有数据,不存在重复的问题,所以可以插入多个null,不建议
                 2. 在创建表时,添加唯一约束
                         CREATE TABLE stu(
                              id INT,
                              phone_number VARCHAR(20) UNIQUE -- 手机号
                           );
                 3. 删除唯一约束
                          ALTER TABLE stu DROP INDEX phone_number;
                 4. 在表创建完后,添加唯一约束
                          ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
       

4. 外键约束:foreign key

            什么是外键:在从表中与主表主键对应的那一列,如:员工表中的 dep_id
            主表: 一方,用来约束别人的表
            从表: 多方,被别人约束的表

让表于表产生关系,从而保证数据的正确性。
         1. 在创建表时,可以添加外键
             语法:

[CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)

                       create table 表名(
                                    ....
                                  外键列
                                  constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
                        );

         2. 删除外键
                        ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;

         3. 创建表之后,添加外键

ALTER TABLE 从表 ADD [CONSTRAINT] [外键约束名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主
键字段名);

   ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);  
         4. 级联操作(联动操作)
     
      以上操作会遇到 更改外键 时,被限制,不能更改和删除操作的问题
            原因是和主表的主键进行了关联,进行了外键限制
            解决方式就是级联操作
           什么是级联操作:
                        在修改和删除主表的主键时,同时更新或删除副表的外键值,称为级联操作
           语法:

级联操作语法 描述
ON UPDATE CASCADE 级联更新, 只能是创建表的时候创建级联关系。更新主表中的主键, 从表中的外键列也自动同步更新
ON DELETE CASCADE 级联删除

                       1. 添加级联操作
                              语法:ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE  ;
                       2. 分类:
                                 1. 级联更新:ON UPDATE CASCADE 
                                 2. 级联删除:ON DELETE CASCADE 
              5 .注意点   :
                                
外键可以为NULL, 但是不可以为不存在的外键值(和主键一一对应)           
                                 
 

外键约束综合案例:

创建一个员工表包含字段(id, name, age, dep_name, dep_location), 其中id 主键并自动增长

CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30),
age INT,
dep_name VARCHAR(30),
dep_location VARCHAR(30)
);

-- 添加数据
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('张三', 20, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('李四', 21, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('王五', 20, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('小明', 20, '销售部', '深圳');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('小王', 22, '销售部', '深圳');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('小张', 18, '销售部', '深圳');

  
从表中看出总以上数据表的缺点是数据冗余, 后期还会出现增删改的问题
解决方案:分成 2 张表(此时还未使用外键约束)

-- 创建部门表(id,dep_name,dep_location)  一方,主表

create table department(
id int primary key auto_increment,
dep_name varchar(20),
dep_location varchar(20)
);

-- 创建员工表(id,name,age,dep_id) 多方,从表

create table employee(
id int primary key auto_increment,
name varchar(20),
age int,
dep_id int -- 外键对应主表的主键
)

-- 添加 2 个部门
insert into department values(null, '研发部','广州'),(null, '销售部', '深圳');

select * from department;

-- 添加员工,dep_id 表示员工所在的部门
INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小明', 20, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 22, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小张', 18, 2);

select * from employee;

    
问题:当我们在 employee 的 dep_id 里面输入不存在的部门,数据依然可以添加.但是并没有对应的部门,
           这时的数据是有误的, SQLyog中有架构器可以查看表设计的关系, 如下两张图 
     

实际应用中不能出现这种情况
从表(员工表)employee 的 (外键)dep_id 中的数据只能是(主表)department 表中存在的(主键) id

问题:  需要约束 dep_id 只能是 department 表中已经存在 id ,
解决:  使用外键约束

新建表时增加外键:

[CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
已有表增加外键:
ALTER TABLE 从表 ADD [CONSTRAINT] [外键约束名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主
键字段名)
-- 添加外键
--  删除从表 employee

drop table employee;

-- 创建从表 employee 并添加外键约束 emp_depid_fk

create table employee(
id int primary key auto_increment,
name varchar(20),
age int,
dep_id int, -- 外键对应主表的主键
-- 创建外键约束
constraint emp_depid_fk foreign key (dep_id) references department(id)
)

-- 正常添加数据:
INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小明', 20, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 22, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小张', 18, 2);

此时从表就引用主表部门表的主键作为从表的外键使用
                                          

-- 其他操作

-- 删除 employee 表的 emp_depid_fk 外键
alter table employee drop foreign key emp_depid_fk;

-- 在 employee 表存在的情况下添加外键
alter table employee add constraint emp_depid_fk
foreign key (dep_id) references department(id);


当再插入受外键约束的数据时报错       
                  

此时又会有一个问题: 

select * from department;
-- 要把部门表中的 id 值 2,改成 5,能不能直接更新呢?
UPDATE department SET id=5 WHERE id=2;

-- 要删除部门 id 等于 1 的部门, 能不能直接删除呢?
DELETE FROM department WHERE id=1;

 结果:    
         
       遇到以上问题的时候 可以先把从表的外键进行更改成NULL值,然后更改主表的主键, 最后把从表的外键改成和主表主键对应的值。但是遇到细节问题,就是外键可以为NULL, 但是不可以为不存在的外键值(和主键一一对应)
解决这类问题的办法就是级联操作:   
          添加级联操作格式
           语法:ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE  ;

    第一种方式先删除表的外键, 再进行添加外键的时候进行添加级联更新

-- 删除外键

ALTER TABLE employee DROP FOREIGN KEY emp_depid_fk;

-- 添加外键 
alter table employee add constraint emp_deptid_fk foreign key (dep_id)
 references department(id) ;

-- 添加外键 ,设置级联更新

alter table employee add constraint emp_deptid_fk foreign key (dep_id)
 references department(id) on update cascade ;

--  设置级联删除
alter table employee add constraint emp_deptid_fk foreign key (dep_id)
 references department(id) on delete cascade;

    第二种方式先删除表, 在重新创建表的时候进行添加级联更新

第二种方式
-- 删除 employee 表,重新创建 employee 表,添加级联更新和级联删除
drop table employee;

create table employee(
id int primary key auto_increment,
name varchar(20),
age int,
dep_id int, -- 外键对应主表的主键
-- 创建外键约束
constraint emp_depid_fk foreign key (dep_id) references
department(id) on update cascade on delete cascade
)


-- 再次添加数据到员工表和部门表
INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小明', 20, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 22, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小张', 18, 2);
-- 删除部门表
drop table department;
-- 把部门表中 id 等于 1 的部门改成 id 等于 3
update department set id=10 where id=1;

select * from employee;
select * from department;


-- 删除部门号是 2 的部门
delete from department where id=2;

在开发中, 级联的操作一定要慎用, 因为删除一个表的话其他的表或者数据都可能被删除掉

5. 默认值

  什么是默认值:

字段名 字段类型 DEFAULT 默认值
-- 创建一个学生表 stu,包含字段(id,name,address), 地址默认值是北京

create table stu (
id int,
name varchar(20),
address varchar(20) default '北京'
)

-- 添加一条记录,使用默认地址
insert into stu values (1, '张三', default); -- 默认北京

insert into stu (id,name) values (2, '李四'); -- 省略default关键字, 默认北京

insert into stu values (3, '王五', '山东');  -- 添加一条记录,不使用默认地址

select * from stu;

如果一个字段设置了非空与唯一约束,该字段与主键的区别?
1) 主键数在一个表中,只能有一个。不能出现多个主键。主键可以单列,也可以是多列。
2) 自增长只能用在主键上

以上约束主要说的是: 

约束名 关键字 说明
主键 primary key 1) 唯一
2) 非空
非空 not null 这一列必须有值
唯一 unique 这一列不能有重复值
外键 foreign key 主表中主键列,在从表中外键列
默认 default 如果一列没有值,使用默认值

                                                 <约束到此结束>

 

猜你喜欢

转载自blog.csdn.net/object_oriented_/article/details/87891003