MySQL数据库

MySQL数据库

  • 一、SQL 结构化查询语言
    • 1.1、SQL概述
    • 1.2、SQL基本语法
    • 1.3、DDL 数据定义语⾔
      • 1.3.1、DDL-数据库操作
      • 1.3.2、DDL-数据表操作
    • 1.4、MySQL数据类型
      • 1.4.1、数值类型
      • 1.4.2、字符串类型
      • 1.4.3、日期类型
    • 1.5、字段约束
      • 1.5.1、约束介绍
      • 1.5.2、非空约束
      • 1.5.3、唯⼀约束
      • 1.5.4、主键约束
      • 1.5.5、主键自动增长
      • 1.5.6、联合主键
    • 1.6、DML 数据操纵语言
    • 1.7、DQL 数据查询语⾔
      • 1.7.1、查询基础语法
      • 1.7.2、where子句
      • 1.7.3、LIKE子句
      • 1.7.4、对查询结果的处理
      • 1.7.5、排序 - order by
      • 1.7.6、聚合函数
      • 1.7.7、日期函数和字符串函数
      • 1.7.8、分组查询 - group by
      • 1.7.9、分页查询 - limit
  • 二、数据表的关联关系
    • 2.1、关联关系介绍
    • 2.2、⼀对⼀关联
    • 2.3、一对多与多对一
    • 2.4、多对多关联
    • 2.5、外键约束
    • 2.6、外键约束-级联
  • 三、连接查询
    • 3.1、内连接 INNER JOIN
    • 3.2、左连接 LEFT JOIN
    • 3.3、右连接 RIGHT JOIN
    • 3.4、数据表别名
    • 3.5、子查询/嵌套查询
  • 四、存储过程
    • 4.1、存储过程介绍
      • 4.1.1、SQL指令执行过程
      • 4.1.2、存储过程的介绍
    • 4.2、创建存储过程
      • 4.2.1、存储过程创建语法
      • 4.2.2、示例
    • 4.3、调用存储过程
    • 4.4、存储过程中变量的使用
      • 4.4.1、定义局部变量
      • 4.4.2、定义用户变量
      • 4.4.3、给变量设置值
    • 4.5、存储过程的参数
    • 4.6、存储过程中流程控制
      • 4.6.1 分支语句
      • 4.6.2、循环语句
    • 4.7、存储过程管理
      • 4.7.1、查询存储过程
      • 4.7.2、修改存储过程
      • 4.7.3、删除存储过程
    • 4.8、游标
  • 五、触发器
    • 5.1、触发器操作
    • 5.2、NEW与OLD
    • 5.3、触发器使用总结
  • 六、视图
    • 6.1、视图的概念
    • 6.2、视图的作用
    • 6.3、创建视图
    • 6.4、视图数据的特性
    • 6.5、查询视图结构
    • 6.6、修改视图
    • 6.7、删除视图
  • 七、索引
    • 7.1、索引的介绍
    • 7.2、索引的分类
    • 7.3、创建索引
    • 7.4、索引使用
    • 7.5、查看索引
    • 7.6、删除索引
    • 7.7、索引的使用总结

一、SQL 结构化查询语言

1.1、SQL概述

SQL(Structured Query Language)结构化查询语⾔,用于存取、查询、更新数据以及管理关系型数据库系统

SQL是在1981年由IBM公司推出,⼀经推出基于其简洁的语法在数据库中得到了广泛的应用,成为主流数据库的通用规范。

  • SQL由ANSI组织确定规范
  • 在不同的数据库产品中遵守SQL的通用规范,但是也对SQL有⼀些不同的改进,形成了⼀些数据库的专有指令
    • MySQL:limit
    • SQLServer : top
    • Oracle:rownum

根据SQL指令完成的数据库操作的不同,可以将SQL指令分为四类

  • DDL(Data Definition Language)数据定义语⾔
    用于完成对数据库对象(数据库、数据表、视图、索引等)的创建、删除、修改
  • DML(Data Manipulation Language)数据操作/操纵语⾔
    用于完成对数据表中的数据的添加、删除、修改操作
    添加:将数据存储到数据表
    删除:将数据从数据表移除
    修改:对数据表中的数据进⾏修改
  • DQL(Data Query Language)数据查询语⾔
    用于将数据表中的数据查询出来
  • DCL(Data Control Language)数据控制语⾔
    用于完成事务管理等控制性操作

1.2、SQL基本语法

在MySQL Command Line Client 或者Navicat等工具中都可以编写SQL指令

  • SQL指令不区分大小写
  • 每条SQL表达式结束之后都以;结束
  • SQL关键字之间以空格进行分隔
  • SQL之间可以不限制换行(可以有空格的地⽅就可以有换行)

1.3、DDL 数据定义语⾔

1.3.1、DDL-数据库操作

使⽤DDL语句可以创建数据库、查询数据库、修改数据库、删除数据库

## 查询数据库
# 显示当前mysql中的数据库列表
show databases;

# 显示指定名称的数据的创建的SQL指令
show create database <dbName>;


