20190823 尚硅谷MySQL核心技术

背景

  • 视频时间:2017.09
  • MySQL版本:5.5

MySQL基础

命令行启动、停止MySQL:

net start MySQL(这里是注册的服务名称)
net stop MySQL

命令行连接MySQL:

mysql -h localhost -P 3306 -u root -p xxx
-h 主机,可省略
-P 端口号,可省略
-u 用户名
-p 密码,与密码之间不能有空格,其他可有可无

常用命令

  1. 查看当前所有的数据库
show databases;
  1. 打开指定的库
use 库名
  1. 查看当前库的所有表
show tables;
  1. 查看其它库的所有表
show tables from 库名;
  1. 查看当前所在数据库
select DATABASE();
  1. 查看表结构
desc 表名;
  1. 查看服务器的版本
    方式一:登录到mysql服务端
select version();

方式二:没有登录到mysql服务端

mysql --version

mysql --V

MySQL的语法规范

  1. 不区分大小写,但建议关键字大写,表名、列名小写
  2. 每条命令最好用分号结尾
  3. 每条命令根据需要,可以进行缩进 或换行
  4. 注释
    • 单行注释:# 注释文字
    • 单行注释:-- 注释文字
    • 多行注释:/* 注释文字 */

SQL的语言分类

  • DQL(Data Query Language):数据查询语言
    select
  • DML(Data Manipulate Language):数据操作语言
    insert 、update、delete
  • DDL(Data Define Languge):数据定义语言
    create、drop、alter
  • TCL(Transaction Control Language):事务控制语言
    commit、rollback

查询常量值

SELECT 100;
SELECT 'john';

查询表达式

SELECT 100%98;

查询函数

SELECT VERSION();

别名特殊时,加上双引号:

SELECT salary AS "out put" FROM employees;

mysql中的 + 号:

仅仅只有一个功能:运算符

-- 两个操作数都为数值型,则做加法运算
select 100+90; 

-- 只要其中一方为字符型,试图将字符型数值转换成数值型
-- 如果转换成功,则继续做加法运算
select '123'+90;

-- 如果转换失败,则将字符型数值转换成0
select 'john'+90;	

-- 只要其中一方为null,则结果肯定为null
select null+10; 

-- 会试图转换字符串的开始部分为数字
SELECT '123abc'+'3a2a'; 

字符串连接函数:

SELECT CONCAT('a','b','c') AS 结果;

null与其他字符串左连接时结果为null;

IFNULL函数判断是否为空:

SELECT 
	IFNULL(commission_pct,0) AS 奖金率,
	commission_pct
FROM 
	employees;

条件查询:

一、按条件表达式筛选

简单条件运算符:> < = != <> >= <=

二、按逻辑表达式筛选

逻辑运算符:
作用:用于连接条件表达式
	&& || !
	and or not
	
&&和and:两个条件都为true,结果为true,反之为false  
||或or: 只要有一个条件为true,结果为true,反之为false  
!或not: 如果连接的条件本身为false,结果为true,反之为false  

三、模糊查询

	like
	between and
	in
	is null

like:
①一般和通配符搭配使用
通配符:
% 任意多个字符,包含0个字符
_ 任意单个字符

可以直接使用转义符,也可以指定转义符:

last_name LIKE '_\_%';  
last_name LIKE '_$_%' ESCAPE '$';

安全等于 <=>
既可以判断NULL值,又可以判断普通的数值

ISNULL

判断是否为空
1 为是 0为否

order by 支持别名排序

DATEDIFF相隔天数:

SELECT DATEDIFF('1995-2-7','1995-2-6');

单行函数

#一、字符函数

  • length:获取参数值的字节个数

  • concat:拼接字符串

  • upperlower:转大写、小写

  • substrsubstring:截取字符串

    注意:索引从 1 开始

    截取从指定索引处后面所有字符

  • instr 返回子串第一次出现的索引,如果找不到返回0

  • trim

  • lpad 用指定的字符实现左填充指定长度

  • rpad 用指定的字符实现右填充指定长度

  • replace 替换

