Java学习笔记-零基础学MySQL(四)

19.9 MySQL 约束

约束用于确保数据库的数据满足特定的商业规则,在mysq|中,约束包括: not nulluniqueprimary keyforeign keycheck五种

主键约束,非空约束,唯一约束,外键约束,检查约束

注意:去除约束的办法

19.9.1 primary key

  1. 基本介绍

  2. 注意事项

    1. primary key 不能重复且不能为null
    2. 一张表最多只能有一个主键,但是可以是复合主键
    3. 主键有两种指定方式
      • 直接在字段名字后面:字段名 primary key
      • 在表定义最后写:primary key(列名)
    4. 使用desc 表名,可以看到primary key的情况
    5. 在实际开发中,每个表往往都会设计一个主键
    6. 删除主键约束:alter table 表名 drop primary key或者not null等
  3. 举例说明

    sql 复制代码
    -- 主键使用
    
    -- id	name 	email
    CREATE TABLE t17
    	(id INT PRIMARY KEY, -- 表示id列是主键 
    	`name` VARCHAR(32),
    	email VARCHAR(32));
    	
    -- 主键列的值是不可以重复
    INSERT INTO t17 VALUES(1, 'jack', 'jack@sohu.com');
    INSERT INTO t17 VALUES(2, 'tom', 'tom@sohu.com');
    INSERT INTO t17 VALUES(1, 'hsp', 'hsp@sohu.com');
    	
    SELECT * FROM t17;
    
    -- 主键使用的细节讨论
    -- primary key不能重复而且不能为 null。
    INSERT INTO t17 VALUES(NULL, 'hsp', 'hsp@sohu.com');
    -- 一张表最多只能有一个主键, 但可以是复合主键(比如 id+name)
    CREATE TABLE t18
    	(id INT PRIMARY KEY, -- 表示id列是主键 
    	`name` VARCHAR(32), PRIMARY KEY -- 错误的,不能添加两个主键
    	email VARCHAR(32));
    -- 演示复合主键 (id 和 name 做成复合主键)
    CREATE TABLE t18
    	(id INT , 
    	`name` VARCHAR(32), 
    	email VARCHAR(32),
    	PRIMARY KEY (id, `name`) -- 这里就是复合主键,即在添加数据时id与name不能同时相同
    	);
    
    INSERT INTO t18 VALUES(1, 'tom', 'tom@sohu.com');
    INSERT INTO t18 VALUES(1, 'jack', 'jack@sohu.com');
    INSERT INTO t18 VALUES(1, 'tom', 'xx@sohu.com'); -- 这里就违反了复合主键
    SELECT * FROM t18;
    
    -- 主键的指定方式 有两种 
    -- 1. 直接在字段名后指定:字段名  primakry key
    -- 2. 在表定义最后写 primary key(列名); 
    CREATE TABLE t19
    	(id INT , 
    	`name` VARCHAR(32) PRIMARY KEY, 
    	email VARCHAR(32)
    	);
    
    CREATE TABLE t20
    	(id INT , 
    	`name` VARCHAR(32) , 
    	email VARCHAR(32),
    	PRIMARY KEY(`name`) -- 在表定义最后写 primary key(列名)
    	);
     
    -- 使用desc 表名,可以看到primary key的情况
    
    DESC t20 -- 查看 t20表的结果,显示约束的情况
    DESC t18

19.9.2 not null 与 unique

  1. not null

  2. unique

    sql 复制代码
    -- unique的使用
    
    CREATE TABLE t21
    	(id INT UNIQUE ,  -- 表示 id 列是不可以重复的.
    	`name` VARCHAR(32) , 
    	email VARCHAR(32)
    	);	
    INSERT INTO t21 VALUES(1, 'jack', 'jack@sohu.com');
    INSERT INTO t21 VALUES(1, 'tom', 'tom@sohu.com');
    	
    -- unqiue使用细节
    -- 1. 如果没有指定 not null , 则 unique 字段可以有多个null
    -- 如果一个列(字段), 是 unique not null 使用效果类似 primary key
    INSERT INTO t21 VALUES(NULL, 'tom', 'tom@sohu.com');
    SELECT * FROM t21;
    -- 2. 一张表可以有多个unique字段
    
    CREATE TABLE t22
    	(id INT UNIQUE ,  -- 表示 id 列是不可以重复的.
    	`name` VARCHAR(32) UNIQUE , -- 表示name不可以重复 
    	email VARCHAR(32)
    	);
    DESC t22

