目录

  • 学习内容
  • 1 DML命令
  • 1.1 insert插入
  • 2.2 update修改语句
  • 2.3 delete删除语句
  • 2.3.1 delete & truncaet 区别(面试题)
  • 2 DDL命令
  • 2.1 create&alter&drop
  • 2.2 表的创建
  • 2.3表的修改
  • 2.4 表的删除
  • 2.5 表的复制
  • 3 数据类型介绍
  • 3.1 整型
  • 3.1.1 设置无符号和有符号
  • 3.2 小数
  • 3.3 字符型
  • 3.3.1 其他类型Bit,binary,varbinary,Enum,Set类型
  • 3.4 日期型
  • 4 DDL语言的学习
  • 4.1 常见约束
  • 4.2 创建表时添加约束
  • 4.2.1 添加列级约束(可多个约束)
  • 4.2.2 添加表级约束
  • 4.2.3 主键和唯一的对比(面试)
  • 4.2.4 外键的特点
  • 4.3 修改表时添加约束
  • 4.3.1 添加约束
  • 4.3.2 删除约束
  • 4.3.3 列级约束、表级约束的区别
  • 4.4 标识列(自增长列)AUTO_INCREMENT
  • 5 TCL事务控制语言
  • 5.1 事务的创建
  • 5.1.1 演示事务对于delete和truncate的处理的区别
  • 5.2 事务并发问题的介绍
  • 5.2.1 隔离级别
  • 5.2.2 savepoint(回滚点) 的使用
  • 6. 视图
  • 6.1 创建视图
  • 6.2 修改视图
  • 6.3 视图的查看和删除
  • 6.4 视图的更新
  • 6.5 视图和表的对比
  • 7 变量
  • 7.1 系统变量
  • 7.2 自定义变量
  • 7.2.1 用户变量
  • 7.2.2 局部变量
  • 7.2.3 用户变量和局部变量的对比
  • 8. 存储过程的介绍
  • 8.1 创建存储过程
  • 8.2 调用方法
  • 8.2.1 空参列表
  • 8.2.2 带in模式的存储过程
  • 8.2.3 带out模式的存储过程
  • 8.2.4 带inout模式的存储过程
  • 8.2.5 存储过程的删除
  • 8.2.6 查看存储过程的信息
  • 9. 函数的介绍
  • 9.1 创建函数
  • 9.1.1 无参又返回
  • 9.1.1 有参又有返回值
  • 9.2 查看函数
  • 9.3 删除函数
  • 10 流程控制介绍
  • 10.1 分支结构-
  • 10.1.1 if函数
  • 10.1.2 case结构
  • 10.1.3 if结构
  • 10.2 循环结构
  • 10.2.1 while
  • 10.2.2 loop
  • 10.2.3 repeat
  • 10.2.4 几种循环对比
  • 循环结构案例


学习内容

数据操作语言:
插入:insert
修改:update
删除:delete

1 DML命令

1.1 insert插入

方式一(使用较多)

SELECT * FROM beauty;
#1.插入的值的类型要与列的类型一致或兼容
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);
#2.不可以为null的列必须插入值。可以为null的列如何插入值?
#方式一:
INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐艺昕','女','1990-4-23','1898888888',NULL,2);

#方式二:
INSERT INTO beauty(id,NAME,sex,phone)
VALUES(15,'娜扎','女','1388888888'); 可多行
#3.列的顺序是否可以调换
INSERT INTO beauty(NAME,sex,id,phone)
VALUES('蒋欣','女',16,'110'); 可多行
#4.列数和值的个数必须一致`在这里插入代码片`
INSERT INTO beauty(NAME,sex,id,phone)
VALUES('关晓彤','女',17,'110'); 可多行
#5.可以省略列名,默认所有列,而且列的顺序和表中列的顺序一致
INSERT INTO beauty
VALUES(18,'张飞','男',NULL,'119',NULL,NULL); 可多行

方式二

语法:
insert into 表名
set 列名=值,列名=值,...

INSERT INTO beauty
SET id=19,NAME='刘涛',phone='999';
体会该种方式不同
方式二:
INSERT INTO my_employees
SELECT 1,'patel','Ralph','Rpatel',895 UNION
SELECT 2,'Dancs','Betty','Bdancs',860 UNION
SELECT 3,'Biri','Ben','Bbiri',1100 UNION
SELECT 4,'Newman','Chad','Cnewman',750 UNION
SELECT 5,'Ropeburn','Audrey','Aropebur',1550;