#二、数学函数

  • round 四舍五入
  • ceil 向上取整,返回 >= 该参数的最小整数
  • floor 向下取整,返回 <= 该参数的最大整数
  • truncate 截断
  • mod取余

#三、日期函数

now 返回当前系统日期+时间

SELECT NOW();

curdate 返回当前系统日期,不包含时间

SELECT CURDATE();

curtime 返回当前时间,不包含日期

SELECT CURTIME();

可以获取指定的部分,年、月、日、小时、分钟、秒

SELECT YEAR(NOW()) 年;
SELECT YEAR('1998-1-1') 年;

SELECT  YEAR(hiredate) 年 FROM employees;

SELECT MONTH(NOW()) 月;
SELECT MONTHNAME(NOW()) 月;

str_to_date 将字符通过指定的格式转换成日期

SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;

date_format 将日期转换成字符

SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS out_put;
序号 格式符 功能
1 %Y 4 位的年份
2 %y 2 位的年份
3 %m 月份( 01,02…11,12)
4 %c 月份( 1,2,…11,12)
5 %d 日( 01,02,…)
6 %H 小时( 24 小时制)
7 %h 小时( 12 小时制)
8 %i 分钟( 00,01…59)
9 %s 秒( 00,01,…59)

#四、其他函数

SELECT VERSION();
SELECT DATABASE();
SELECT USER();

#五、流程控制函数

#1.if函数: if else 的效果

SELECT IF(10<5,'大','小');

#2.case 函数的使用一: switch case 的效果

#3.case 函数的使用二:类似于 多重if

分组函数

sum 求和、avg 平均值、max 最大值 、min 最小值 、count 计算个数

特点:

  1. sum、avg一般用于处理数值型
    max、min、count可以处理任何类型
  2. 以上分组函数都忽略null值
  3. 可以和distinct搭配实现去重的运算
  4. count函数的单独介绍
    一般使用count(*)用作统计行数
SELECT COUNT(salary) FROM employees;
SELECT COUNT(*) FROM employees;
SELECT COUNT(1) FROM employees;

效率:

MYISAM 存储引擎下 ,COUNT(*)的效率高

INNODB 存储引擎下,COUNT(*)COUNT(1)的效率差不多,比COUNT(字段)要高一些

  1. 和分组函数一同查询的字段要求是group by后的字段

筛选分类

筛选分为两类:分组前筛选和分组后筛选

分类 针对的表 位置 连接的关键字
分组前筛选 原始表 group by前 where
分组后筛选 group by后的结果集 group by后 having

一般来讲,能用分组前筛选的,尽量使用分组前筛选,提高效率

MySQL中group by 子句和having子句后都支持别名,与Oracle不同。

where子句后都不支持别名。

连接查询:

如果为表起了别名,则查询的字段就不能使用原来的表名去限定。

sql99语法的连接查询

内连接:

inner join == join

MySQL不支持全外连接 full join

交叉连接就是笛卡尔乘积。cross join

子查询

分类:
按子查询出现的位置:

select后面:
	仅仅支持标量子查询
from后面:
	支持表子查询
where或having后面:★
	标量子查询(单行) √
	列子查询  (多行) √
	行子查询
exists后面(相关子查询)
	表子查询

按结果集的行列数不同:

标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一行多列)
表子查询(结果集一般为多行多列)

标量子查询,一般搭配着单行操作符使用

> < >= <= = <>

列子查询,一般搭配着多行操作符使用

in、any/some、all

语法:

exists(完整的查询语句)

结果:1或0

exists子句先执行主查询,在执行子查询。

分页查询

语法: 执行顺序:
select 查询列表	 |						7
from 表				 |					1
【join type join 表2	 |						2
on 连接条件					 |			3
where 筛选条件				 |			4
group by 分组字段			 |				5
having 分组后的筛选			 |			6
order by 排序的字段】		 |				8
limit 【offset,】size;		 |				9


