MySQL基础学习笔记

课程引入

为什么要学数据库

常见的数据库管理系统有MySQL、Oracle、DB2、SqlServer。程序员在客户端程序,通过数据库管理系统,对数据进行增删改查。其中,MySQL由于开源、免费等因素,是当前最受欢迎的数据库管理系统。淘宝、网易、百度、Facebook等众多互联网公司都在使用MySQL,学精了MySQL,就业市场广阔。

将数据存放在内存中不能持久化存储,存放在普通文件中不方便管理。
数据库管理系统的好处:

  • 实现数据持久化
  • 使用完整的管理系统统一管理,易于查询
数据库相关概念

DB:数据库(database),存储数据的“仓库”,他保存了一系列有组织的数据。

DBMS:数据库管理系统(database management system),数据库是通过DBMS进行管理的。

SQL:结构化查询语言(structure query language)。

SQL的优点

  • 几乎所有的DBMS都支持SQL
  • 简单易学
  • 虽然简单,但是功能强大,灵活使用可以完成诸多复杂、高级的功能。
数据库是如何存储数据的
  1. 将数据放在表上,再将表放进库中。
  2. 一个数据库可以有多个表,每个表名称具有唯一性。
  3. 表有自己的特性,表示表中数据的属性,一张表就类似于C++中的一个类。
  4. 表由列组成,列也称为字段。每一个列就类似于C++中类的一个属性。
  5. 表中数据按行存储,每一行类似于C++中的一个对象。
MySQL服务的登陆和退出
# MySQL服务的启动
net start 服务名
# MySQL服务的停止
net stop 服务名
# 连接本机
mysql -u root -p
# 退出
exit
MySQL常见命令
# 查看当前所有数据库
SHOW DATABASES;
# 打开指定的库
USE 库名;
# 查看库中的表
SHOW TABLES
FROM
	库名;
# 创建表
creat TABLE 表名 (
	列名 列类型,
	列名 列类型,
	列名 列类型 ,
	......);
# 查看表结构
DESC 表名;
MySQL语法规范
  • 不区分大小写,但是建议关键字大写,其他小写
  • 每条命令用分号结尾
  • 命令可以缩进和换行
  • 单行注释
# 单行注释
-- 单行注释(--后有空格)
  • 多行注释
/*
多行注释
*/
SQL语言的细分
  • DQL语言(Data Query Language):查询功能

  • DML语言(Data Manipulation Language):增删改功能
    tips:也有书籍将上面两种语言统称为DML,也即合并了增删改查四个功能。

  • DDL语言(Data Define Language):数据定义语言

  • TCL语言(Transaction Control Language):事务控制语言

查询(DQL语言)

基础查询
# 语法
SELECT
	查询列表
FROM
	表名;
# 查询单个字段
SELECT
	first_name
FROM
	employees;
# 查询多个字段 逗号隔开
SELECT
	first_name,
	last_name
FROM
	employees;
# 查询所有字段
SELECT
	*
FROM
	employees;
# 起别名 AS关键字 (空格也行)
SELECT
	first_name AS,
	last_name 姓
FROM
	employees
# 去重 Distinct关键字
SELECT DISTINCT
	last_name 姓
FROM
	employees
条件查询
# 语法
SELECT
	查询列表
FROM
	表名
WHERE
	筛选条件;
# 条件运算符
> 
<
<=
>=
<>!=
# 逻辑运算符
and&&
or|| 
not!
# 按条件运算符查询
SELECT
	*
FROM
	employees
WHERE
	salary > 12000;
#  逻辑运算符连接条件运算符查询

SELECT
	*
FROM
	employees
WHERE
	salary > 12000
AND salary < 180000;
#  模糊查询

LIKE 
BETWEEN AND 
IN 
IS NULL
/*
like 关键字 查询字符串
需要使用通配符
% 可以匹配若干个字符(包含0)
_ 可以匹配一个字符
*/
SELECT
	last_name
FROM
	employees
WHERE
	last_name LIKE '_r%'
/*
结果
Ernst
Greenberg
Urman
... ...
*/
# 转义字符:反斜杠 或 escape关键字

SELECT
	last_name
FROM
	employees
WHERE
	last_name LIKE '\_%' #查询以下划线开头的字符串
  	last_name LIKE 'a_%' escape 'a' #与上面语句等价