19.9.3 foreign key

  1. 基本介绍

    sql 复制代码
    CONSTRAINT 外键名 FOREIGN KEY 字段名 REFERENCES 主表名(主键名)

    用于定义主表和从表之间的关系:外键约束要定义在从表上,主表则必须具有主键约束或是unique约束(即唯一),当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为null

    举例说明

    如下图所示,其中外键要定义在学生表上,即从表,且班级表id列唯一,即具有主键或者唯一约束,如果不唯一,那学生表的class_id到底对应那个班级则不明确,当建立外键约束后,除非班级表的班级里面已经没有学生了,才能将那个班级删除成功,同理,向学生表插入数据时,如果班级表中没有对应的id,则会插入失败,如果class_id为空,能插入成功

  2. 注意细节

  3. 举例

    sql 复制代码
    -- 外键演示
    
    -- 创建 主表 my_class
    CREATE TABLE my_class (
    	id INT PRIMARY KEY , -- 班级编号
    	`name` VARCHAR(32) NOT NULL DEFAULT '');
    
    -- 创建 从表 my_stu
    CREATE TABLE my_stu (
    	id INT PRIMARY KEY , -- 学生编号
    	`name` VARCHAR(32) NOT NULL DEFAULT '',
    	class_id INT , -- 学生所在班级的编号
    	-- 下面指定外键关系
    	FOREIGN KEY (class_id) REFERENCES my_class(id))
    -- 测试数据
    INSERT INTO my_class VALUES(100, 'java'), (200, 'web'), (300, 'php');
    	
    SELECT * FROM my_class;
    INSERT INTO my_stu VALUES(1, 'tom', 100);
    INSERT INTO my_stu VALUES(2, 'jack', 200);
    INSERT INTO my_stu VALUES(3, 'hsp', 300);
    INSERT INTO my_stu 
    	VALUES(4, 'mary', 400); -- 这里会失败...因为400班级不存在
    
    INSERT INTO my_stu 
    	VALUES(5, 'king', NULL); -- 可以, 外键 没有写 not null
    SELECT * FROM my_class;
    
    -- 一旦建立主外键的关系,数据不能随意删除了
    DELETE FROM my_class WHERE id = 100; 

19.9.4 check

  1. 基本介绍

  2. 举例讲解

    sql 复制代码
    -- 演示check的使用
    -- mysql5.7目前还不支持check ,只做语法校验,但不会生效,mysql 8.0已经生效
    -- 了解 
    -- 学习 oracle, sql server, 这两个数据库是真的生效.
    -- 测试
    CREATE TABLE t23 (
    	id INT PRIMARY KEY,
    	`name` VARCHAR(32) ,
    	sex VARCHAR(6) CHECK (sex IN('man','woman')),
    	sal DOUBLE CHECK ( sal > 1000 AND sal < 2000)
    	);
    	
    -- 添加数据
    INSERT INTO t23 VALUES(1, 'jack', 'mid', 1);
    SELECT * FROM t23;