offset 要显示条目的起始索引(起始索引从0开始),不写默认为0  
size 要显示的条目个数

特点:

limit语句放在查询语句的最后
公式:要显示的页数 page,每页的条目数 size
select 查询列表
	from 表
	limit (page-1)*size,size;
	
	size=10
	page  
	1	0
	2  	10
	3	20

DDL 数据操纵语言

MySQL的另一种插入语法:

insert into 表名
set 列名=值,列名=值,...
INSERT INTO beauty
SET id=19,NAME='刘涛',phone='999';

多行插入:

INSERT INTO beauty
VALUES(23,'唐艺昕1','女','1990-4-23','1898888888',NULL,2)
,(24,'唐艺昕2','女','1990-4-23','1898888888',NULL,2)
,(25,'唐艺昕3','女','1990-4-23','1898888888',NULL,2);
INSERT INTO beauty(id,NAME,phone)
SELECT id,boyname,'1234567'
FROM boys WHERE id<3;

1. 修改单表的记录★

语法:

update 表名
set 列=新值,列=新值,...
where 筛选条件;

2. 修改多表的记录【补充】

语法:
sql92语法:

update 表1 别名,表2 别名
set 列=值,...
where 连接条件
and 筛选条件;

sql99语法:

update 表1 别名
inner|left|right join 表2 别名
on 连接条件
set 列=值,...
where 筛选条件;

删除表记录

方式一:delete
语法:

1、单表的删除【★】

delete from 表名 where 筛选条件

2、多表的删除【补充】

sql92语法:

delete 表1的别名,表2的别名
from 表1 别名,表2 别名
where 连接条件
and 筛选条件;

sql99语法:

delete 表1的别名,表2的别名
from 表1 别名
inner|left|right join 表2 别名 on 连接条件
where 筛选条件;

方式二:truncate
语法:

truncate table 表名;

#delete VS truncate【面试题★】

  1. delete 可以加where 条件,truncate不能加

  2. truncate删除,效率高一丢丢

  3. 假如要删除的表中有自增长列,

如果用delete删除后,再插入数据,自增长列的值从断点开始,

而truncate删除后,再插入数据,自增长列的值从1开始。

  1. truncate删除没有返回值,delete删除有返回值

  2. truncate删除不能回滚,delete删除可以回滚.

DDL语言 数据定义语言

一、库的管理
创建、修改、删除
二、表的管理
创建、修改、删除

创建: create
修改: alter
删除: drop

#一、库的管理

#1、库的创建

语法:

create database  [if not exists] 库名;

案例:创建库Books

CREATE DATABASE IF NOT EXISTS books ;

#2、库的修改

RENAME DATABASE books TO 新库名;

更改库的字符集

ALTER DATABASE books CHARACTER SET gbk;

#3、库的删除

DROP DATABASE IF EXISTS books;

#二、表的管理

#1.表的创建 ★

语法:

create table 表名(
	列名 列的类型【(长度) 约束】,
	列名 列的类型【(长度) 约束】,
	列名 列的类型【(长度) 约束】,
	...
	列名 列的类型【(长度) 约束】
)

案例:创建表Book

CREATE TABLE book(
	id INT,#编号
	bName VARCHAR(20),#图书名
	price DOUBLE,#价格
	authorId  INT,#作者编号
	publishDate DATETIME#出版日期
);
DESC book;

案例:创建表author

CREATE TABLE IF NOT EXISTS author(
	id INT,
	au_name VARCHAR(20),
	nation VARCHAR(10)

)
DESC author;

#2.表的修改

语法

alter table 表名 add|drop|modify|change column 列名 【列类型 约束】;
  1. 修改列名
ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;
  1. 修改列的类型或约束
ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;
  1. 添加新列