两种方式的区别

1、方式一支持插入多行,方式二不支持
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);

2、方式一支持子查询,方式二不支持
INSERT INTO beauty(id,NAME,phone)
SELECT 26,'宋茜','11809866';

INSERT INTO beauty(id,NAME,phone)
SELECT id,boyname,'1234567'
FROM boys WHERE id<3;

2.2 update修改语句

1.修改单表的记录★
语法:
update 表名
set 列=新值,列=新值,...(字符和日期加引号)
where 筛选条件;

2.修改多表的记录【补充】
语法:
sql92语法:
update 表1 别名,表2 别名
set 列=值,...
where 连接条件
AND 筛选条件;

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

修改单表

案例1:修改beauty表中姓唐的女神的电话为13899888899
UPDATE beauty SET phone = '13899888899'
WHERE NAME LIKE '唐%';

案例2:修改boys表中id好为2的名称为张飞,魅力值 10
UPDATE boys SET boyname='张飞',usercp=10
WHERE id=2;

修改多表

案例2:修改没有男朋友的女神的男朋友编号都为2号
UPDATE boys bo
RIGHT JOIN beauty b ON bo.`id`=b.`boyfriend_id`
SET b.`boyfriend_id`=2
WHERE bo.`id` IS NULL;

2.3 delete删除语句

方式一: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 表名; 清空数据
2.3.1 delete & truncaet 区别(面试题)
#delete pk truncate【面试题★】
1.delete 可以加where 条件,truncate不能加
2.truncate删除,效率高一丢丢
3.假如要删除的表中有自增长列,
如果用delete删除后,再插入数据,自增长列的值从断点开始,
而truncate删除后,再插入数据,自增长列的值从1开始。
4.truncate删除没有返回值,delete删除有返回值
5.truncate删除不能回滚,delete删除可以回滚.

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_主键

2 DDL命令

数据定义语言
库和表的管理
一、库的管理
创建、修改、删除
二、表的管理
创建: create 创建结构
修改: alter 修改结构
删除: drop 删除结构
IF EXISTS 只可用于 表或库 的删除和创建,不可用于判断是否存在某列(字段名)

2.1 create&alter&drop

语法:(如果只是create database XXX,如果没存在还好,已经存在的话会报错)
create database  [if not exists]库名;
案例:创建库Books
CREATE DATABASE IF NOT EXISTS books ;
RENAME DATABASE books TO 新库名;  	5.1.7废弃了,修改库名可能会导致数据丢失
更改库的字符集
ALTER DATABASE books CHARACTER SET gbk;
DROP DATABASE IF EXISTS books;

2.2 表的创建

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

案例:创建表Book
CREATE TABLE book(
	id INT,#编号
	bName VARCHAR(20),#图书名
	price DOUBLE,#价格
	authorId  INT,#作者编号
	publishDate DATETIME#出版日期
);

2.3表的修改

语法
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;

2.4 表的删除

DROP TABLE IF EXISTS book_author;

DROP DATABASE IF EXISTS 旧库名;
CREATE DATABASE 新库名;
DROP TABLE IF EXISTS 旧表名;
CREATE TABLE  表名();

2.5 表的复制

INSERT INTO author VALUES
(1,'村上春树','日本'),
(2,'莫言','中国'),
(3,'冯唐','中国'),
(4,'金庸','中国');

SELECT * FROM Author;
SELECT * FROM copy2;
1.仅仅复制表的结构
CREATE TABLE copy LIKE author;

2.复制表的结构+数据
CREATE TABLE copy2 
SELECT * FROM author;

只复制部分数据
CREATE TABLE copy3
SELECT id,au_name
FROM author 
WHERE nation='中国'; 

仅仅复制某些字段
CREATE TABLE copy4 
SELECT id,au_name
FROM author
WHERE 0;

跨库复制表数据
2.	将表departments中的数据插入新表dept2中
CREATE TABLE dept2 (当前是在test库)
SELECT department_id,department_name
FROM myemployees.departments;

3 数据类型介绍