# between and 查找区间范围内的数字

SELECT
	last_name,
	salary
FROM
	employees
WHERE
	salary BETWEEN 10000
AND 15000
# in 判断字段值是否属于列表中的某一项

SELECT
	last_name,
	salary
FROM
	employees
WHERE
	salary IN (12000, 13000)
# is null 判断字段值是否为null
# =和!=不能判断null

SELECT
	last_name,
	salary
FROM
	employees
WHERE
	commission_pct IS NULL;
#	commission_pct is not null;
排序查询
# order by 排序列表(asc升序,desc降序)
# 注意先筛选(where)后排序

SELECT
	employee_id,
	salary,
	manager_id
FROM
	employees
WHERE
	salary BETWEEN 10000
AND 20000
ORDER BY
	salary DESC;

# 多关键字排序

SELECT
	employee_id,
	salary,
	manager_id
FROM
	employees
WHERE
	salary BETWEEN 10000
AND 20000
ORDER BY
	manager_id ASC,
	salary DESC;
# 从前往后排序,先按manager_id升序,再按salary降序。

函数

# 调用
SELECT
	函数名 (实参列表)
常见的字符函数

注意,SQL语言中的索引都从1开始。

# 获取字符串长度(字节)
SELECT
	length("abc123");

# 字符串拼接
SELECT
	concat(first_name, ' ', last_name) '姓名'
FROM
	employees;

# 将last_name中第一个字母大写,其余小写
SELECT
	concat(
		upper(substr(first_name, 1, 1)),
		lower(substr(first_name, 3))
	) '姓名'
FROM
	employees;
常见的数学函数
# round 四舍五入
SELECT
	round(1.456, 2);

# ceil 向上取整
SELECT
	ceil(1.1);

# floor 向下取整
SELECT
	floor(1.9);
常见的日期函数
# 返回当前系统时间
SELECT
	now();
流程控制函数
# if函数 类似于C语言中的三目运算
SELECT
IF (10 > 5, 'yes', 'no');
# case函数 类似于C语言中的switch case
CASE 表达式
WHEN 常量1 THEN
	语句1
WHEN 常量2 THEN
	语句2
WHEN 常量3 THEN
	语句3
ELSE
	默认语句
END
分组(统计)函数

单行函数一般作用于一个字段的一个值,而分组函数一般作用于一个字段的所有值。

# SUM(求和)
SELECT
	SUM(salary)
FROM
	employees;

# SUM(distinct )去重求和
SELECT
	SUM(DISTINCT salary)
FROM
	employees;

# AVG(求平均值n)
SELECT
	AVG(salary)
FROM
	employees;

# COUNT(计数)
SELECT
	COUNT(DISTINCT salary)
FROM
	employees;
分组查询
# group by 按照字段值分组
SELECT
	manager_id
FROM
	employees
GROUP BY
	manager_id;
# 分组函数结合分组查询
# 每个经理底下所有员工的最大工资
SELECT
	manager_id,
	max(salary)
FROM
	employees
GROUP BY
	manager_id;
# 分组前筛选
# 底下所有员工的最大工资大于5000的所有经理
SELECT
	manager_id,
	max(salary)
FROM
	employees
WHERE
	manager_id > 105
GROUP BY
	manager_id;
# 分组后筛选
# 底下所有员工的最大工资大于5000的所有经理
SELECT
	manager_id,
	max(salary)
FROM
	employees
GROUP BY
	manager_id
HAVING
	max(salary) > 5000;
# 分组前筛选+分组后筛选
# 底下所有员工的最大工资大于5000的所有经理
# 分组函数作为筛选条件肯定是放在having子句中。
SELECT
	manager_id,
	max(salary)
FROM
	employees
WHERE
	manager_id > 105
GROUP BY
	manager_id
HAVING
	max(salary) > 5000;
连接查询
# 笛卡尔乘积现象:表1有m行,表2有n行,结果总共有n*m行。

#需要使用链接查询避免笛卡尔乘积现象
SELECT
	boyname,
	NAME 
FROM
	boys,
	beauty
WHERE
	boys.id = beauty.boyfriend_id;
为表起别名
# 提高语句的简洁度
# 给表起别名之后,不能再使用原表名

SELECT 
	FIRST_name,
	department_name
FROM
	employees,
	departments