## 创建数据库
# 创建数据库 dbName表示创建的数据库名称,可以⾃定义
create database <dbName>;

# 创建数据库,当指定名称的数据库不存在时执行创建
create database if not exists <dbName>;

# 在创建数据库的同时指定数据库的字符集(字符集:数据存储在数据库中采⽤的编码格式utf8 gbk)
create database <dbName> character set utf8;


## 修改数据库 修改数据库字符集
alter database <dbName> character set utf8; # utf8 gbk


## 删除数据库 删除数据库时会删除当前数据库中所有的数据表以及数据表中的数据
# 删除数据库
drop database <dbName>;

# 如果数据库存在则删除数据库
drop database if exists <dbName>;


## 使⽤/切换数据库
use <dbName>

1.3.2、DDL-数据表操作

数据表实际就是⼀个⼆维的表格,⼀个表格是由多列组成,表格中的每⼀类称之为表格的⼀个字段。

## 创建数据表
create table user(
	 id int not null unique,
	 name varchar(20) not null,
	 gender char(2) not null,
	 age int not null,
	 tel char(11) not null unique,
	 address varchar(30) unique
);

## 查询数据表
show tables; 

## 查询表结构
desc <tableName>; 

## 删除数据表
drop table <tableName>;

## 当数据表存在时删除数据表
drop table if exists <tableName>;


## 修改数据表
# 修改表名
alter table <tableName> rename to <newTableName>;

# 数据表也是有字符集的,默认字符集和数据库⼀致
alter table <tableName> character set utf8;

# 添加列(字段)
alter table <tableName> add <columnName> varchar(200);

# 修改列(字段)的列表和类型
alter table <tableName> change <oldColumnName> <newCloumnName> <type>;

# 只修改列(字段)类型
alter table <tableName> modify <columnName> <newType>;

# 删除列(字段)
alter table <tableName> drop <columnName>;

1.4、MySQL数据类型

数据类型,指的是数据表中的列中⽀持存放的数据的类型

1.4.1、数值类型

在mysql中有多种数据类型可以存放数值,不同的类型存放的数值的范围或者形式是不同的

类型 内存空间大小 范围 说明
tinyint 1byte 有符号 -128~127
⽆符号 0~255
特小型整数(年龄)
smallint 2byte 有符号 -32768 ~ 32767
⽆符号 0~65535
小型整数
mediumint 3byte 有符号 -2^31 ~ 2^31 - 1
⽆符号 0~2^32-1
中型整数
int/integer 4byte 整数
bigint 8byte 大型整数
float 4byte 单精度
double 8byte 双精度
decimal 第⼀参数+2 decimal(10,2)
表示数值⼀共有10位
⼩数位有2位

1.4.2、字符串类型

存储字符序列的类型

类型 字符长度 说明
char 0~255字节 定⻓字符串,最多可以存储255个字符 ;当我们指定数据表字段为char(n)
此列中的数据最⻓为n个字符,如果添加的数据少于n,则补’\u0000’⾄n⻓度
varchar 0~65536字节 可变⻓度字符串,此类型的类最⼤⻓度为65535
tinyblob 0~255 字节 存储⼆进制字符串
blob 0~65535 存储⼆进制字符串
mediumblob 0~1677215字节 存储⼆进制字符串
longblob 0~4294967295字节 存储⼆进制字符串
tinytext 0~255字节 ⽂本数据(字符串)
text 0~65535字节 ⽂本数据(字符串)
mediumtext 0~1677215字节 ⽂本数据(字符串)
longtext 0~4294967295字节 ⽂本数据(字符串)

1.4.3、日期类型

在MySQL数据库中,我们可以使用字符串来存储时间,但是如果我们需要基于时间字段进行查询操作(查询在某个时间段内的数据)就不便于查询实现

类型 格式 说明
date 2021-09-13 日期,只存储年月日
time 11:12:13 时间,只存储时分秒
year 2021 年份
datetime 2021-09-13 11:12:13 日期+时间,存储年⽉日时分秒
timestamp 20210913 111213 日期+时间 (时间戳)

1.5、字段约束

1.5.1、约束介绍

在创建数据表的时候,指定的对数据表的列的数据限制性的要求(对表的列中的数据进行限制)

为什么要给表中的列添加约束呢?

  • 保证数据的有效性
  • 保证数据的完整性
  • 保证数据的正确性

字段常见的约束有哪些呢?

  • 非空约束(not null):限制此列的值必须提供,不能为null
  • 唯⼀约束(unique):在表中的多条数据,此列的值不能重复
  • 主键约束(primary key):⾮空+唯⼀,能够唯⼀标识数据表中的⼀条数据
  • 外键约束(foreign key):建立不同表之间的关联关系

1.5.2、非空约束

限制数据表中此列的值必须提供

创建表:设置图书表的 name not null

create table books(
    id int,
    name varchar(10) not null,
    author varchar(20)
);

添加数据:id和author 不给值,可以默认为null,如果name不给值则提示添加错误

如果添加中文报错,在创建数据库时选择编码为utf8或utf8mb4