ALTER TABLE author ADD COLUMN annual DOUBLE;
  1. 删除列
ALTER TABLE book_author DROP COLUMN  annual;
  1. 修改表名
ALTER TABLE author RENAME TO book_author;

DESC book;

#3.表的删除

DROP TABLE IF EXISTS book_author;

通用的写法:

DROP DATABASE IF EXISTS 旧库名;
CREATE DATABASE 新库名;


DROP TABLE IF EXISTS 旧表名;
CREATE TABLE  表名();

#4.表的复制

1.仅仅复制表的结构

CREATE TABLE copy LIKE author;

2.复制表的结构+数据

CREATE TABLE copy2 
SELECT * FROM author;

数据类型

常见的数据类型

数值型:

	整型:
	小数:
		定点数
		浮点数
字符型:

	较短的文本:char、varchar
	较长的文本:text、blob(较长的二进制数据)

日期型:

#一、整型

分类:

类型
占用字节 1 2 3 4 8
类型 占用字节
tinyint 1
smallint 2
mediumint 3
int/integer 4
bigint 8

特点:

  1. 如果不设置无符号还是有符号,默认是有符号,如果想设置无符号,需要添加 unsigned 关键字

  2. 如果插入的数值超出了整型的范围,会报out of range异常,并且插入临界值

  3. 如果不设置长度,会有默认的长度

    长度代表了显示的最大宽度,如果不够会用 0 在左边填充,但必须搭配 zerofill 使用!

#二、小数

分类:

  1. 浮点型
  • float(M,D)
  • double(M,D)
  1. 定点型
  • dec(M,D)
  • decimal(M,D)

特点:

  1. M:整数部位+小数部位
    D:小数部位
    如果超过范围,则插入临界值

  2. M和D都可以省略
    如果是decimal,则M默认为10,D默认为0
    如果是float和double,则会根据插入的数值的精度来决定精度

  3. 定点型的精确度较高,如果要求插入数值的精度较高如货币运算等则考虑使用

原则:

所选择的类型越简单越好,能保存数值的类型越小越好

#三、字符型

较短的文本:

  • char
  • varchar

其他:

  • binary 和 varbinary 用于保存较短的二进制
  • enum 用于保存枚举
  • set 用于保存集合

较长的文本:

  • text
  • blob(较大的二进制)

特点:

写法 M的意思 特点 空间的耗费 效率
char char(M) 最大的字符数,可以省略,默认为1 固定长度的字符 比较耗费
varchar varchar(M) 最大的字符数,不可以省略 可变长度的字符 比较节省

枚举类型:

CREATE TABLE tab_char(
	c1 ENUM('a','b','c')
);
INSERT INTO tab_char VALUES('a');
INSERT INTO tab_char VALUES('b');
INSERT INTO tab_char VALUES('c');

set类型:

CREATE TABLE tab_set(
	s1 SET('a','b','c','d')
);
INSERT INTO tab_set VALUES('a');
INSERT INTO tab_set VALUES('A,B');
INSERT INTO tab_set VALUES('a,c,d');

#四、日期型

分类:

  • date 只保存日期

  • time 只保存时间

  • year 只保存年

  • datetime 保存日期+时间

  • timestamp 保存日期+时间

特点:

类型 字节 范围 时区等的影响
datetime 8 1000-9999 不受
timestamp 4 1970-2038

常见约束

含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性

分类:六大约束

  • NOT NULL

    非空,用于保证该字段的值不能为空

  • DEFAULT

    默认值,用于保证该字段有默认值

  • PRIMARY KEY

    主键,用于保证该字段的值具有唯一性,并且非空

  • UNIQUE

    唯一,用于保证该字段的值具有唯一性,可以为空

  • CHECK

    检查约束【mysql中不支持】

    MySQL 只是可以使用 check 约束,但不会强制的遵循check约束!

  • FOREIGN KEY

    外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值

    在从表添加外键约束,用于引用主表中某列的值