file:///G:/%E5%B0%9A%E7%A1%85%E8%B0%B7Java%E5%AD%A6%E7%A7%91%E5%85%A8%E5%A5%97%E6%95%99%E7%A8%8B%EF%BC%88%E6%80%BB207.77GB%EF%BC%89/1.%E5%B0%9A%E7%A1%85%E8%B0%B7%E5%85%A8%E5%A5%97JAVA%E6%95%99%E7%A8%8B--%E5%9F%BA%E7%A1%80%E9%98%B6%E6%AE%B5%EF%BC%8873.36GB%EF%BC%89/MySQL%E6%A0%B8%E5%BF%83%E6%8A%80%E6%9C%AF/%E8%AF%BE%E4%BB%B6/7.%20%E5%B0%9A%E7%A1%85%E8%B0%B7_MySQL_%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%20.pdf
数值型:
	整型
	小数:
		定点数
		浮点数
字符型:
	较短的文本:char、varchar
	较长的文本:text、blob(较长的二进制数据)
日期型:

3.1 整型

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_表名_02

分类:
tinyint、smallint、mediumint、int/integer、bigint
1	 		2		   3			4		8
特点:
① 如果不设置无符号还是有符号,默认是有符号,如果想设置无符号,需要添加unsigned关键字
② 如果插入的数值超出了整型的范围,会报out of range异常,并且插入临界值,(取距离真值最近的临界值)
③ 如果不设置长度,会有默认的长度
长度代表了显示的最大宽度,如果不够会用0在左边填充,但必须搭配zerofill使用!
3.1.1 设置无符号和有符号
CREATE TABLE tab_int(
	t1 INT,
	t2 INT unsigned 
);

INSERT INTO tab_int VALUES(-123456);
INSERT INTO tab_int VALUES(-123456,-123456); t1=-123456,t2=0
INSERT INTO tab_int VALUES(2147483648,4294967296); t1=2147483647,t2=2147483647
CREATE TABLE tab_int(
	t1 INT(7) ZEROFILL, 长度站位为7,不够用0填充;并且默认为无符号,字节数是由类型决定的
	t2 INT(7) ZEROFILL 
); 结果如下

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_外键_03

3.2 小数

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_外键_04

0. 类型选取原则: 所选择的类型越简单越好,能保存数值的类型越小越好
分类:
1.浮点型
	float(M,D)	double(M,D)
2.定点型
	dec(M,D)	decimal(M,D)
特点:
①
M:整数部位+小数部位 一共的个数
D:小数部位(超过的话会四舍五入,位数不够会自动回补零)
如果超过范围,则插入临界值(eg:float(5,2) 999.99)
②
M和D都可以省略
如果是decimal,则M默认为10,D默认为0
如果是float和double,则会根据插入的数值的精度来决定精度
③定点型的精确度较高,如果要求插入数值的精度较高如货币运算等则考虑使用

3.3 字符型

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_数据库_05

特点:eg:性别(使用char)
		  写法				M的意思						特点			空间的耗费	效率
char	char(M)		最大的字符数,可以省略,默认为1	固定长度的字符		比较耗费		高
					eg:插入'中国'即使只有2个字符,也会开辟M个字符的空间
varchar varchar(M)	最大的字符数,不可以省略			可变长度的字符		比较节省		低
3.3.1 其他类型Bit,binary,varbinary,Enum,Set类型

也有别的,但不常用,了解

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_外键_06

binary和varbinary类型
说明:类似于char和varchar,不同的是它们包含二进制字符串而不包含非二进制字符串。

Enum类型
说明:又称为枚举类型哦,要求插入的值必须属于列表中指定的值之一。
如果列表成员为1~255,则需要1个字节存储
如果列表成员为255~65535,则需要2个字节存储
最多需要65535个成员!

CREATE TABLE tab_char(
	c1 ENUM('a','b','c') 插入A也会存入小写的a,
);

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');  结果如下

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_mysql_07

3.4 日期型

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_数据库_08

分类:
date只保存日期
time 只保存时间
year只保存年
datetime保存日期+时间
timestamp保存日期+时间

特点:
		   字节		范围		时区等的影响
datetime	8		1000——9999	    不受
timestamp	4	    1970-2038	     受
datetime和timestamp的区别
1、Timestamp支持的时间范围较小,取值范围: 19700101080001——2038年的某个时间
	 Datetime的取值范围:1000-1-1 ——9999—12-31
2、timestamp和实际时区有关,更能反映实际的日 期,而datetime则只能反映出插入时的当地时区
3、timestamp的属性受Mysql版本和SQLMode的影响 很大
CREATE TABLE tab_date(
	t1 DATETIME,
	t2 TIMESTAMP
);

INSERT INTO tab_date VALUES(NOW(),NOW());
SELECT * FROM tab_date;
SHOW VARIABLES LIKE 'time_zone';
SET time_zone='+9:00';