WHERE 
	departments.department_id=employees.department_id;


SELECT
	FIRST_name,
	department_name
FROM
	employees e,	# 起别名
	departments d	# 起别名
WHERE 
	d.department_id=e.department_id;


等值连接

只有两个表的字段值相同时才会被查询到。

SELECT
	d.department_name 部门名,
	l.city 所在城市
FROM
	locations l,
	departments d  
WHERE
	l.location_id = d.location_id
非等值连接
# 不用等于号作为链接
SELECT
	grade_level,
	employee_id
FROM
	job_grades,
	employees
WHERE
	salary <= highest_sal && salary >= lowest_sal
自连接
# 一张表连接自己
SELECT
	e1.last_name 员工名字,
	e2.last_name 此员工的经理名字,
	e1.employee_id 员工id,
	e2.employee_id 此员工的经理id
FROM
	employees e1,
	employees e2
WHERE
	e1.manager_id = e2.employee_id

sql99语法_等值连接

SELECT
	[查询列表]
FROM
	[1],
	[连接类型] JOIN
	[2]
ON 
	[连接条件]
WHERE
	[筛选条件]
GROUP BY
	[分组条件]
ORDER BY
	[排序列表]

/*
连接类型
	内连接:inner

	外连接:
		左外:left (outer)
		右外:right(outer)
		全外:full(outer)
	
	交叉连接:cross
*/
等值连接
SELECT
	count(*),l.city
FROM
	departments d
INNER JOIN
	locations l 
ON
	d.location_id=l.location_id
GROUP BY
	l.city
HAVING
	count(*)>=3
ORDER BY
	count(*)
SELECT
	count(*),
	department_name
FROM
	departments d
INNER JOIN  
	employees e
ON 
	d.department_id=e.department_id
GROUP BY
	d.department_name
HAVING
	count(*)>3
ORDER BY
	count(*)
ASC

非等值连接、自连接同理。

左(右)外连接
/*
应用场景:用于查询一个表中有,而另一个表中没有的记录。

1.外连接的查询结果为主表中的所有记录
	如果从表中有和它匹配的记录,则显示它的值。
	如果从表中没有和它匹配的记录,则显示NULL。

2.左外连接,left join左边的表是主表
  左外连接,right join右边的表是主表
*/

SELECT
	boyName,
	name
FROM
	boys
RIGHT JOIN
	beauty
ON 
	boys.id=beauty.boyfriend_id
全外连接
/*
全外连接的结果为:内连接+表1有表2没有+表2有表1没有
*/
SELECT
	b1.*,
	b2.*
FROM
	boys b1
FULL OUTER JOIN
	beauty b2
ON
	b1.id = b2.boyfriend_id
交叉连接
/*
交叉连接结果为笛卡尔积
*/

子查询






where后面的标量子查询
SELECT
	first_name
FROM
	employees e
WHERE
	e.salary > (
		SELECT
			sum(salary) / count(*)
		FROM
			employees
	)
ORDER BY
	salary
SELECT
	first_name,
	job_id,
	salary
FROM
	employees e
WHERE
	e.job_id = (
		SELECT
			job_id
		FROM
			employees
		WHERE
			employee_id = 141
	) && e.salary > (
		SELECT
			salary
		FROM
			employees
		WHERE
			employee_id = 143
	)
having后面的标量子查询
SELECT
	min(salary)
FROM
	employees
GROUP BY
	department_id
HAVING
	min(salary) > (
		SELECT
			min(salary)
		FROM
			employees
		WHERE
			department_id = 50
	)
where后面的列子查询
SELECT
	first_name
FROM
	employees
WHERE
	department_id IN (
		SELECT
			department_id
		FROM
			departments
		WHERE
			location_id = 1400 || location_id = 1700
	)
where后面的行子查询
SELECT
	*
FROM
	employees
WHERE
	(employee_id, salary) = (
		SELECT
			min(employee_id),
			max(salary)
		FROM
			employees
	)
select后面的标量子查询
SELECT
	d.department_name,
	(
		SELECT
			count(*)
		FROM
			employees e
		WHERE
			e.department_id = d.department_id
	)
FROM
	departments d
from后面的子查询
SELECT
	grade_level
FROM
	(
		SELECT
			AVG(salary) ag,
			department_id
		FROM
			employees
		GROUP BY
			department_id
	) s