1.5.3、唯⼀约束

在表中的多条数据,此列的值不能重复
创建表:设置图书表的name为 unique

create table books(
    id int unique,
    name varchar(10) not null,
    author varchar(20)
);

1.5.4、主键约束

主键——就是数据表中记录的唯⼀标识,在⼀张表中只能有⼀个主键(主键可以是⼀个列,也可以是多个列的组合)

当⼀个字段声明为主键之后,添加数据时:

  • 此字段数据不能为null
  • 此字段数据不能重复
## 方式一:创建表时添加主键约束
create table books(
    id int primary key,
    name varchar(10) not null,
    author varchar(20)
);

## 方式二:创建表时添加主键约束
create table books(
    id int ,
    name varchar(10) not null,
    author varchar(20),
		primary key(id)
);

## 删除数据表主键约束
alter table books drop primary key; 

## 创建表时没有添加主键约束
create table books(
    id int ,
    name varchar(10) not null,
    author varchar(20)
);

## 创建表之后添加主键约束
alter table books modify id int primary key;

1.5.5、主键自动增长

在我们创建⼀张数据表时,如果数据表中有列可以作为主键(例如:用户表的id、图书表的id)我们可以直接这是这个列为主键;
当有些数据表中没有合适的列作为主键时,我们可以额外定义⼀个与记录本身⽆关的列(ID)作为主键,此列数据⽆具体的含义主要⽤于标识⼀条记录,在mysql中我们可以将此列定义为int,同时设置为自动增长,当我们向数据表中新增⼀条记录时,⽆需提供ID列的值,它会⾃动⽣成。

## 定义主键⾃动增⻓
## 定义int类型字段⾃动增⻓: auto_increment
create table types(
    type_id int primary key auto_increment,
    type_name varchar(20) not null,
    type_remark varchar(100)
);

注意:⾃动增⻓从1开始,每添加⼀条记录,⾃动的增⻓的列会⾃定+1,当我们把某条记录删除之后再添加数据,⾃动增⻓的数据也不会重复⽣成(⾃动增⻓只保证唯⼀性、不保证连续性)

1.5.6、联合主键

联合主键——将数据表中的多列组合在⼀起设置为表的主键

## 定义联合主键
create table grades(
    user_id int,
    course_id int,
    score int,
    primary key(user_id, course_id)
);

注意:在实际企业项⽬的数据库设计中,联合主键使⽤频率并不⾼;当⼀个张数据表中没有明确的字段可以作为主键时,我们可以额外添加⼀个ID字段作为主键。

1.6、DML 数据操纵语言

用于完成对数据表中数据的插入、删除、修改操作

## 插入数据
insert into <tableName>(columnName,columnName....)
values(value1,value2....);

## 删除数据--从数据表中删除满⾜特定条件(所有)的记录
delete from <tableName> [where conditions]; 

## 删除数据--一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。
##			并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。
truncate table user;

### 修改数据--对数据表中已经添加的记录进⾏修改
update <tableName> set columnName=value [where conditions] 

1.7、DQL 数据查询语⾔

从数据表中提取满足特定条件的记录

  • 单表查询
  • 多表联合查询

1.7.1、查询基础语法

## select 关键字后指定要显示查询到的记录的哪些列
select colnumName1[,colnumName2,colnumName3...] from <tableName> [where conditions];

## 如果要显示查询到的记录的所有列,则可以使⽤ * 替代字段名列表 (在项⽬开发中不建议使⽤*)
select * from user;

1.7.2、where子句

在删除、修改及查询的语句后都可以添加where子句(条件),用于筛选满⾜特定的添加的数据进⾏删除、修改和查询操作。

条件关系运算符

  • = 等于
  • !=、<> 不等于
  • > 大于
  • < 小于
  • >= 大于等于
  • <= 小于等于
  • between and 区间查询 between v1 and v2 [v1,v2]

条件逻辑运算符

在where⼦句中,可以将多个条件通过逻辑预算(and or not )进⾏连接,通过多个条件来筛选要操作的数据。

  • and 并且 筛选多个条件同时满足的记录
  • or 或者 筛选多个条件中⾄少满足⼀个条件的记录
  • not 取反

1.7.3、LIKE子句

在where子句的条件中,我们可以使⽤like关键字来实现模糊查询

在like关键字后的reg表达式中

  • % 表示任意多个字符 【 %o% 包含字⺟o】
  • _ 表示任意⼀个字符 【 _o% 第⼆个字⺟为o】

1.7.4、对查询结果的处理

  • select colnumName1, columnName2,…
    声明显示查询结果的指定列
  • select distinct colnumName1, columnName2…
    消除重复行
  • select colnumName1 + columnName2…
    对从数据表中查询的记录的列进行⼀定的运算之后显示出来
  • select colnumName as newColnumName…
    字段取别名

1.7.5、排序 - order by

将查询到的满足条件的记录按照指定的列的值升序/降序排列

order by columnName 表示将查询结果按照指定的列排序

  • asc 按照指定的列升序(默认)
  • desc 按照指定的列降序