添加约束的时机:

  1. 创建表时
  2. 修改表时

约束的添加分类:

  • 列级约束:

    六大约束语法上都支持,但外键约束没有效果

  • 表级约束:

    除了非空、默认,其他的都支持

#1.添加列级约束

语法:

直接在字段名和类型后面追加 约束类型即可。

只支持:默认、非空、主键、唯一

CREATE TABLE stuinfo(
	id INT PRIMARY KEY,#主键
	stuName VARCHAR(20) NOT NULL UNIQUE,#非空
	gender CHAR(1) CHECK(gender='男' OR gender ='女'),#检查
	seat INT UNIQUE,#唯一
	age INT DEFAULT  18,#默认约束
	majorId INT REFERENCES major(id)#外键
);

#2.添加表级约束

语法:在各个字段的最下面
【constraint 约束名】 约束类型(字段名)

DROP TABLE IF EXISTS stuinfo;
CREATE TABLE stuinfo(
	id INT,
	stuname VARCHAR(20),
	gender CHAR(1),
	seat INT,
	age INT,
	majorid INT,
	
	CONSTRAINT pk PRIMARY KEY(id),#主键
	CONSTRAINT uq UNIQUE(seat),#唯一键
	CONSTRAINT ck CHECK(gender ='男' OR gender  = '女'),#检查
	CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)#外键
	
);

通用的写法:★

CREATE TABLE IF NOT EXISTS stuinfo(
	id INT PRIMARY KEY,
	stuname VARCHAR(20),
	sex CHAR(1),
	age INT DEFAULT 18,
	seat INT UNIQUE,
	majorid INT,
	CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)
);

主键和唯一的大对比:

类型 保证唯一性 是否允许为空 一个表中可以有多少个 是否允许组合
主键 × 至多有1个 √,但不推荐
唯一 可以有多个 √,但不推荐

外键:

1、要求在从表设置外键关系
2、从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
3、主表的关联列必须是一个key(一般是主键或唯一)
4、插入数据时,先插入主表,再插入从表
	删除数据时,先删除从表,再删除主表

#二、修改表时添加约束

1、添加列级约束

alter table 表名 modify column 字段名 字段类型 新约束;

2、添加表级约束

alter table 表名 add 【constraint 约束名】 约束类型(字段名) 【外键的引用】;
DROP TABLE IF EXISTS stuinfo;
CREATE TABLE stuinfo(
	id INT,
	stuname VARCHAR(20),
	gender CHAR(1),
	seat INT,
	age INT,
	majorid INT
)
DESC stuinfo;
  1. 添加非空约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20)  NOT NULL;
  1. 添加默认约束
ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;
  1. 添加主键

    ① 列级约束

ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;

​ ② 表级约束

ALTER TABLE stuinfo ADD PRIMARY KEY(id);
  1. 添加唯一

    ① 列级约束

ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE;

​ ② 表级约束

ALTER TABLE stuinfo ADD UNIQUE(seat);
  1. 添加外键
ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id);

#三、修改表时删除约束

  1. 删除非空约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL;
  1. 删除默认约束
ALTER TABLE stuinfo MODIFY COLUMN age INT ;
  1. 删除主键
ALTER TABLE stuinfo DROP PRIMARY KEY;
  1. 删除唯一
ALTER TABLE stuinfo DROP INDEX seat;
  1. 删除外键
ALTER TABLE stuinfo DROP FOREIGN KEY fk_stuinfo_major;

标识列

又称为自增长列

含义:可以不用手动的插入值,系统提供默认的序列值

特点:

  1. 标识列必须和主键搭配吗?不一定,但要求是一个key
  2. 一个表可以有几个标识列?至多一个!
  3. 标识列的类型只能是数值型
  4. 标识列可以通过 SET auto_increment_increment=3; 设置步长,可以通过 手动插入值,设置起始值

#一、创建表时设置标识列