JOIN job_grades j ON s.ag <= j.highest_sal && s.ag >= j.lowest_sal;
exists后面的子查询(相关子查询)
# exists(是否存在) 返回 0 或 1 
SELECT
	EXISTS (
		SELECT
			*
		FROM
			employees
		WHERE
			salary > 10000
	)
SELECT
	department_name
FROM
	departments d
WHERE
	EXISTS (
		SELECT
			*
		FROM
			employees e
		WHERE
			e.department_id = d.department_id
	)
limit 分页查询
# limit [begin] [size] 
# 索引从0开始
SELECT
	*
FROM
	employees
LIMIT 10,5;
# 查询11-15
union 联合查询
/*
union 会自动 去重,不想去重可以使用union all
union 的两个查询结果字段数量必须一样多
*/
SELECT
	employee_id
FROM
	employees
UNION
SELECT
	department_id
FROM
	departments

增删改(DML语言)

插入记录
/*
语法:
INSERT INTO 表名(列名1,...)
VALUE(值1,...)

插入的值的类型要和列的类型一致或兼容。
列的数量和顺序可以改变,但要和值一一对应上。
*/

写法一

INSERT  INTO boys(id,boyname,usercp) 
value(5,'hesorchen',520)
# 列名可以省略,默认为表中的字段。
INSERT  INTO boys 
value(6,'hesor',52013)

写法二:

INSERT INTO boys
SET id = 10,
 boyname = 'chenyan',
 usercp = 1314;

写法三:

INSERT INTO temp SELECT
	*
FROM
	copy;
修改记录
UPDATE boys
SET1=1,2=2,
     ...
WHERE
    筛选条件
UPDATE boys
SET id = 9,
 boyname = 'zhangsan',
 userCP = 2
WHERE
	id = 3
删除记录
# 删除一定是一行
# 语法
DELETE
FROM
	表名
WHERE
	筛选条件
DELETE
FROM
	boys
WHERE
	id = 2 
# truncate删除记录,删除所有记录
 TRUNCATE TABLE t1;

delete删除记录可以回滚,truncate删除记录不可以回滚。

数据定义语言(DDL语言)

库的管理
# 创建库
CREATE DATABASE 库名
# 没有才创建库
CREATE DATABASE IF NOT EXISTS 库名
库的删除
# 删除库
DROP DATABASE 库名
# 没有才删除库
DROP DATABASE IF EXISTS 库名
表的创建
# 语法:
CREATE TABLE 表名(
	列名 列的类型【(长度) 约束】,
	列名 列的类型【(长度) 约束】, 
	列名 列的类型【(长度) 约束】
)
CREATE TABLE books (
	id INT,
	#编号
	bname VARCHAR (20),
	#书名
	author VARCHAR (20),
	#作者
	price DOUBLE #价格
);
表的修改
ALTER TABLE 表名 [ADD/DROP/change/MODIFY] COLUMN 列名 

修改列名

# 语法:
ALTER TABLE 表名 
CHANGE COLUMN 原列名 要改成的列名 改后的列类型
ALTER TABLE books 
CHANGE COLUMN author writer VARCHAR (15) 

修改列的类型和约束

# 语法:
ALTER TABLE 表名 
MODIFY COLUMN  要改的列名 改后的列类型
ALTER TABLE books 
MODIFY COLUMN  id TIMESTAMP

增加列

# 语法:
ALTER TABLE 表名 
ADD COLUMN  要增加的列名 列类型
ALTER TABLE books 
ADD COLUMN  test INT

删除列

# 语法:
ALTER TABLE 表名 
DROP COLUMN  要删除的列名
ALTER TABLE books
DROP COLUMN  test

修改表名

# 语法:
ALTER TABLE 表名 
RENAME TO  要改成的表名
ALTER TABLE books
RENAME TO  book
表的复制
# 只复制表结构
CREATE TABLE copy LIKE temp;
# 复制结构及数据
CREATE TABLE copy SELECT
	*
FROM
	temp
WHERE
	a1 = 1;
表的删除
# 删除表
DROP TABLE 表名
# 没有才删除表
DROP TABLE IF EXISTS 表名

数据类型