多字段排序: 先满⾜第⼀个排序规则,当第⼀个排序的列的值相同时再按照第⼆个列的规则排序

1.7.6、聚合函数

SQL中提供了⼀些可以对查询的记录的列进行计算的函数——聚合函数

  • count
    统计函数,统计满足条件的指定字段值的个数(记录数)
  • max
    计算最⼤值,查询满足条件的记录中指定列的最⼤值
  • min
    计算最小值,查询满足条件的记录中指定列的最小值
  • sum
    计算和,查询满足条件的记录中 指定的列的值的总和
  • avg
    求平均值,查询满足条件的记录中 计算指定列的平均值

1.7.7、日期函数和字符串函数

日期函数

当我们向日期类型的列添加数据时,可以通过字符串类型赋值(字符串的格式必须为yyyy-MM-dd hh:mm:ss),如果我们想要获取当前系统时间添加到日期类型的列,可以使⽤now()或者sysdate()

  • 通过字符串类型 给日期类型的列赋值
  • 通过now()获取当前时间
  • 通过sysdate()获取当前时间

字符串函数

  • concat(colnum1, colunm2,…)
    拼接多列
  • upper(column)
    将字段的值转换成大写
  • lower(column)
    将指定列的值转换成小写
  • substring(column, start, len)
    从指定列中截取部分显示 start从1开始

1.7.8、分组查询 - group by

分组——就是将数据表中的记录按照指定的类进行分组

语法

select 分组字段/聚合函数
from 表名
[where 条件]
group by 分组列名 [having 条件]
[order by 排序字段]

select 后使⽤ * 显示对查询的结果进行分组之后,显示每组的第⼀条记录(这种显示通常是⽆意义的)
select 后通常显示分组字段和聚合函数(对分组后的数据进⾏统计、求和、平均值等)

语句执行顺序:

  1. 先根据where条件从数据库查询记录
  2. group by对查询记录进行分组
  3. 执行having对分组后的数据进行筛选

1.7.9、分页查询 - limit

当数据表中的记录比较多的时候,如果⼀次性全部查询出来显示给⽤户,用户的可读性体验性就不太好,因此我们可以将这些数据分页进行展示。