4 DDL语言的学习

4.1 常见约束

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

分类:六大约束
	NOT NULL:非空,用于保证该字段的值不能为空
	比如姓名、学号等
	DEFAULT:默认,用于保证该字段有默认值
	比如性别
	PRIMARY KEY:主键,用于保证该字段的值具有唯一性,并且非空
	比如学号、员工编号等
	UNIQUE:唯一,用于保证该字段的值具有唯一性,可以为空
	比如座位号
	CHECK:检查约束【mysql中不支持,加不加上没效果,但是SQLserver Oracal支持】 兼容性
	比如年龄、性别
	FOREIGN KEY:外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值
		在从表添加外键约束,用于引用主表中某列的值
	比如学生表的专业编号,员工表的部门编号,员工表的工种编号

添加约束的时机(添加数据之前):
	1.创建表时
	2.修改表时
	
约束的添加分类:
	列级约束:
		六大约束语法上都支持,但外键约束没有效果
	表级约束:
		除了非空、默认,其他的都支持(如下)
		CREATE TABLE 表名(
		字段名 字段类型 列级约束,
		字段名 字段类型,
		表级约束
		)

4.2 创建表时添加约束

4.2.1 添加列级约束(可多个约束)

无顺序要求

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

CREATE TABLE major(
	id INT PRIMARY KEY,
	majorName VARCHAR(20)
);

查看stuinfo中的所有索引,包括主键、外键、唯一
SHOW INDEX FROM stuinfo; DESC stuinfo; 两者可结合使用
SHOW CREATE VIEW XXX;
4.2.2 添加表级约束
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)#外键
);
SHOW INDEX FROM stuinfo; 结果如下

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_mysql_09

通用的写法:★
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)
);
4.2.3 主键和唯一的对比(面试)
主键和唯一的大对比:
	保证唯一性  是否允许为空    一个表中可以有多少个   是否允许组合
主键	√			×			至多有1个          	 √,但不推荐
唯一	√			√			可以有多个         	 √,但不推荐

CONSTRAINT pk PRIMARY KEY(id, seat) 只有当这两个都一样时插入才会出错
4.2.4 外键的特点
外键:
	1、要求在从表设置外键关系
	2、从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
	3、主表的关联列必须是一个key(一般指的是主键或唯一)
	4、插入数据时,先插入主表,再插入从表
		删除数据时,先删除从表,再删除主表

4.3 修改表时添加约束

4.3.1 添加约束
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); 括号类似函数的形式,且注意ADD&MODIFY COLUMN

4.添加唯一
①列级约束
ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE; 加入原来有约束NOT NULL,修改后会同时满足两个约束
②表级约束
ALTER TABLE stuinfo ADD UNIQUE(seat);
5.添加外键
ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id);
4.3.2 删除约束
三、修改表时删除约束
1.删除非空约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL; 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;
SHOW INDEX FROM stuinfo;
4.3.3 列级约束、表级约束的区别
1.向表emp2的id列中添加PRIMARY KEY约束(my_emp_id_pk)
ALTER TABLE emp2 MODIFY COLUMN id INT PRIMARY KEY;
ALTER TABLE emp2 ADD CONSTRAINT my_emp_id_pk PRIMARY KEY(id);

2.	向表dept2的id列中添加PRIMARY KEY约束(my_dept_id_pk)
3.	向表emp2中添加列dept_id,并在其中定义FOREIGN KEY约束,与之相关联的列是dept2表中的id列。
ALTER TABLE emp2 ADD COLUMN dept_id INT;
ALTER TABLE emp2 ADD CONSTRAINT fk_emp2_dept2 FOREIGN KEY(dept_id) REFERENCES dept2(id);

			位置				支持的约束类型			是否可以起约束名
列级约束:	列的后面			语法都支持,但外键没有效果		不可以
表级约束:	所有列的下面		默认和非空不支持,其他支持	可以(主键没有效果)
note: 在orcal中check约束是都不支持的,但不会报错

4.4 标识列(自增长列)AUTO_INCREMENT

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