整形
类型字节范围
Tinyint1-128~127
Smallint2-32768~32767
Mediumintint3-8388608~8388607
Int4-2147483648~2147483647
Bigint8-9223372036854775808~9223372036854775807
CREATE TABLE temp (
	a1 INT,
	a2 INT UNSIGNED,
	a3 BIGINT
);
小数
类型字节
Float1
Double2
CREATE TABLE temp (
	a1 FLOAT(10【整数位+小数位总位数】,2【小数位数】),
	a2 DOUBLE(10,2),
	a3 DECIMAL(10,2)
);
字符类型
类型最多字符数描述及存储需求
Char(M)MM为0~255的整数
Varchar(M)MM为0~65535的整数

Char为固定长度字符,Varchar为可变长度字符,因此Char更耗费空间,但是效率更高。

还有一些不太常用的字符类型:

  1. Binary和Varbinary,类似于Char和Varchar,不过它们是用来存储二进制串。

  2. Enum(‘a’,‘b’,‘c’),括号中是列表值,最终选择的值只能是在列表中的。

  3. Set(‘a’,‘b’,‘c’),类似于Enum,不过Enum是单选,Set可以多选。

CREATE TABLE temp (a CHAR(10));

INSERT INTO temp
VALUES
	('01hello陈');

SELECT
	*
FROM
	temp;
CREATE TABLE temp (a BINARY(10));

INSERT INTO temp
VALUES
	('0111001');

SELECT
	*
FROM
	temp;
CREATE TABLE temp (a SET('1', '2', '3'));

INSERT INTO t1
VALUES
	('1'),
	('1,3');

SELECT
	*
FROM
	t1;
日期型
数据类型用处
date保存日期
time保存时间
year保存年份
datetime保存日期和时间
timestamp保存日期和时间

约束

常见约束
约束类型用处
NOT NULL字段值非空
DEFAULT字段值有默认值
PRIMARY KEY主键,字段值具有唯一性,并且非空
UNIQUE字段值具有唯一性
FOREIGN KEY外键,改字段值必须来自于主表的关联列的值【比如学生的专业,必须来自于专业表】
创建约束

列级约束

CREATE TABLE temp1 (
	id INT PRIMARY KEY,
	majorNAME VARCHAR (20)
);

CREATE TABLE temp (
	id INT PRIMARY KEY,
	stuNAME VARCHAR (20) NOT NULL,
	gender CHAR (1) DEFAULT '男',
	seat INT UNIQUE
);

表级约束

语法格式:
#【constraint 约束名】 约束类型(字段名)
# 【】中的内容可以省略,省略后约束名会自动生成。

CREATE TABLE temp1 (
	id INT PRIMARY KEY,
	majorNAME VARCHAR (20)
);

CREATE TABLE temp (
	id INT,
	majorid INT,
	stuNAME VARCHAR (20),
	gender CHAR (1),
	seat INT,
	CONSTRAINT con1 PRIMARY KEY(id),
	CONSTRAINT con2 UNIQUE(seat),
	CONSTRAINT fk_temp_temp1 FOREIGN KEY(majorid) REFERENCES temp1(id)
);

一般来说,外键使用表级约束,其他使用列级约束。

组合主键以及组合唯一键。功能就是当组合起来冲突时才算冲突。

CREATE TABLE temp (
	id INT,
	majorid INT,
	stuNAME VARCHAR (20),
	gender CHAR (1),
	seat INT,
	PRIMARY KEY (id, majorid),
	UNIQUE (seat, gender)
);

外键的特点

  1. 必须在从表创建外键。
  2. 主从表关联列的类型要一致。
  3. 主表中的关联列必须是key(一般是主键或唯一键)
  4. 插入数据时,先插入主表,再插入从表。删除数据时,先删除从表,再删除主表。
修改表时添加约束
语法:
1. 添加列级约束
ALTER TABLE 表名 MODIFY COLUMN 列名 字段类型 新约束
2. 添加列级约束
ALTER TABLE 表名 ADDCONSTRAINT 约束名】 约束类型(字段名)

# 添加非空约束
ALTER TABLE t1 MODIFY COLUMN id INT NOT UNIQUE;

# 添加默认约束
ALTER TABLE t1 MODIFY COLUMN id INT default 100;

# 添加主键约束
# 1.列级约束写法
ALTER TABLE t1 MODIFY COLUMN id INT PRIMARY KEY;
# 2.表级约束写法
ALTER TABLE t1 ADD PRIMARY KEY(id);

