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;只要其中一方为字符型,试图将字符型数值转换成数值型
            如果转换成功,则继续做加法运算
select 'john'+90;   如果转换失败,则将字符型数值转换成0

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

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');

单行函数

#一、字符函数

  1. length:获取参数值的字节个数
  2. concat:拼接字符串
  3. upper、lower:转大写、小写
  4. substr、substring:截取字符串
    注意:索引从1开始
    截取从指定索引处后面所有字符
  5. instr 返回子串第一次出现的索引,如果找不到返回0
  6. trim
  7. lpad 用指定的字符实现左填充指定长度
  8. rpad 用指定的字符实现右填充指定长度
  9. 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 四位的年份
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 pk truncate【面试题★】

  1. delete 可以加where 条件,truncate不能加
  2. truncate删除,效率高一丢丢
  3. 假如要删除的表中有自增长列,
    如果用delete删除后,再插入数据,自增长列的值从断点开始,
    而truncate删除后,再插入数据,自增长列的值从1开始。
  4. truncate删除没有返回值,delete删除有返回值
  5. 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 列名 【列类型 约束】;

①修改列名

ALTER TABLE book CHANGE COLUMN publishdate pubDate DATETIME;

②修改列的类型或约束

ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;

③添加新列

ALTER TABLE author ADD COLUMN annual DOUBLE;

④删除列

ALTER TABLE book_author DROP COLUMN  annual;

⑤修改表名

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(较长的二进制数据)

日期型:

#一、整型

分类:
tinyint、smallint、mediumint、int/integer、bigint
1 2 3 4 8

特点:
① 如果不设置无符号还是有符号,默认是有符号,如果想设置无符号,需要添加unsigned关键字
② 如果插入的数值超出了整型的范围,会报out of range异常,并且插入临界值
③ 如果不设置长度,会有默认的长度
长度代表了显示的最大宽度,如果不够会用0在左边填充,但必须搭配zerofill使用!

#二、小数

分类:

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

特点:


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


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

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

原则:

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

#三、字符型

较短的文本:

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中不支持】
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;

2.添加默认约束

ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;

3.添加主键
①列级约束

ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;

②表级约束

ALTER TABLE stuinfo ADD PRIMARY KEY(id);

4.添加唯一

①列级约束

ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE;

②表级约束

ALTER TABLE stuinfo ADD UNIQUE(seat);

5.添加外键

ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id);

#三、修改表时删除约束

1.删除非空约束

ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL;

2.删除默认约束

ALTER TABLE stuinfo MODIFY COLUMN age INT ;

3.删除主键

ALTER TABLE stuinfo DROP PRIMARY KEY;

4.删除唯一

ALTER TABLE stuinfo DROP INDEX seat;

5.删除外键

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;

MySQL8中是:

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 值;
  3. 函数体中仅有一句话,则可以省略begin end
  4. 使用 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)$

猜你喜欢

转载自www.cnblogs.com/huangwenjie/p/11401846.html