特点:
1、标识列必须和主键搭配吗?不一定,但要求是一个key
2、一个表可以有几个标识列?至多一个!
3、标识列的类型只能是数值型
4、标识列可以通过 SET auto_increment_increment=3;设置步长:可以通过 手动插入值,设置起始值
DROP TABLE IF EXISTS tab_identity;
CREATE TABLE tab_identity(
	id INT  ,
	NAME varchar(20) 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;
SHOW VARIABLES LIKE '%auto_increment%';
SET auto_increment_increment=3;

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_外键_10

但是自己测试的时候两个都可以设,并且有作用

5 TCL事务控制语言

Transaction Control Language 事务控制语言
事务:(事务:事务由单独单元的一个或多个SQL语句组成,在这个单元中,每个MySQL语句是相互依赖的。而整个单独单 元作为一个不可分割的整体,如果单元中某条SQL语句一 旦执行失败或产生错误,整个单元将会回滚。所有受到影响的数据将返回到事物开始以前的状态;如果单元中的所有SQL语句均执行成功,则事物被顺利执行。)
一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。
案例:转账
张三丰  1000
郭襄	1000
update 表 set 张三丰的余额=500 where name='张三丰'
意外
update 表 set 郭襄的余额=1500 where name='郭襄'

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

show engines

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_表名_11


mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_表名_12

5.1 事务的创建

事务的创建
隐式事务:事务没有明显的开启和结束的标记
比如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;回滚事务
SHOW VARIABLES LIKE 'autocommit';
SHOW ENGINES;

1.演示事务的使用步骤
开启事务
SET autocommit=0;
START TRANSACTION;
编写一组事务的语句
UPDATE account SET balance = 1000 WHERE username='张无忌';
UPDATE account SET balance = 1000 WHERE username='赵敏';
结束事务
ROLLBACK;
#commit;
5.1.1 演示事务对于delete和truncate的处理的区别
SET autocommit=0;
START TRANSACTION;
DELETE FROM account;
ROLLBACK;  运行到此处,表中数据存在,delete支持回滚

SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE accunt;
ROLLBACK; 运行到此处,表中数据不存在,TRUNCATE不支持回滚

SELECT * FROM account;

5.2 事务并发问题的介绍

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_外键_13

5.2.1 隔离级别

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_主键_14

select @@tx_isolation 查看当前的隔离级别
select @@global.tx_isolation;查看当前的全局隔离级别

 set session transaction isolation level read committed;;设置事务隔离级别(设置当前会话)
 (当退出mysql后,重新进入,当前的隔离级别又会恢复成  REPEATABLE-READ,一般重启一下才有效)

 set global transaction isolation level read committed; 设置数据库系统的全局的隔离级别:
  (当退出mysql后,重新进入,当前的隔离级别并不又会恢复成  REPEATABLE READ,是持久的)
事务的隔离级别:
		  		脏读		不可重复读	幻读
read uncommitted:√				√		√
read committed:  ×				√		√
repeatable read: ×				×		√
serializable	  ×             ×       ×

mysql中默认 第三个隔离级别 repeatable read
oracle中默认第二个隔离级别 read committed
查看隔离级别
select @@tx_isolation;
设置隔离级别
set session|global transaction isolation level 隔离级别;
5.2.2 savepoint(回滚点) 的使用

只搭配rollback to 使用,不能搭配commit

SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a;  设置保存点
DELETE FROM account WHERE id=28;
ROLLBACK TO a;  回滚到保存点 
此时 id=25的数据已删,而 id=28 的数据仍在

SELECT * FROM account;

6. 视图

含义:虚拟表,和普通表一样使用
mysql5.1版本出现的新特性,是通过表动态生成的数据
比如:舞蹈班和普通班级的对比
CREATE VIEW v1
AS
SELECT stuname,majorname
FROM stuinfo s
INNER JOIN major m ON s.`majorid`= m.`id`;

SELECT * FROM v1 WHERE stuname LIKE '张%';

6.1 创建视图

语法:
create view 视图名
as
查询语句;

1.查询姓名中包含a字符的员工名、部门名和工种信息
①创建
CREATE VIEW myv1
AS
SELECT last_name,department_name,job_title
FROM employees e
JOIN departments d ON e.department_id  = d.department_id
JOIN jobs j ON j.job_id  = e.job_id;

②使用
SELECT * FROM myv1 WHERE last_name LIKE '%a%';

视图的使用可以嵌套
CREATE VIEW myv3
AS
SELECT * FROM myv2 ORDER BY ag LIMIT 1;

6.2 修改视图

方式一

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

CREATE OR REPLACE VIEW myv3  如果不存在就创建,存在就替换
AS
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

方式二

语法:
alter view 视图名
as 
查询语句;

ALTER VIEW myv3
AS
SELECT * FROM employees;

6.3 视图的查看和删除

删除语法:drop view 视图名,视图名,...;
DROP VIEW emp_v1,emp_v2,myv3;

查看视图
DESC myv3;
SHOW CREATE VIEW myv3;

6.4 视图的更新

因为会影响原来的表,不安全,所以视图往往会添加权限

CREATE OR REPLACE VIEW myv1
AS
SELECT last_name,email
FROM employees;

SELECT * FROM myv1;
SELECT * FROM employees;
1.插入 原数据的emplyee表也会增添一列,没有指明值的以NULL填充
INSERT INTO myv1 VALUES('张飞','zf@qq.com');
2.修改
UPDATE myv1 SET last_name = '张无忌' WHERE last_name='张飞';
3.删除
DELETE FROM myv1 WHERE last_name = '张无忌';

具备以下特点的视图是不允许更新的(了解,视图不要更新)

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

6.5 视图和表的对比

创建语法的关键字		是否实际占用物理空间			使用

视图	create view			只是保存了sql逻辑		增删改查,只是一般不能增删改

表		create table			保存了数据				增删改查

7 变量

系统变量:
	全局变量:作用于整个服务器的,跨连接有效且持久的,但是不能跨重启(eg:右上角新建一个连接)
			作用域:针对于所有会话(连接)有效,但不能跨重启(如果想夸重启需要修改配置文件,略)
	会话变量:针对于一个会话的,或者客户端的一次连接,针对本次会话的一些变量赋予默认值
			作用域:针对于当前会话(连接)有效,

自定义变量:
	用户变量: 作用域:针对于当前会话(连接)有效,作用域同于会话变量
	局部变量		作用域:仅仅在定义它的begin end块中有效, 应用在 begin end中的第一句话

7.1 系统变量

说明:变量由系统定义,不是用户定义,属于服务器层面,登录服务器的时候这些变量会有一些默认值
注意:全局变量需要添加global关键字,会话变量需要添加session关键字,如果不写,默认会话级别
使用步骤:
1、查看所有系统变量
show global variables; 			不写session的话,默认是session变量 
show [session] variables;
2、查看满足条件的部分系统变量
show global variables like '%char%';
show [session] variables like '%char%';
3、查看指定的系统变量的值
select @@global.系统变量名;
select @@[session.]系统变量名;
4、为某个系统变量赋值
方式一:
set global|【session】系统变量名=值;
方式二:
set @@global.系统变量名=值;
set @@[session.]系统变量名=值;

7.2 自定义变量

7.2.1 用户变量
说明:变量由用户自定义,而不是系统提供的
使用步骤:
1、声明并初始化
2、赋值
3、使用(查看、比较、运算等)
赋值操作符:=或:=
①声明并初始化
SET @变量名=值;
SET @变量名:=值;
SELECT @变量名:=值;

②赋值(更新变量的值)
方式一:
	SET @变量名=值;
	SET @变量名:=值;
	SELECT @变量名:=值;
方式二:
	SELECT 字段 INTO @变量名
	FROM 表;
③使用(查看变量的值)
SELECT @变量名;
7.2.2 局部变量

BEGIN END的第一句话

①声明
DECLARE 变量名 类型;
DECLARE 变量名 类型 【DEFAULT 值】;

②赋值(更新变量的值)
方式一:
	SET 局部变量名=值;
	SET 局部变量名:=值;
	SELECT @局部变量名:=值;  		注意
方式二:
	SELECT 字段 INTO 局部变量名  	标量,单行单列的一个查询结果
	FROM 表;
③使用(查看变量的值)
SELECT 局部变量名;
案例:声明两个变量,求和并打印
用户变量
SET @m=1;
SET @n=1;
SET @sum=@m+@n;
SELECT @sum;

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

8. 存储过程的介绍

存储过程和函数:类似于java中的方法
好处:1、提高代码的重用性		2、简化操作

存储过程
含义:一组预先编译好的SQL语句的集合,理解成批处理语句
1、提高代码的重用性
2、简化操作
3、减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率

8.1 创建存储过程

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

1、参数列表包含三部分
参数模式  参数名  参数类型
举例:in stuname varchar(20)

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

2、如果存储过程体仅仅只有一句话,begin end可以省略
存储过程体中的每条sql语句的结尾要求必须加分号。
存储过程的结尾可以使用 delimiter 重新设置
语法:delimiter 结束标记
案例:delimiter $

8.2 调用方法

8.2.1 空参列表
方法:
案例:插入到admin表中五条记录
SELECT * FROM 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()$
8.2.2 带in模式的存储过程
案例1:创建存储过程实现 根据女神名,查询对应的男神信息
CREATE PROCEDURE myp2(IN beautyName VARCHAR(20))
BEGIN
	SELECT bo.*
	FROM boys bo
	RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
	WHERE b.name=beautyName;
END $
调用
CALL myp2('柳岩')$

案例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 myp3('张飞','8888')$  set names gbk;设置字符集
Incorrect string value: '\xA3\x9E' for column 'username' at row 198
8.2.3 带out模式的存储过程
案例1:根据输入的女神名,返回对应的男神名
CREATE PROCEDURE myp5(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))
BEGIN
	SELECT bo.boyname INTO boyname
	FROM boys bo
	INNER JOIN
	beauty b ON b.boyfriend_id = bo.id
	WHERE b.name=beautyName ;