## 语法
select ...
from ...
where ...
limit param1,param2
  • param1 int , 表示获取查询语句的结果中的第⼀条数据的索引(索引从0开始)
  • param2 int, 表示获取的查询记录的条数(如果剩下的数据条数

二、数据表的关联关系

2.1、关联关系介绍

MySQL是⼀个关系型数据库,不仅可以存储数据,还可以维护数据与数据之间的关系 ——通过在数据表中添加字段建⽴外键约束

数据与数据之间的 关联关系 分为四种:

  • ⼀对⼀关联
  • ⼀对多关联
  • 多对⼀关联
  • 多对多关联

2.2、⼀对⼀关联

  • 人 — 身份证 ⼀个人只有⼀个身份证、⼀个身份证只对应⼀个人
  • 学⽣ — 学籍 ⼀个学生只有⼀个学籍、⼀个学籍也对应唯⼀的⼀个学生
  • 用户 — 用户详情 ⼀个用户只有⼀个详情、⼀个详情也只对应⼀个用户

⽅法1:
主键关联——两张数据表中主键相同的数据为相互对应的数据

⽅法2:
唯⼀外键 —— 在任意⼀张表中添加⼀个字段添加外键约束与另⼀张表主键关联,并 且将外键列添加唯⼀约束

2.3、一对多与多对一

  • 班级 — 学生 (一对多) 一个班级包含多个学生
  • 学生 — 班级 (多对一) 多个学生可以属于同一个班级
  • 图书 — 分类
  • 商品 ---- 商品类别

⽅法: 在多的⼀端添加外键 ,与少的一端主键进行关联

2.4、多对多关联

  • 学⽣ — 课程 ⼀个学生可以选择多门课、⼀门课程也可以由多个学生选择
  • 会员 — 社团 ⼀个会员可以参加多个社团、⼀个社团也可以招纳多个会员

⽅法: 额外创建⼀张关系表来维护多对多关联——在关系表中定义两个外键,分别与两个数据表的主键进行关联

2.5、外键约束

将⼀个列添加外键约束与另⼀张表的主键(唯⼀列)进行关联之后,这个外键 约束的列添加的数据必须要在关联的主键字段中存在

案例:学⽣表 与 班级表

1.先创建班级表

CREATE TABLE classes ( 
	class_id INT PRIMARY KEY auto_increment, 
	class_name VARCHAR ( 40 ) NOT NULL UNIQUE, 
	class_remark VARCHAR ( 200 ) 
);

2.创建学⽣表(在学⽣表中添加外键与班级表的主键进行关联)

## 【⽅式⼀】在创建表的时候,定义cid字段,并添加外键约束
#  由于cid 列 要与classes表的class_id进⾏关联,因此cid字段类型和⻓度要与class_id⼀致
CREATE TABLE students (
	stu_num CHAR ( 8 ) PRIMARY KEY,
	stu_name VARCHAR ( 20 ) NOT NULL,
	stu_gender CHAR ( 2 ) NOT NULL,
	stu_age INT NOT NULL,
	cid INT,
	CONSTRAINT FK_STUDENTS_CLASSES FOREIGN KEY ( cid )REFERENCES classes ( class_id )
);

## 【⽅式⼆】先创建表,再添加外键约束
CREATE TABLE students (
	stu_num CHAR ( 8 ) PRIMARY KEY,
	stu_name VARCHAR ( 20 ) NOT NULL,
	stu_gender CHAR ( 2 ) NOT NULL,
	stu_age INT NOT NULL,
	cid INT 
);
# 在创建表之后,为cid添加外键约束
ALTER TABLE students ADD CONSTRAINT FK_STUDENTS_CLASSES FOREIGN KEY ( cid ) REFERENCES classes ( class_id );
# 删除外键约束
ALTER TABLE students DROP FOREIGN KEY FK_STUDENTS_CLASSES;

2.6、外键约束-级联

当学⽣表中存在学⽣信息关联班级表的某条记录时,就不能对班级表的这条记录进行修 改ID和删除操作,如下:

SELECT * FROM classes;
SELECT * FROM students;
UPDATE classes SET class_id=5 WHERE class_name='Java';
DELETE FROM classes WHERE class_id=2;

如果⼀定要修改Java 的班级ID,该如何实现呢 ? 将引⽤Java班级id的学⽣记录中的cid修改为 NULL 在修改班级信息表中Java记录的 class_id 将学生表中cid设置为NULL的记录的cid重新修改为 Java这个班级的新的id

三、连接查询

通过对DQL的学习,我们可以很轻松的从⼀张数据表中查询出需要的数据;在企业的应用开发中,我们经常需要从多张表中查询数据(例如:我们查询学生信息的时候需要同 时查询学生的班级信息),可以通过连接查询从多张数据表提取数据:

在MySQL中可以使用join实现多表的联合查询——连接查询,join按照其功能不同分为三个操作:

  • inner join 内连接
  • left join 左连接
  • right join 右连接

3.1、内连接 INNER JOIN

select ... from tableName1 inner join tableName2 ON 匹配条件 [where 条件];

笛卡尔积

  • 笛卡尔积(A集合&B集合):使用A中的每个记录⼀次关联B中每个记录,笛卡尔积的总数=A总数*B总数
  • 如果直接执行select … from tableName1 inner join tableName2; 会获取两种数 据表中的数据集合的笛卡尔积(依次使用tableName1 表中的每⼀条记录去匹配 tableName2的每条数据)

内连接条件
两张表时⽤inner join连接查询之后生产的笛卡尔积数据中很多数据都是⽆意义的,我们如何消除无意义的数据呢? —— 添加两张进行连接查询时的条件 使用 on 设置两张表连接查询的匹配条件

结果:只获取两种表中匹配条件成立的数据,任何⼀张表在另⼀种表如果没有找到对应 匹配则不会出现在查询结果中)。

3.2、左连接 LEFT JOIN

左连接:显示左表中的所有数据,如果在有右表中存在与左表记录满⾜匹配条件的数据,则 进行匹配;如果右表中不存在匹配数据,则显示为NULL

3.3、右连接 RIGHT JOIN

同上

3.4、数据表别名

如果在连接查询的多张表中存在相同名字的字段,我们可以使用 表名.字段名 来进行区分,如果表名太长则不便于SQL语句的编写,我们可以使⽤数据表别名

3.5、子查询/嵌套查询

⼦查询 — 先进行⼀次查询,第⼀次查询的结果作为第二次查询的源/条件(第二次查询 是基于第⼀次的查询结果来进行的)

  • 如果⼦查询返回的结果是⼀个值(单列单行),条件可以直接使⽤关系运算符=、 !=
  • 如果⼦查询返回的结果是多个值(单列多行),条件使用IN / NOT IN
  • 可以将子查询的结果作为一个虚拟表(多行多列),再基于这个虚拟表查询

四、存储过程

4.1、存储过程介绍

4.1.1、SQL指令执行过程

MySQL数据库_第1张图片
从SQL执行的流程中我们分析存在的问题:

  1. 如果我们需要重复多次执行相同的SQL,SQL执行都需要通过连接传递到MySQL,并且 需要经过编译和执行的步骤;
  2. 如果我们需要连续执行多个SQL指令,并且第⼆个SQL指令需要使用第⼀个SQL指令执行的结果作为参数;

4.1.2、存储过程的介绍

存储过程: 将能够完成特定功能的SQL指令进行封装(SQL指令集),编译之后存储在数据库服务器上,并且为之取⼀个名字,客户端可以通过名字直接调用这个SQL指令集,获取执行结果。

存储过程优点

  • SQL指令⽆需客户端编写,通过⽹络传送,可以节省网络开销,同时避免SQL指令在网络传输过程中被恶意篡改保证安全性;
  • 存储过程经过编译创建并保存在数据库中的,执行过程⽆需重复的进行编译操作,对SQL 指令的执行过程进行了性能提升;
  • 存储过程中多个SQL指令之间存在逻辑关系,⽀持流程控制语句(分⽀、循环),可以实现更为复杂的业务;