DROP TABLE IF EXISTS tab_identity;
CREATE TABLE tab_identity(
	id INT  ,
	NAME FLOAT UNIQUE AUTO_INCREMENT,
	seat INT 
);
TRUNCATE TABLE tab_identity;


INSERT INTO tab_identity(id,NAME) VALUES(NULL,'john');
INSERT INTO tab_identity(NAME) VALUES('lucy');
SELECT * FROM tab_identity;


SHOW VARIABLES LIKE '%auto_increment%';


SET auto_increment_increment=3;

TCL 事务控制语言

事务的特性:

ACID

  • 原子性:一个事务不可再分割,要么都执行要么都不执行
  • 一致性:一个事务执行会使数据从一个一致状态切换到另外一个一致状态
  • 隔离性:一个事务的执行不受其他事务的干扰
  • 持久性:一个事务一旦提交,则会永久的改变数据库的数据.

事务的创建

隐式事务:事务没有明显的开启和结束的标记
比如insert、update、delete语句

delete from 表 where id =1;

显式事务:事务具有明显的开启和结束的标记
前提:必须先设置自动提交功能为禁用

set autocommit=0;

步骤1:开启事务

set autocommit=0;
start transaction; 	# 可选的

步骤2:编写事务中的sql语句(select insert update delete)

语句1;
语句2;
...

步骤3:结束事务

commit;		# 提交事务
rollback;	# 回滚事务

savepoint 节点名;		# 设置保存点

并发问题

  • 脏读

    对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段之后, 若 T2 回滚, T1读取的内容就是临时且无效的

  • 不可重复读

    对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段之后, T1再次读取同一个字段, 值就不同了.

  • 幻读

    对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.

事务的隔离级别:

类型 脏读 不可重复读 幻读
read uncommitted
read committed ×
repeatable read × ×
serializable × × ×

mysql中默认第三个隔离级别 repeatable read

oracle中默认第二个隔离级别 read committed

查看隔离级别:

select @@tx_isolation;

MySQL 8中是:

SELECT @@TRANSACTION_ISOLATION;

设置隔离级别

set session|global transaction isolation level 隔离级别;

视图

mysql5.1版本出现的新特性

#一、创建视图

语法:

create view 视图名
as
查询语句;

#二、视图的修改

方式一:

create or replace view  视图名
as
查询语句;

方式二:

语法:

alter view 视图名
as 
查询语句;

#三、删除视图

语法:

drop view 视图名,视图名,...;
DROP VIEW emp_v1,emp_v2,myv3;

#四、查看视图

DESC myv3;

SHOW CREATE VIEW myv3;

#五、视图的更新

具备以下特点的视图不允许更新

#① 包含以下关键字的sql语句:分组函数、distinct、group  by、having、union或者union all
#② 常量视图
#③ select中包含子查询
#④ join
#⑤ from一个不能更新的视图
#⑥ where子句的子查询引用了from子句中的表

变量

系统变量:

全局变量  
会话变量

自定义变量:

用户变量  
局部变量

#一、系统变量

说明:变量由系统定义,不是用户定义,属于服务器层面
注意:全局变量需要添加global关键字,会话变量需要添加session关键字,如果不写,默认会话级别

使用步骤:

  1. 查看所有系统变量
show global|【session】variables;
  1. 查看满足条件的部分系统变量
show global|【session】 variables like '%char%';
  1. 查看指定的系统变量的值
select @@global|【session】系统变量名;
  1. 为某个系统变量赋值
    方式一:
set global|【session】系统变量名=值;

方式二:

set @@global|【session】系统变量名=值;

#1》全局变量

作用域:针对于所有会话(连接)有效,但不能跨重启

①查看所有全局变量

SHOW GLOBAL VARIABLES;

②查看满足条件的部分系统变量

SHOW GLOBAL VARIABLES LIKE '%char%';

③查看指定的系统变量的值

SELECT @@global.autocommit;

④为某个系统变量赋值