# 添加唯一约束
# 1.列级约束写法
ALTER TABLE t1 MODIFY COLUMN id INT UNIQUE;
# 2.表级约束写法
ALTER TABLE t1 ADD UNIQUE(id);

# 添加外键约束
ALTER TABLE t1 ADD FOREIGN KEY(id) REFERENCES t2(id);
修改表时删除约束
语法:
1. 添加列级约束
ALTER TABLE 表名 MODIFY COLUMN 列名 字段类型 新约束
2. 添加列级约束
ALTER TABLE 表名 ADDCONSTRAINT 约束名】 约束类型(字段名)

# 删除非空约束
ALTER TABLE t1 MODIFY COLUMN id INT;

# 删除默认约束
ALTER TABLE t1 MODIFY COLUMN id INT;

# 删除主键约束
ALTER TABLE t1 DROP PRIMARY KEY;

# 删除唯一约束
ALTER TABLE t1 DROP INDEX 约束名;

# 删除外键约束
ALTER TABLE t1 DROP FOREIGN KEY 约束名;

标识列

又称自增长列,可以不用手动插入值,系统提供默认的序列值,默认从1开始。

标识列的特点:

  1. 必须是一个key
  2. 一个表最多一个标识列
  3. 标识必须是数值类型(整数或小数)
添加标识列
# 创建表时添加标识列
CREATE TABLE
IF NOT EXISTS t1 (
	id INT UNIQUE AUTO_INCREMENT
);

# 修改表时设置标识列
ALTER TABLE t1 MODIFY COLUMN id INT UNIQUE AUTO_INCREMENT;

删除标识列
ALTER TABLE t1 MODIFY COLUMN id INT;

事务控制语言(TCL)

事务:一个或一组sql组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。