END $

调用
set @bName$ # 此句可省略,直接在下面使用
CALL myp5('小昭',@bName)$  用户变量
SELECT @bName$


案例2:根据输入的女神名,返回对应的男神名和魅力值
CREATE PROCEDURE myp7(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT)  # in可省略,但不建议
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$
8.2.4 带inout模式的存储过程
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$


四、创建存储过程或函数实现传入一个日期,格式化成xx年xx月xx日并返回
CREATE PROCEDURE test_pro4(IN mydate DATETIME,OUT strDate VARCHAR(50))
BEGIN
	SELECT DATE_FORMAT(mydate,'%y年%m月%d日') INTO strDate;
END $
调用
CALL test_pro4(NOW(),@str)$
SELECT @str $


五、创建存储过程或函数实现传入女神名称,返回:女神 and 男神  格式的字符串
如 传入 :小昭
返回: 小昭 AND 张无忌
DROP PROCEDURE test_pro5 $
CREATE PROCEDURE test_pro5(IN beautyName VARCHAR(20),OUT str VARCHAR(50))
BEGIN
	SELECT CONCAT(beautyName,' and ',IFNULL(boyName,'null')) INTO str
	FROM boys bo
	RIGHT JOIN beauty b ON b.boyfriend_id = bo.id
	WHERE b.name=beautyName;