SET @@global.autocommit=0;
SET GLOBAL autocommit=0;

#2》会话变量

作用域:针对于当前会话(连接)有效

①查看所有会话变量

SHOW SESSION VARIABLES;

②查看满足条件的部分会话变量

SHOW SESSION VARIABLES LIKE '%char%';

③查看指定的会话变量的值

SELECT @@autocommit;
SELECT @@session.tx_isolation;

④为某个会话变量赋值

SET @@session.tx_isolation='read-uncommitted';
SET SESSION tx_isolation='read-committed';

#二、自定义变量

说明:变量由用户自定义,而不是系统提供的

使用步骤:

  1. 声明
  2. 赋值
  3. 使用(查看、比较、运算等)

#1》用户变量

作用域:针对于当前会话(连接)有效,作用域同于会话变量

赋值操作符:=或:=

①声明并初始化

SET @变量名=值;
SET @变量名:=值;
SELECT @变量名:=值;

②赋值(更新变量的值)

方式一:

SET @变量名=值;
SET @变量名:=值;
SELECT @变量名:=值;

方式二:

SELECT 字段 INTO @变量名
FROM 表;

③使用(查看变量的值)

SELECT @变量名;

#2》局部变量

作用域:仅仅在定义它的begin end块中有效

应用在 begin end中的第一句话

①声明

DECLARE 变量名 类型;
DECLARE 变量名 类型 【DEFAULT 值】;

②赋值(更新变量的值)

方式一:

SET 局部变量名=值;
SET 局部变量名:=值;
SELECT 局部变量名:=值;

方式二:

SELECT 字段 INTO 具备变量名
	FROM 表;

③使用(查看变量的值)

SELECT 局部变量名;

案例:声明两个变量,求和并打印

用户变量

SET @m=1;
SET @n=1;
SET @sum=@m+@n;
SELECT @sum;
类型 作用域 定义位置 语法
用户变量 当前会话 会话的任何地方 加@符号,不用指定类型
局部变量 定义它的BEGIN END中 BEGIN END的第一句话 一般不用加@,需要指定类型

存储过程

含义:一组预先编译好的SQL语句的集合,理解成批处理语句

1、提高代码的重用性
2、简化操作
3、减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率

#一、创建语法

CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
	存储过程体(一组合法的SQL语句)
END

注意:
1、参数列表包含三部分

参数模式 参数名 参数类型

举例:

in stuname varchar(20)

参数模式:

in:该参数可以作为输入,也就是该参数需要调用方传入值
out:该参数可以作为输出,也就是该参数可以作为返回值
inout:该参数既可以作为输入又可以作为输出,也就是该参数既需要传入值,又可以返回值

2、如果存储过程体仅仅只有一句话,begin end可以省略

存储过程体中的每条sql语句的结尾要求必须加分号。

存储过程的结尾可以使用 delimiter 重新设置

语法:

delimiter 结束标记

案例:

delimiter $

#二、调用语法

CALL 存储过程名(实参列表);

#1.空参列表

案例:插入到admin表中五条记录

DELIMITER $
CREATE PROCEDURE myp1()
BEGIN
	INSERT INTO admin(username,`password`) 
	VALUES('john1','0000'),('lily','0000'),('rose','0000'),('jack','0000'),('tom','0000');
END $

调用

CALL myp1()$

#2.创建带 in 模式参数的存储过程

案例2 :创建存储过程实现,用户是否登录成功

