目录
一、变量
1、系统变量
系统变量由系统提供,属于服务器层面变量,用户不可以声明
可分为全局变量和会话变量
(1)全局变量
全局变量会在mysql启动时赋初始值,无法夸重启使用,如有需要,应该设置配置文件
用法:
#查看所有的全局变量
SHOW GLOBAL VARIABLES;
#查看满足条件的部分全局变量
SHOW GLOBAL VARIABLES LIKE ‘_%’;
#查看某个全局变量
SELECT @@GLOBAL.系统变量名;
#为某个全局变量赋值
SET @@GLOBAL.系统变量名 = 值;
(2)会话变量
会话变量会在新的连接的赋初始值,作用域为当前连接,无法夸连接使用
用法与全局变量一样,将GLOBAL关键字换为SESSION关键字即可
#查看所有的会话变量
SHOW SESSION VARIABLES;
#查看满足条件的部分会话变量
SHOW SESSION VARIABLES LIKE ‘_%’;
#查看某个会话变量
SELECT @@SESSION.系统变量名;
#为某个会话变量赋值
SET @@SESSION.系统变量名 = 值;
2、自定义变量
自定义变量即用户根据某些需求,自己声明并使用的变量
根据作用域不同,可分为用户变量和局部变量
(1)用户变量
用户变量的作用域与会话变量一样,为当前连接有效
使用步骤如下:
#1、声明并初始化:
SET @用户变量名=值;
SET @用户变量名:=值;
SELECT @用户变量名:=值;
#2、赋值:
#方式一:同声明并初始化的语法一样
#方式二:
SELECT 字段 INTO 用户变量名 FROM 表;
#3、使用用户变量的值:
@用户变量名
(2)局部变量
局部变量的作用域为在一个函数或存储过程中有效
使用步骤如下:
#1、声明:
DECLARE 局部变量名 类型 [DEFAULT 值]; #类型为sql数据类型中的一个
#2、赋值:
#方法一:
SET 局部变量名=值;
SET 局部变量名:=值;
SELECT @局部变量名:=值;
#方法二:
SELECT 字段 INTO 局部变量名 FROM 表 ….;
SELECT 字段1,字段2... INTO 局部变量1,局部变量2... FROM 表 ….;#同时给多个局部变量赋值
二、存储过程
存储过程是一组预先编译好的sql语句的集合,可理解为批处理语句
1、优点
- 提高了代码的复用性
- 简化了操作
- 减少编译次数,减少了数据库服务器的连接次数,提高了效率
2、存储过程的创建
在存储过程中的sql语句要用分号结尾,为了区分存储过程的结尾,可以自定义一个结尾符号:
DELIMITER $ #定义结尾符号为$
创建一个存储过程的一般写法:
CREATE PROCEDURE 存储过程名(参数模式 参数名 参数类型,参数模式 参数名 参数类型......)
BEGIN
存储过程体...
END$
参数的参数模式有以下几种:
- IN:该参数可以作为输入,需要调用方传入值
- OUT:该参数可以作为输出,可作为返回值
- INOUT:既可以作为输入也可以作为输出,即需要调用方传入值,又可以返回值
3、存储过程的调用
CALL 存储过程名(参数模式 参数名 参数类型,参数模式 参数名 参数类型......)
4、存储过程的查看
SHOW CREATE PRECEDURE 存储过程名
5、存储过程的删除
DROP PROCEDURE 存储过程名
6、案例
#创建一个user表
CREATE TABLE IF NOT EXISTS user(
no VARCHAR(20) PRIMARY KEY,
password VARCHAR(20) NOT NULL
)
- 创建无参存储过程
DELIMITER $ #声明结束标记,一个连接只声明一次即可
#创建
CREATE PROCEDURE pro1()
BEGIN
INSERT INTO user VALUES('1001','123'),('1002','321'),('1003','111');
END $
#调用
CALL pro1()$
- 创建带IN模式参数的存储过程
DELIMITER $ #声明结束标记,一个连接只声明一次即可
#传入用户名和密码,显示出是否匹配
#创建
CREATE PROCEDURE pro2(IN no VARCHAR(20),IN password VARCHAR(20))
BEGIN
DECLARE result TINYINT DEFAULT 0;
SELECT COUNT(1) INTO result
FROM user
WHERE user.no=no AND user.password=password;
SELECT IF(result>0,'true','false');
END $
#调用
CALL pro2(‘1001’,‘123’)$
- 创建带OUT模式参数的存储过程
DELIMITER $ #声明结束标记,一个连接只声明一次即可
#根据用户名,返回密码
#创建
CREATE PROCEDURE pro3(IN no VARCHAR(20),OUT password VARCHAR(20))
BEGIN
SELECT user.password INTO password
FROM user
WHERE user.no = no;
END $
#调用
CALL pro3('1001',@pw)$
SELECT @pw$
- 创建带INOUT模式参数的存储过程
DELIMITER $ #声明结束标记,一个连接只声明一次即可
#创建
CREATE PROCEDURE pro4(INOUT a INT,INOUT b INT)
BEGIN
SET a=a*2;
SET b=b*2;
END$
#调用
SET @m=1$
SET @n=2$
CALL pro4(@m,@n)$
SELECT @m,@n$
三、函数
1、存储过程和函数的比较
存储过程和函数都类似于JAVA的方法
存储过程:可以有0个或多个返回值,适合做批量插入、批量更新
函数:有且只有一个返回值,适合做处理数据后返回一个结果在(类似与自定义的分组函数)
2、函数的创建
CREATE FUNCTION 函数名(参数名 参数类型,参数名 参数类型...) RETURNS 返回类型
BEGIN
函数体
RETURN 返回值;(函数体中必须有RETURN语句,建议放在函数体最后)
END
3、函数的调用
SELECT 函数名(参数名 参数类型,参数名 参数类型...) #类似分组函数的使用
4、函数的查看
SHOW CREATE FUNCTION 函数名
5、函数的删除
DROP FUNCTION 函数名
6、案例
- 无参函数
DELIMITER $ #声明结束标记,一个连接只声明一次即可
#创建函数 返回user表中人数
CREATE FUNCTION fun1() RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0;
SELECT COUNT(1) INTO c
FROM user;
RETURN c;
END$
#调用函数
SELECT fun1()$
- 有参函数
DELIMITER $ #声明结束标记,一个连接只声明一次即可
#创建函数 根据no和password,返回是否匹配
CREATE FUNCTION fun2(no VARCHAR(20),pw VARCHAR(20)) RETURNS VARCHAR(5)
BEGIN
DECLARE result TINYINT DEFAULT 0;
SELECT COUNT(1) INTO result
FROM user
WHERE user.no=no AND user.password=pw;
RETURN IF(result>0,'true','false');
END$
#调用函数
SELECT fun2('1001','123')$
四、流程控制结构
1、顺序结构
2、分支结构
(1)IF结构
IF可以当做一个表达式来用,也可以当做一个语句来用
a.IF作表达式
IF做表达式来用即简单的二分支
可以用在一般的sql语句中,也可以用在存储过程和函数中
SELECT IF(表达式1,表达式2,表达式3);#若满足表达式1,则值为表达式2,否则为表达式3
b.IF作语句
IF做语句来用即多重分支
只可以用在存储过程和函数中,比较常用
IF 条件1 THEN 语句1;
ELSEIF 条件2 THEN 语句2;
…...
ELSE 语句n;
END IF;
(2)CASE结构
同IF结构一样,CASE也可一当做表达式或独立的语句使用
a.CASE作表达式
CASE作为表达式来用,可以用于一般的sql语句中,也可以用于存储过程和函数中
#方式一
CASE 变量|表达式|字段
WHEN 值1 THEN 返回值1
WHEN 值2 THEN 返回值2
…….
ELSE 返回值n
END CASE
#方式二
CASE
WHEN 条件1 THEN 返回值1
WHEN 条件2 THEN 返回值2
…….
ELSE 返回值n
END CASE
b.CASE作语句
CASE做独立语句来用,只能用在存储过程和函数中
#方式一
CASE 变量|表达式|字段
WHEN 值1 THEN 语句1;
WHEN 值2 THEN 语句2;
…….
ELSE 语句1;
END CASE
#方式二
CASE
WHEN 条件1 THEN 语句1;
WHEN 条件2 THEN 语句2;
…….
ELSE 语句n;
END CASE
3、循环结构
循环结构有以下三种:
- WHILE:先判断在执行,常用
- LOOP:没有跳出循环的条件,只能搭配循环控制使用,可以用来模拟简单的死循环
- REPEAT:先执行再判断,至少执行一次
循环控制有以下两种:
- ITERATE 结束本次循环,继续下一次
- LEAVE 结束当前所在的循环
(1)WHILE
[标签:] WHILE 循环条件 DO
循环体
END WHILE [标签];
(2)LOOP
[标签:] LOOP
循环体
END LOOP [标签];
(3)REPEAT
[标签:] REPEAT
循环体
UNTIL 结束循环的条件
END LOOP [标签];
五、案例
Type 表有type_id(主键)、type_name
book表有book_id(主键)、book_name、book_price、type_id(外键)、book_count
写一个sql脚本,随机插入千万级数据
#建库
CREATE DATABASE books;
USE books;
#建表
CREATE TABLE type(
type_id INT PRIMARY KEY AUTO_INCREMENT,
type_name VARCHAR(20) NOT NULL
);
CREATE TABLE book(
book_id INT PRIMARY KEY AUTO_INCREMENT,
book_name VARCHAR(20) NOT NULL,
book_price FLOAT NOT NULL DEFAULT 0,
type_id INT NOT NULL,
book_count INT NOT NULL DEFAULT 0,
CONSTRAINT fk_typeid FOREIGN KEY(type_id) REFERENCES type(type_id)
);
DELIMITER $
SET @base='abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ';
#随机字符串函数,输入需要生成的串的长度n
CREATE FUNCTION rand_str(n INT) RETURNS VARCHAR(20)
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE tmp VARCHAR(20) DEFAULT '';
WHILE i<n DO
SET tmp = CONCAT(tmp,SUBSTR(@base,FLOOR(RAND()*52)+1,1));
SET i = i+1;
END WHILE;
RETURN tmp;
END$
#生成一个[s,e)的浮点数
CREATE FUNCTION rand_float(s INT,e INT) RETURNS FLOAT(6,2)
BEGIN
DECLARE f FLOAT(6,2) DEFAULT 0;
SET f = ROUND(RAND()*(e-s)+s,2);
RETURN f;
END$
#生成一个[s,e)的整数
CREATE FUNCTION rand_int(s INT,e INT) RETURNS INT#[s,e)
BEGIN
DECLARE i INT DEFAULT 0;
SET i=FLOOR(RAND()*(e-s)+s);
RETURN i;
END$
#插入type表数据,n为记录数
CREATE PROCEDURE insert_type(n INT)
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i<n DO
INSERT into type(type_name) VALUES(rand_str(5));
SET i=i+1;
END WHILE;
END$
#插入book表数据,n为记录数,type_num为type表的记录数(因为有外键)
CREATE PROCEDURE insert_book(n INT,type_num INT)
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i<n DO
INSERT INTO book(book_name,book_price,type_id,book_count) VALUES(rand_str(4),rand_float(0,100),rand_int(1,type_num+1),rand_int(0,10));
SET i = i+1;
END WHILE;
END$
CALL insert_type(10)$
CALL insert_book(20,10)$
来源:CSDN
作者:Sirm23333
链接:https://blog.csdn.net/qq_37969433/article/details/102746919