存储过程的缺点

  • 存储过程是根据不同的数据库进行编译、创建并存储在数据库中;当我们需要切换到其他的数据库产品时,需要重写编写针对于新数据库的存储过程;
  • 存储过程受限于数据库产品,如果需要高性能的优化会成为⼀个问题;
  • 在互联网项目中,如果需要数据库的高(连接)并发访问,使用存储过程会增加数据库的连接执行时间(因为我们将复杂的业务交给了数据库进行处理)

4.2、创建存储过程

4.2.1、存储过程创建语法

## 语法:
create procedure <proc_name>([IN/OUT args])
begin
 -- SQL
end;

4.2.2、示例

## 创建⼀个存储过程实现加法运算: Java语法中,⽅法是有参数和返回值的
## 存储过程中,是有输⼊参数 和 输出参数的
create procedure proc_test1(IN a int,IN b int,OUT c int)
begin
 SET c = a+b;
end;

4.3、调用存储过程

## 调⽤存储过程
## 定义变量@m
SET @m=0; 
## 调用存储过程,将3传递给a,将2传递给b,将@m传递给c
CALL proc_test1 (3,2,@m);
## 显示变量值
SELECT @m FROM DUAL;

4.4、存储过程中变量的使用

存储过程中的变量分为两种:

  • 局部变量
  • ⽤户变量

4.4.1、定义局部变量

局部变量:定义在存储过程中的变量,只能在存储过程内部使用局部变量定义语法

## 局部变量要定义在存储过程中,⽽且必须定义在存储过程开始
declare <attr_name> <type> [default value];

## 局部变量定义示例:
CREATE PROCEDURE proc_test2 ( IN a INT, OUT r INT ) BEGIN
	## 定义x int类型,默认值为0
	DECLARE x INT DEFAULT 0;
	## 定义y
	DECLARE y INT DEFAULT 1;
	
	SET x = a * a;
	
	SET y = a / 2;
	
	SET r = x + y;
END;

4.4.2、定义用户变量

用户变量:相当于全局变量,定义的⽤户变量可以通过 select @attrName from dual 进行查询

## 用户变量会存储在mysql数据库的数据字典中(dual)
## 用户变量定义使⽤set关键字直接定义,变量名要以@开头
SET@n=1;

4.4.3、给变量设置值

⽆论是局部变量还是用户变量,都是使用 set 关键字修改值

SET @n=1; 
CALL proc_test2 (6,@n); 
SELECT @n FROM DUAL;

用户变量使用注意事项
因为用户变量相当于全局变量,可以在SQL指令以及多个存储过程中共享,在开发中建议尽量少使用用户变量,用户变量过多会导致程序不易理解、难以维护。

4.5、存储过程的参数

MySQL存储过程的参数⼀共有三种:IN \ OUT \ INOUT

  • IN 输入参数
    输入参数——在调⽤存储过程中传递数据给存储过程的参数(在调用的过程必须为具有实际值的变量 或者 字面值)
  • OUT 输出参数
    输出参数——将存储过程中产⽣的数据返回给过程调用者,相当于Java⽅法的返回值,但不同的是⼀个存储过程可以有多个输出参数
  • INOUT 输入输出参数

4.6、存储过程中流程控制

在存储过程中⽀持流程控制语句用于实现逻辑的控制

4.6.1 分支语句

if-then-else

## 单分支:如果条件成立,则执行SQL
IF conditions THEN
	## SQL
END IF;

## 双分支:如果条件成立则执行SQL1,否则执行SQL2
IF conditions THEN
	## SQL1
ELSE
	## SQL2
END IF;

case

CREATE PROCEDURE proc_test3 (IN a INT) 
BEGIN 
	CASE a WHEN 1 THEN
		## SQL1 如果a的值为1 则执行SQL1
	WHEN 2 THEN
		## SQL2 如果a的值为2 则执行SQL2
	ELSE
		## SQL (如果变量的值和所有when的值都不匹配,则执行else中的这个SQL)
 END CASE;
END;

4.6.2、循环语句

while

CREATE PROCEDURE proc_test4 (IN num INT) 
BEGIN 
	DECLARE i INT; 
	SET i=0; 
	WHILE i< num DO
		-- SQL
		SET i=i+1; 
	END WHILE; 
END;
CALL proc_test4(4);

repeat

CREATE PROCEDURE proc_test5 (IN num INT) 
BEGIN 
	DECLARE i INT; 
	SET i=1; 
	REPEAT
		-- SQL
		SET i=i+1; 
		UNTIL i> num 
	END REPEAT; 
END; 
CALL proc_test5 (4);

loop

CREATE PROCEDURE proc_test6 (IN num INT) 
BEGIN 
	DECLARE i INT; 
	SET i=0; 
	myloop : LOOP-- SQL
			INSERT INTO classes (class_name) VALUES (CONCAT('HTML',i			)); 
			SET i=i+1; 
			IF i=num THEN 
				LEAVE myloop; 
			END IF; 
	END LOOP; 