事务的属性(ACID)

  1. 原子性(Atomicity):事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

  2. 一致性(consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态。

  3. 隔离性(Isolation):隔离性是当多个用户并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  4. 持久性(Durability):持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

事务的创建

隐式事务:事务没有明显的开启和结束

比如insert、update、delete语句

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

SET autocommit = 0;
START TRANSACTION;

事务中的sql语句(select INSERT UPDATE delete;

COMMIT;#提交事务
ROLLBACK;#回滚事务
事务并发可能导致的问题

对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:

问题描述
脏读对于两个事务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 @@transaction_isolation;

设置隔离级别

set sessionglobaltransaction isolation level 隔离级别;
savepoint的使用
SET autocommit = 0;
INSERT INTO t1 VALUES(1);
SAVEPOINT p1;# 设置保存点
INSERT INTO t1 VALUES(2);
ROLLBACK TO p1;# 回滚到保存点
# 最后只提交了第一条insert语句。

视图

视图:一种虚拟存在的表,行和列的数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的,只保存了sql逻辑,不保存查询结果。

应用场景:

  • 多个地方用到同样的查询结果
  • 该查询结果使用的sql语句比较复杂
视图的创建
CREATE VIEW V1 
AS 
SELECT
	studentname,
	majorname
FROM
	students
INNER JOIN major ON students.marjorid = major.majorid
WHERE
	studnets.majorid = 1;

SELECT * FROM V1 WHERE studentname LIKE '张%';
视图的修改
# 方式一 CREATE OR REPLACE VIEW 视图名

CREATE OR REPLACE VIEW V1 
AS 
SELECT
	studentname,
	majorname
FROM
	students
INNER JOIN major ON students.marjorid = major.majorid
WHERE
	studnets.majorid = 1;
# 方式二 ALTER VIEW 视图名

ALTER VIEW V1 
AS 
SELECT
	studentname,
	majorname
FROM
	students
INNER JOIN major ON students.marjorid = major.majorid
WHERE
	studnets.majorid = 1;
视图的删除
DROP VIEW 视图名;
视图的查看
DESC VIEW 视图名;
视图的更新

对视图进行insert、update、delete等操作时,会在原表中做对应的更新,不在视图中的字段值为NULL。但是以下情况不能对视图进行更新:

  1. 包含以下关键字的sql语句:分组函数、distinct、group by、having、union、union all
  2. 常量视图
  3. select中包含子查询
  4. 连接查询
  5. from一个不能更新的表
  6. where子句中的子查询引用了from子句中的表

存储过程和函数

变量

一、系统变量:

  1. 全局变量
  2. 会话变量

二、自定义变量:

  1. 用户变量
  2. 局部变量

一、系统变量

系统变量由系统提供,不是用户定义,属于服务器层面使用的语法:
注意:如果是全局级别,使用关键字GLOBAL,如果是会话级别,使用关键字SESSION,都不使用默认SESSION。

  1. 查看所有系统变量
SHOW GLOBAL VARIABLES; # 查看所有系统变量
SHOW SESSION VARIABLES; # 查看所有会话变量
  1. 查看满足条件的部分系统变量
SHOW GLOBAL VARIABLES LIKE%char%; # 查看名称中包含‘char’的所有系统变量
  1. 查看指定的系统变量的值
SELECT @@GLOBAL.系统变量名; # 查看系统变量名的值
SELECT @@global.autocommit;
  1. 为指定的系统变量赋值
# 方式一
SET global|SESSION 系统变量名 =;
# 方式二
SET @@global|SESSION.系统变量名 =;

二、自定义变量

用户变量

作用域:针对于当前会话有效,同于会话变量的作用域。

  1. 声明并初始化
# 三种方式
SET @用户变量名 =;
SET @用户变量名 :=;
SELECT @用户变量名 :=;
  1. 赋值
# 方式一 
SET @用户变量名 =;
SET @用户变量名 :=;
SELECT @用户变量名 :=;
# 方式二
SELECT 字段 INTO @用户变量名 FROM;
  1. 查看
SELECT @用户变量名;

局部变量

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

  1. 声明
DECLARE 变量名 类型;
DECLARE 变量名 类型 DEFAULT;
  1. 赋值
# 方式一 
SET 局部变量名 =;
SET 局部变量名 :=;
SELECT @局部变量名 :=;
# 方式二
SELECT 字段 INTO 局部变量名 FROM;
  1. 查看
SELECT 局部变量名;
存储过程

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

优点:

  1. 提高代码的重用性
  2. 简化操作
  3. 减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率。
存储过程的创建
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
	存储过程体
END
存储过程的创建
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
	存储过程体
END

注意:

  1. 参数列表包含三个部分:参数模式 参数名 参数类型
    参数模式有三种:
    IN:该参数作为输入
    OUT:该参数可以作为输出(返回值)
    INOUT:该参数即作为输入,又可以作为输出

  2. 如果存储过程体只有一句话,可以省略BEGIN END。存储过程体中的每条SQL语句的结尾必须加分号;

  3. 默认情况下,delimiter是分号,可以用DELIMITER重新设置结尾符号。如果delimiter不重新设置,会和存储过程中的分号冲突,因此需要事先将delimiter设置成其他符号:

DELIMITER $$
存储过程的调用
CALL 存储过程名(实参列表);
存储过程使用实例
  1. 无参的存储过程实例:
CREATE TABLE
IF NOT EXISTS t1 (num INT);

DELIMITER $$

CREATE PROCEDURE ins1 ()
BEGIN
	INSERT INTO t1
	VALUES
		(1),
		(3) ;
END $$

CALL ins1 () $$

SELECT
	*
FROM
	t1 $$
  1. 带IN模式参数的存储过程实例:
CREATE TABLE
IF NOT EXISTS t1 (num INT);

DELIMITER $$

CREATE PROCEDURE ins2 (IN val INT)
BEGIN
	INSERT INTO t1
	VALUES
		(val);
END $$

CALL ins2 (10086) $$

SELECT
	*
FROM
	t1 $$
  1. 带OUT模式参数的存储过程实例:
CREATE TABLE
IF NOT EXISTS t1 (num INT);

DELIMITER $$

CREATE PROCEDURE get_sum (OUT s INT)
BEGIN
	SELECT
		sum(num) INTO s
	FROM
		t1 ; 
END$$


SET @answer = 0$$

CALL get_sum (@answer)$$

SELECT
	@answer$$

  1. 带INOUT模式参数的存储过程实例:
# 使两个变量翻倍
DELIMITER $$
CREATE PROCEDURE doub (INOUT a INT, INOUT b INT)
BEGIN
	SET a := a * 2 ;
	SET b := b * 2 ; 
END$$


SET @a = 1 ,@b = 2$$

CALL doub (@a ,@b)$$

SELECT
	@a ,@b$$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值