CREATE PROCEDURE myp4(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
	DECLARE result INT DEFAULT 0;#声明并初始化
	
	SELECT COUNT(*) INTO result#赋值
	FROM admin
	WHERE admin.username = username
	AND admin.password = PASSWORD;
	
	SELECT IF(result>0,'成功','失败');#使用
END $

调用

CALL myp4('张飞','8888')$

#3.创建 out 模式参数的存储过程

案例2:根据输入的女神名,返回对应的男神名和魅力值

CREATE PROCEDURE myp7(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT) 
BEGIN
	SELECT boys.boyname ,boys.usercp INTO boyname,usercp
	FROM boys 
	RIGHT JOIN
	beauty b ON b.boyfriend_id = boys.id
	WHERE b.name=beautyName ;
	
END $

调用

CALL myp7('小昭',@name,@cp)$
SELECT @name,@cp$

#4.创建带 inout 模式参数的存储过程

案例1:传入a和b两个值,最终a和b都翻倍并返回

CREATE PROCEDURE myp8(INOUT a INT ,INOUT b INT)
BEGIN
	SET a=a*2;
	SET b=b*2;
END $

调用

SET @m=10$
SET @n=20$
CALL myp8(@m,@n)$
SELECT @m,@n$

#三、删除存储过程

语法:drop procedure 存储过程名

DROP PROCEDURE p1;
DROP PROCEDURE p2,p3;#×

#四、查看存储过程的信息

SHOW CREATE PROCEDURE myp2;

函数

含义:一组预先编译好的SQL语句的集合,理解成批处理语句

1、提高代码的重用性
2、简化操作
3、减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率

区别:

  • 存储过程:可以有0个返回,也可以有多个返回,适合做批量插入、批量更新
  • 函数:有且仅有1 个返回,适合做处理数据后返回一个结果

#一、创建语法

CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型
BEGIN
	函数体
END

注意:

  1. 参数列表 包含两部分:
    参数名 参数类型

  2. 函数体:肯定会有return语句,如果没有会报错

如果return语句没有放在函数体的最后也不报错,但不建议

return 值;

  1. 函数体中仅有一句话,则可以省略 begin end

  2. 使用 delimiter 语句设置结束标记

#二、调用语法

SELECT 函数名(参数列表)

案例2:根据部门名,返回该部门的平均工资

CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE
BEGIN
	DECLARE sal DOUBLE ;
	SELECT AVG(salary) INTO sal
	FROM employees e
	JOIN departments d ON e.department_id = d.department_id
	WHERE d.department_name=deptName;
	RETURN sal;
END $

SELECT myf3('IT')$

#三、查看函数

SHOW CREATE FUNCTION myf3;

#四、删除函数

DROP FUNCTION myf3;

流程控制结构

顺序、分支、循环

#一、分支结构

#1.if函数

语法:if(条件,值1,值2)
功能:实现双分支
应用在begin end中或外面

#2.case结构

语法:

情况1:类似于switch

case 变量或表达式
when 值1 then 语句1;
when 值2 then 语句2;
...
else 语句n;
end

情况2:

case 
when 条件1 then 语句1;
when 条件2 then 语句2;
...
else 语句n;
end case

应用在 begin end 中或外面

#3.if结构

语法:

if 条件1 then 语句1;
elseif 条件2 then 语句2;
....
else 语句n;
end if;

功能:类似于多重if

只能应用在begin end 中

#二、循环结构

分类:
while、loop、repeat

循环控制:

iterate类似于 continue,继续,结束本次循环,继续下一次
leave 类似于  break,跳出,结束当前所在的循环

#1.while

语法:

【标签:】while 循环条件 do
	循环体;
end while【 标签】;

联想:

while(循环条件){
	循环体;
}

#2.loop

语法:

【标签:】loop
	循环体;
end loop 【标签】;

可以用来模拟简单的死循环

#3.repeat

语法:

【标签:】repeat
	循环体;
until 结束循环的条件
end repeat 【标签】;

#2.添加 leave 语句

案例:批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止

TRUNCATE TABLE admin$
DROP PROCEDURE test_while1$
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	a:WHILE i<=insertCount DO
		INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
		IF i>=20 THEN LEAVE a;
		END IF;
		SET i=i+1;
	END WHILE a;
END $


CALL test_while1(100)$
原文地址:https://www.cnblogs.com/huangwenjie/p/11401846.html