END; 
CALL proc_test6 (5);

4.7、存储过程管理

4.7.1、查询存储过程

存储过程是属于某个数据库的,也就是说当我们将存储过程创建在某个数据库之后,只能在当前数据库中调用此存储过程。

查询存储过程:查询某个数据库中有哪些存储过程

## 根据数据库名,查询当前数据库中的存储过程
SHOW PROCEDURE STATUS WHERE db='mysql_test';
-- 查询存储过程的创建细节
SHOW CREATE PROCEDURE mysql_test.proc_test1;

4.7.2、修改存储过程

修改存储过程指的是修改存储过程的特征/特性

ALTER PROCEDURE<proc_name> 特征1 [特征2 特征3 ....] 

存储过程的特征参数:

  • CONTAINS SQL 表示子程序包含 SQL 语句,但不包含读或写数据的语句
  • NO SQL 表示子程序中不包含 SQL 语句
  • READS SQL DATA 表示子程序中包含读数据的语句
  • MODIFIES SQL DATA 表示子程序中包含写数据的语句
  • SQL SECURITY { DEFINER |INVOKER } 指明谁有权限来执行
    • DEFINER 表示只有定义者自己才能够执行
    • INVOKER 表示调用者可以执行
  • COMMENT ‘string’ 表示注释信息
ALTER PROCEDURE proc_test1 READS SQL DATA;

4.7.3、删除存储过程

## 删除存储过程
## drop 删除数据库中的对象 数据库、数据表、列、存储过程、视图、触发器、索引....
## delete 删除数据表中的数据
DROP PROCEDURE proc_test1;

4.8、游标

游标可以用来依次取出查询结果集中的每⼀条数据——逐条读取查询结果集中的记录

游标的使用步骤

## 1、声明游标
DECLARE cursor_nanme CURSOR FOR select_statement;

## 2、打开游标
open mycursor; 

## 3、使用游标,使用游标:提取游标当前指向的记录(提取之后,游标⾃动下移)
FETCH mycursor INTO bname,bauthor,bprice;

## 4、关闭游标
CLOSE mycursor; 

五、触发器

5.1、触发器操作

触发器,就是⼀种特殊的存储过程。触发器和存储过程⼀样是⼀个能够完成特定功能、存储在数据库服务器上的SQL片段,但是触发器无需调用,当对数据表中的数据执行DML操作时自动触发这个SQL⽚段的执行,无需⼿动调用。

在MySQL,只有执行insertdeleteupdate操作才能触发触发器的执行。

## 创建触发器
create trigger tri_name
<before|after> -- 定义触发时机
<insert|delete|update> -- 定义DML类型
ON <table_name>
for each row -- 声明为⾏级触发器(只要操作⼀条记录就触发触发器执⾏⼀
次)
sql_statement -- 触发器操作


## 查看触发器
SHOW TRIGGERS;

## 删除触发器
DROP TRIGGER tri_test1;

5.2、NEW与OLD

触发器用于监听对数据表中数据的insert、delete、update操作,在触发器中通常处理⼀些DML的关联操作;我们可以使用 NEW 和 OLD 关键字在触发器中获取触发这个触发器的DML操作的数据

  • NEW
    在触发器中用于获取insert操作添加的数据、update操作修改后的记录
  • OLD
    在触发器中用于获取delete操作删除前的数据、update操作修改前的数据

5.3、触发器使用总结

优点

  • 触发器是⾃动执行的,当对触发器相关的表执行响应的DML操作时立即执行;
  • 触发器可以实现表中的数据的级联操作(关联操作),有利于保证数据的完整性;
  • 触发器可以对DML操作的数据进行更为复杂的合法性校验

缺点

  • 使用触发器实现的业务逻辑如果出现问题将难以定位,后期维护困难;
  • ⼤量使用触发器容易导致代码结构杂乱,增加了程序的复杂性;
  • 当触发器操作的数据量比较⼤时,执行效率会大大降低。

使用建议

  • 在互联网项目中,应避免适应触发器;
  • 对于并发量不大的项目可以选择使用存储过程,但是在互联网引用中不提倡使用存储过程
    原因:存储过程时将实现业务的逻辑交给数据库处理,
    • ⼀则增减了数据库的负载,
    • ⼆则不利于数据库的迁移

六、视图

6.1、视图的概念

视图,就是由数据库中⼀张表或者多张表根据特定的条件查询出得数据构造成得 虚拟表

6.2、视图的作用

  • 安全性
    如果我们直接将数据表授权给用户操作,那么用户可以CRUD数据表中所有数据,加入我们想要对数据表中的部分数据进行保护,可以将公开的数据⽣成视图,授权用户访问视图;用户通过查询视图可以获取数据表中公开的数据,从而达到将数据表中的部分数据对用户隐藏。
  • 简单性
    如果我们需要查询的数据来源于多张数据表,可以使用多表连接查询来实现;我们通过视图将这些连表查询的结果对用户开放,用户则可以直接通过查询视图获取多表数据,操作更便捷。