END $
CALL test_pro5('柳岩',@str)$
SELECT @str $
8.2.5 存储过程的删除
语法:drop procedure 存储过程名
DROP PROCEDURE p1;
DROP PROCEDURE p2,p3;  会报错×,一次只能删一个
8.2.6 查看存储过程的信息
DESC myp2;× 报错  适用于表或视图
SHOW CREATE PROCEDURE  myp2;

9. 函数的介绍

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

9.1 创建函数

CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型
BEGIN
	函数体
END
注意:
1.参数列表 包含两部分:
参数名 参数类型

2.函数体:肯定会有return语句,如果没有会报错
如果return语句没有放在函数体的最后也不报错,但不建议

return 值;
3.函数体中仅有一句话,则可以省略begin end
4.使用 delimiter语句设置结束标记

二、调用语法
SELECT 函数名(参数列表)  类似单行函数和分组函数
9.1.1 无参又返回
案例:返回公司的员工个数
CREATE FUNCTION myf1() RETURNS INT
BEGIN
	DECLARE c INT DEFAULT 0;#定义局部变量
	SELECT COUNT(*) INTO c#赋值
	FROM employees;
	RETURN c;
END $
调用
SELECT myf1()$
9.1.1 有参又有返回值
案例1:根据员工名,返回它的工资
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
	SET @sal=0; 			定义用户变量 
	SELECT salary INTO @sal   赋值
	FROM employees
	WHERE last_name = empName;
	RETURN @sal;
END $
SELECT myf2('k_ing') $


案例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')$

9.2 查看函数

SHOW CREATE FUNCTION myf3;  
也可通过
mysql的系统库当中查看
mysql库-proc-右击打开表

9.3 删除函数

DROP FUNCTION myf3;

10 流程控制介绍

10.1 分支结构-

10.1.1 if函数
语法:if(表达式1,表达式2,表达式3)
执行顺序:如果表达式1成立,则if返回表达式2的值,否则返回表达式 3的值
应用在任何地方
10.1.2 case结构
语法:
情况1:类似于switch
case 变量或表达式
when 值1 then 语句1;
when 值2 then 语句2;
...
else 语句n;
end [case];