19.9.5 自增长

  1. 基本介绍

  2. 注意细节

    1. 一般来说自增长是和primary key配合使用的

    2. 自增长也可以单独使用(但是需要配合一个unique

    3. 自增长修饰的字段为整数型的(虽然小数也可以但是非常非常少这样使用)

    4. 自增长默认从1开始,也可以通过如下命令修改

      mysql 复制代码
      alter table 表名 auto_increment = 新开始的值
    5. 如果添加数据时,给自增长字段(列)指定的值,则以指定的值为准,如果指定了字增长,一般来说,就按照自增长的规则来添加数据

    6. 自增长是在目前最大的数上进行增长,例如id这列有数据1,10,11,则自增长下一个数据为12

  3. 举例说明

    sql 复制代码
    -- 演示自增长的使用
    -- 创建表
    CREATE TABLE t24
    	(id INT PRIMARY KEY AUTO_INCREMENT,
    	 email VARCHAR(32)NOT NULL DEFAULT '',
    	 `name` VARCHAR(32)NOT NULL DEFAULT ''); 
    DESC t24
    
    -- 测试自增长的使用
    INSERT INTO t24 VALUES(NULL, 'tom@qq.com', 'tom');   -- 插入数据后 id 列为1
    INSERT INTO t24 (email, `name`) VALUES('hsp@sohu.com', 'hsp');  -- 插入数据后 id 列为2
    SELECT * FROM t24;
    
    -- 修改默认的自增长开始值
    ALTER TABLE t25 AUTO_INCREMENT = 100
    CREATE TABLE t25
    	(id INT PRIMARY KEY AUTO_INCREMENT,
    	 email VARCHAR(32)NOT NULL DEFAULT '',
    	 `name` VARCHAR(32)NOT NULL DEFAULT '');
    
    INSERT INTO t25 VALUES(NULL, 'mary@qq.com', 'mary');
    INSERT INTO t25 VALUES(666, 'hsp@qq.com', 'hsp');
    SELECT * FROM t25;
    
    CREATE DATABASE tmp;
    CREATE TABLE dept( /*部门表*/
        deptno MEDIUMINT   UNSIGNED  NOT NULL  DEFAULT 0,
        dname VARCHAR(20)  NOT NULL  DEFAULT "",
        loc VARCHAR(13) NOT NULL DEFAULT ""
    ) ;
    
    #创建表EMP雇员
    CREATE TABLE emp (
        empno  MEDIUMINT UNSIGNED  NOT NULL  DEFAULT 0, /*编号*/
        ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
        job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/
        mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/
        hiredate DATE NOT NULL,/*入职时间*/
        sal DECIMAL(7,2)  NOT NULL,/*薪水*/
        comm DECIMAL(7,2) NOT NULL,/*红利*/
        deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/
    ) ;
    
    #工资级别表
    CREATE TABLE salgrade (
        grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
        losal DECIMAL(17,2)  NOT NULL,
        hisal DECIMAL(17,2)  NOT NULL
    );
    
    #测试数据
    INSERT INTO salgrade VALUES (1,700,1200);
    INSERT INTO salgrade VALUES (2,1201,1400);
    INSERT INTO salgrade VALUES (3,1401,2000);
    INSERT INTO salgrade VALUES (4,2001,3000);
    INSERT INTO salgrade VALUES (5,3001,9999);	

19.9.6 练习 - 约束

sql 复制代码
-- 使用约束的课堂练习

CREATE DATABASE shop_db;

-- 现有一个商店的数据库shop_db,记录客户及其购物情况,由下面三个表组成:
-- 商品goods(商品号goods_id,商品名goods_name,单价unitprice,商品类别category,
-- 供应商provider);
-- 客户customer(客户号customer_id,姓名name,住址address,电邮email性别sex,身份证card_Id);
-- 购买purchase(购买订单号order_id,客户号customer_id,商品号goods_id,购买数量nums);
-- 1 建表,在定义中要求声明 [进行合理设计]:
-- (1)每个表的主外键;
-- (2)客户的姓名不能为空值;
-- (3)电邮不能够重复;
-- (4)客户的性别[男|女] check 枚举..
-- (5)单价unitprice 在 1.0 - 9999.99 之间 check

-- 商品goods
CREATE TABLE goods (
	goods_id INT PRIMARY KEY,
	goods_name VARCHAR(64) NOT NULL DEFAULT '',
	unitprice DECIMAL(10,2) NOT NULL DEFAULT 0 
		CHECK (unitprice >= 1.0 AND unitprice <= 9999.99),
	category INT NOT NULL DEFAULT 0,
	provider VARCHAR(64) NOT NULL DEFAULT '');
	
-- 客户customer(客户号customer_id,姓名name,住址address,电邮email性别sex,
-- 身份证card_Id);
CREATE TABLE customer(
	customer_id CHAR(8) PRIMARY KEY, -- 程序员自己决定
	`name` VARCHAR(64) NOT NULL DEFAULT '',
	address VARCHAR(64) NOT NULL DEFAULT '',
	email VARCHAR(64) UNIQUE NOT NULL,
	sex ENUM('男','女') NOT NULL ,  -- 这里老师使用的枚举类型, 是生效
	card_Id CHAR(18)); 
	
-- 购买purchase(购买订单号order_id,客户号customer_id,商品号goods_id,
-- 购买数量nums);
CREATE TABLE purchase(
	order_id INT UNSIGNED PRIMARY KEY,
	customer_id CHAR(8) NOT NULL DEFAULT '', -- 外键约束在后
	goods_id INT NOT NULL DEFAULT 0 , -- 外键约束在后
	nums INT NOT NULL DEFAULT 0,
	FOREIGN KEY (customer_id) REFERENCES customer(customer_id),
	FOREIGN KEY (goods_id) REFERENCES goods(goods_id));
DESC goods;
DESC customer;
DESC purchase;

19.10 MySQL 索引

简单介绍

通过在某字段上加索引加上索引后表所占内存会增加,但是通过where语句对该字段进行查询时,速度会快很多,如八万条数据,未加索引时查找耗时 4s4s4s 多,加上索引后变为 0.0020.0020.002 秒左右,索引的原理就是维护一颗排序二叉树,即一个堆,原来的查找就是直接遍历,加上索引后就是在排序二叉树上进行查找,大大减少了查找时间,但是只对加了索引的字段有效,同时如果频繁修改改字段的话,效率会比较低,因为维护堆的代价也比较大

19.10.1 索引原理及类型

  1. 索引原理

  2. 索引类型

    1. 主键索引primary key:主键自动的为主索引(即主键自动添加索引)

      sql 复制代码
      create table t1 (
          id int primary key, -- 主键,同时也是索引
          name varchar(32));
    2. 唯一索引unique

      sql 复制代码
      create table t2 (
          id int unique,  -- id是唯一的,同时也是索引,称为unique索引
          name varchar(32));
    3. 普通索引index

    4. 全文索引fulltext(适用于MyISAM)

      一般开发中不使用mysql自带的全文索引,而是使用:全文搜索SolrElasticSearch(ES)

19.10.2 索引的使用

  1. 基本使用

    sql 复制代码
    -- 演示mysql的索引的使用
    -- 创建索引
    CREATE TABLE t25 (
    	id INT ,
    	`name` VARCHAR(32));
    	
    -- 查询表是否有索引
    SHOW INDEXES FROM t25;
    -- 添加索引
    -- 添加唯一索引 
    CREATE UNIQUE INDEX id_index ON t25 (id);
    -- 添加普通索引方式1
    CREATE INDEX id_index ON t25 (id);
    -- 如何选择 
    -- 1. 如果某列的值,是不会重复的,则优先考虑使用unique索引, 否则使用普通索引
    -- 添加普通索引方式2
    ALTER TABLE t25 ADD INDEX id_index (id)
    
    -- 添加主键索引
    CREATE TABLE t26 (
    	id INT ,
    	`name` VARCHAR(32));
    ALTER TABLE t26 ADD PRIMARY KEY (id)
    
    SHOW INDEX FROM t25
    
    -- 删除索引
    DROP INDEX id_index ON t25
    -- 删除主键索引
    ALTER TABLE t26 DROP PRIMARY KEY
    -- 修改索引 , 先删除,在添加新的索引
    
    
    -- 查询索引
    -- 1. 方式
    SHOW INDEX FROM t25
    -- 2. 方式
    SHOW INDEXES FROM t25
    -- 3. 方式
    SHOW KEYS FROM t25
    -- 4 方式
    DESC t25
  2. 注意事项

    1. 较频繁的作为查询添加的字段应该创建索引

      mysql 复制代码
      select from emp where empno = 1;
    2. 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件

      mysql 复制代码
      select * from emp where sex = '男';
    3. 更新非常频繁的字段不适合创建索引

      mysql 复制代码
      select * from emp where logincount = 1;
    4. 不会出现 where 子句的字段不适合用索引,即不会被用作查询条件的

  3. 练习

相关推荐
吗喽对你问好4 小时前
场景题:如果一个大型项目,某一个时间所有的CPU的已经被占用了,导致服务不可用,我们开发人员应该如何使服务器尽快恢复正常
java·linux·运维·服务器
EthanChou20204 小时前
rust学习之开发环境
开发语言·学习·rust
MrSYJ4 小时前
别告诉我你还不会OAuth 2.0授权过滤器:OAuth2AuthorizationEndpointFilter第一篇
java·后端·微服务
渣哥4 小时前
学会 Java 异常处理,其实没你想的那么难
java
知其然亦知其所以然4 小时前
百万商品大数据下的类目树优化实战经验分享
java·后端·elasticsearch
DemonAvenger4 小时前
大数据量下的MySQL优化策略:从理论到实战,助你游刃有余
数据库·mysql·性能优化
Lethehong4 小时前
飞算JavaAI炫技赛:一天完成学生成绩综合统计分析系统开发(含源码)
java·java开发·飞算java炫技赛
何故染尘優4 小时前
限流、降级、熔断的区别和应用场景
java·服务器·网络
Hello_Embed4 小时前
STM32HAL 快速入门(十七):UART 硬件结构 —— 从寄存器到数据收发流程
笔记·stm32·单片机·嵌入式硬件·学习