6.3、创建视图

## 创建视图
CREATE VIEW <view_name> AS <tableName>

6.4、视图数据的特性

视图是虚拟表,查询视图的数据是来源于数据表的。当对视图进行操作时,对原数据表中的数据是否由影响呢?

  • 查询操作
    如果在数据表中添加了新的数据,而且这个数据满⾜创建视图时查询语句的条件,通过查询视图也可以查询出新增的数据;当删除原表中满足查询条件的数据时,也会从视图中删除。
  • 新增数据
    如果在视图中添加数据,数据会被添加到原数据表
  • 删除数据
    如果从视图删除数据,数据也将从原表中删除
  • 修改操作
    如果通过修改数据,则也将修改原数据表中的数据视图的使用建议 : 对复杂查询简化操作,并且不会对数据进行修改的情况下可以使用视图。

6.5、查询视图结构

-- 查询视图结构
desc <view_name>

6.6、修改视图

-- ⽅式1
create OR REPLACE view <view_name>
AS
select * from students where stu_gender='⼥';

-- ⽅式2
alter view  <view_name>
AS 
select * from students where stu_gender='男';

6.7、删除视图

删除数据表时会同时删除数据表中的数据,删除视图时不会影响原数据表中的数据

-- 删除视图
drop view <view_name>;

七、索引

数据库是用来存储数据,在互联网应用中数据库中存储的数据可能会很多(大数据), 数据表中数据的查询速度会随着数据量的增长逐渐变慢 ,从而导致响应用户请求的速度变慢——用户体验差,我们如何提⾼数据库的查询效率呢?

7.1、索引的介绍

索引,就是用来提⾼数据表中数据的查询效率的。

索引,就是将数据表中某⼀列\某几列的值取出来构造成便于查找的结构进行存储,生成数据表的目录

当我们进行数据查询的时候,则先在目录中进行查找得到对应的数据的地址,然后再到数据表中根据地址快速的获取数据记录,避免全表扫描。

MySQL数据库_第2张图片

7.2、索引的分类

MySQL中的索引,根据创建索引的列的不同,可以分为:

  • 主键索引
    在数据表的主键字段创建的索引,这个字段必须被primary key修饰,每张表只能有⼀个主键
  • 唯⼀索引
    在数据表中的唯⼀列创建的索引(unique),此列的所有值只能出现⼀次,可以为NULL
  • 普通索引
    在普通字段上创建的索引,没有唯⼀性的限制
  • 组合索引
    两个及以上字段联合起来创建的索引

在创建数据表时,将字段声明为主键(添加主键约束),会⾃动在主键字段创建主键索引;
在创建数据表时,将字段声明为唯⼀键(添加唯⼀约束),会⾃动在唯⼀字段创建唯⼀索引;

7.3、创建索引

## 创建唯⼀索引: 创建唯⼀索引的列的值不能重复
-- create unique index  on 表名(列名);
create unique index idx_name on user(name);

## 创建普通索引: 不要求创建索引的列的值的唯⼀性
-- create index  on 表名(列名);
create index idx_age on user(age);

## 创建组合索引
-- create index  on 表名(列名1, 列名2...);
create index idx_gender_tel on user(gender, tel);

## 全⽂索引
-- MySQL 5.6 版本新增的索引,可以通过此索引进⾏全⽂检索操作,因为MySQL全⽂检索不⽀持中⽂,
-- 因此这个全⽂索引不被开发者关注,在应⽤开发中通常是通过搜索引擎(数据库中间件)实现全⽂检索
-- create fulltext index  on 表名(字段名); 
create fulltext index idx_address on user(address); 

7.4、索引使用

索引创建完成之后⽆需调用,当根据创建索引的列进行数据查询的时候,会⾃动使用索引;

组合索引需要根据创建索引的所有字段进行查询时触发。

## 查看查询语句的查询规划
-- explain 查询sql语句
explain select * from user where id='10001';

7.5、查看索引

-- show create table ;
show create table user;

-- 查询数据表的索引
show indexes from user;

-- 查询索引
show keys from user;

7.6、删除索引

-- 删除索引:索引是建⽴在表的字段上的,不同的表中可能会出现相同名称的索引
-- 因此删除索引时需要指定表名
-- drop index  on ;
drop index idx_name on user;

7.7、索引的使用总结

优点

  • 索引⼤⼤降低了数据库服务器在执行查询操作时扫描的数据,提高查询效率
  • 索引可以避免服务器排序、将随机IO编程顺序IO

缺点

  • 索引是根据数据表列的创建的,当数据表中数据发⽣DML操作时,索引页需要更新;
  • 索引⽂件也会占用磁盘空间;

注意事项
1.数据表中数据不多时,全表扫⾯可能更快吗,不要使⽤索引;
2.数据量⼤但是DML操作很频繁时,不建议使用索引;
3.不要在数据重复读高的列上创建索引(性别);
4.创建索引之后,要注意查询SQL语句的编写,避免索引失效。

你可能感兴趣的:(Java,数据库,mysql,sql)