情况2:
case 
when 条件1 then 语句1; 如果满足条件1,会在执行语句1后跳出,不会往下执行
when 条件2 then 语句2;
...
else 语句n;
end [case];
特点:①可以作为表达式嵌套在其他语句中使用,可以放在任何地方,应用在begin end 中或外面;
	可以作为独立的语句去使用,只能放在BEGIN END中
	②如果when中的值或条件成立,则执行对应后面的语句,并结束case,如都不满足则执行else中的语句或者值
	③else可以省略,如果省略,且所有与的when条件都不满足,则返回null

应用

案例1:创建函数,实现传入成绩,如果成绩>90,返回A,如果成绩>80,返回B,如果成绩>60,返回C,否则返回D
CREATE FUNCTION test_case(score FLOAT) RETURNS CHAR
BEGIN 
	DECLARE ch CHAR DEFAULT 'A';
	CASE 
	WHEN score>90 THEN SET ch='A';
	WHEN score>80 THEN SET ch='B';
	WHEN score>60 THEN SET ch='C';
	ELSE SET ch='D';
	END CASE;
	
	RETURN ch;
END $

SELECT test_case(56)$

注意分号

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_主键_15


mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_外键_16

10.1.3 if结构
3.if结构
语法:
if 条件1 then 语句1;
elseif 条件2 then 语句2;
....
[else 语句n;]
end if;
功能:类似于多重if

只能应用在begin end 中
delimiter $
CREATE FUNCTION test_if(score FLOAT) RETURNS CHAR
BEGIN
	DECLARE ch CHAR DEFAULT 'A';
	IF score>90 THEN SET ch='A';
	ELSEIF score>80 THEN SET ch='B';
	ELSEIF score>60 THEN SET ch='C';
	ELSE SET ch='D';
	END IF;
	RETURN ch;
END $

SELECT test_if(87)$

10.2 循环结构

分类:
while、loop、repeat
循环控制:
iterate类似于 continue,继续,结束本次循环,继续下一次
leave 类似于  break,跳出,结束当前所在的循环
10.2.1 while
语法:
【标签:】while 循环条件 do
	循环体;
end while【 标签】;
1.没有添加循环控制语句
案例:批量插入,根据次数插入到admin表中多条记录
DROP PROCEDURE pro_while1$
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	a: WHILE i<=insertCount DO
		INSERT INTO admin(username,`password`) VALUES(CONCAT('Rose',i),'666');  拼接操作
		SET i=i+1;
	END WHILE a;
END $
CALL pro_while1(100)$
2.添加leave
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)$
案例:ITERATE使用,批量插入,根据次数插入到admin表中多条记录,只插入偶数次
TRUNCATE TABLE admin$
DROP PROCEDURE test_while1$
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 0;
	a:WHILE i<=insertCount DO
		SET i=i+1;
		IF MOD(i,2)!=0 THEN ITERATE a;
		END IF;
		INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
	END WHILE a;
END $

CALL test_while1(100)$
10.2.2 loop
语法:
【标签:】loop
	循环体;
end loop 【标签】;
可以用来模拟简单的死循环
10.2.3 repeat
语法:
【标签:】repeat
	循环体;
until 结束循环的条件
end repeat 【标签】;
10.2.4 几种循环对比

mysql 存储过程中 PREPARE cursor mysql 存储过程中执行dml_mysql_17

循环结构案例

向该表插入指定个数的,随机的字符串
创建表
DROP TABLE IF EXISTS stringcontent;
CREATE TABLE stringcontent(
	id INT PRIMARY KEY AUTO_INCREMENT,
	content VARCHAR(20)	
);

DELIMITER $
CREATE PROCEDURE test_randstr_insert(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	DECLARE str VARCHAR(26) DEFAULT 'abcdefghijklmnopqrstuvwxyz';
	DECLARE startIndex INT;	代表初始索引
	DECLARE len INT;	代表截取的字符长度
	WHILE i<=insertcount DO
		SET startIndex=FLOOR(RAND()*26+1);	代表初始索引,随机范围1-26 rand0~0.99999999
		SET len=FLOOR(RAND()*(20-startIndex+1)+1);	代表截取长度,随机范围1-(20-startIndex+1)
		INSERT INTO stringcontent(content) VALUES(SUBSTR(str,startIndex,len));
		SET i=i+1;
	END WHILE;
END $

CALL test_randstr_insert(10)$