mysql-notes
MySQL笔记
MySQL-Server的安装
1 | sudo yum install mysql-server |
服务的停启
Linux
1 | sudo service mysql start |
1 | sudo systemctl start mysql.service |
Windows
1 | net start mysql |
数据库的备份
备份
1 | mysqldump -u用户名 -p密码 数据库名称 > 保存的路径 |
还原
- 登录数据库
- 创建数据库
- 使用数据库
- 执行文件。source 文件路径
MySQL服务器的登录方式
1 | mysql -u user -p |
MySQL的语法规范
- 不区分大小写,但建议关键字大写,表名、列名小写
- 每条命令最好用分号结尾
- 每条命令根据需要,可以进行缩进或换行
- 注释
单行注释:# 注释文字
单行注释:-- 注释文字
多行注释:/*注释文字*/
SQL分类
- DDL(Data Definition Language) 数据定义语言。用来定义数据库对象:数据库、表、列等。关键字: create drop alter 等。
- DML(Data Manipulation Language) 数据操作语言。 用来对数据库中表的数据进行增删改。 关键字: insert delete update 等
- DQL(Data Query Language) 数据查询语言。 用来查询数据库中表的记录(数据)。 关键字: select where 等。
- DCL(Data Control Language) 数据控制语言。 用来定义数据库的访问权限和安全级别,及创建用户。 关键字: grant revoke 等。
常用命令
1 | 1.查看当前所有的数据库 |
DDL
1.数据库操作(CRUD)
创建数据库(Create)
1 | CREATE {DATABASE|SCHEMA} [IF NOT EXISTS] 数据库名 |
查看数据库(Retrieve)
- 查看数据库系统中,指定的数据库名
1 | SHOW {DATABASES|SCHEMA} |
- 查看某个数据库的创建语句
1 | SHOW CREATE DATABASE DBNAME; |
修改数据库(Update)
1 | -- 修改数据库字符集 |
删除数据库(Delete)
1 | DROP {DATABASE|SCHEMA} [IF EXISTS] 数据库名; |
选择数据库
1 | USE 数据库名; |
- 查询当前正在使用的数据库名称
1 | SELECT DATABASE(); |
2.操作数据表
创建数据表(C)
1 | CREATE [TEMPORARY] TABLE [IF NOT EXISTS] 数据表名 |
create_definition部分:
1 | col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [PRIMARY KEY] [reference_definition] |
查看表结构(R)
1 | SHOW [FULL] COLUMNS FROM 数据表名 [FROM 数据库名]; |
- 查看表的构建语句
1 | SHOW CREATE TABLE TABLENAME; |
修改表结构(U)
1 | ALTER [IGNORE] TABLE <表名> |
1.修改表名
1 | alter table 表名 rename to 新的表名; |
2.修改表的字符集
1 | alter table 表名 character set 字符集名称; |
3.添加一列
1 | alter table 表名 add 列名 数据类型; |
4.修改列名称 类型
1 | alter table 表名 change 列名 新列名 新数据类型; |
5.删除列
1 | alter table 表名 drop 列名; |
其中MODIFY只修改字段数据类型,而CHANGE能够修改字段的名字和数据类型。
删除表(D)
1 | DROP TABLE [IF EXISTS] <TABLE_NAME>; |
重命名表
1 | RENAME TABLE <表名1> TO <表名2>; |
表的复制
1.仅仅复制表的结构
1 | CREATE TABLE [IF NOT EXISTS] <表名> LIKE <源表名>; -- 只复制表结构 |
2.复制表的结构+数据
1 | CREATE TABLE [IF NOT EXISTS] <表名> AS SELECT * FROM <源表名>; -- 复制表结构和数据 |
3.只复制部分数据
1 | CREATE TABLE copy3 |
4.仅仅复制某些字段
1 | CREATE TABLE copy4 |
3.约束
一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性
常用约束
NOT NULL
字段非空,字段不能插入null
DEFAULT
指定字段的默认值,字段的默认值为null,即非空字段没有插入值时,自动设置为null
UNIQUE
字段唯一,一个字段中的值不能重复,但可以存在多个null值
该约束的本质是一个唯一索引
PRIMARY KEY
主键约束,字段的值不能为空,且需要唯一,即 not null + unique
一张表只能有一个单列主键或一个复合表级主键
FOREIGN KEY
外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值
在从表添加外键约束,用于引用主表中某列的值
NOTE:
外键字段与引用字段的字段类型需要相同
若往外键字段添加非主表引用字段中的值,则无法添加,但可以添加null
要求在从表设置外键关系
主表的关联列必须是一个key(一般是主键或唯一)
插入数据时,先插入主表,再插入从表
删除数据时,先删除从表,再删除主表
约束的分类
列级约束
六大约束语法上都支持,但外键约束没有效果
表级约束
除了NOT NULL,DEFAULT其他的都支持
PRIMARY KEY 与 UNIQUE的区别
| UNIQUE | NOT NULL | 一个表中可以有多少个 | 是否允许组合 |
|---|---|---|---|
| Y | Y | 最多1个 | Y |
| Y | N | 可以存在多个 | Y |
约束的创建
CREATE TABLE 表名(
字段名 字段类型 列级约束,
字段名 字段类型,
表级约束
)
一、创建表时添加约束
1.添加列级约束
语法:
直接在字段名和类型后面追加 约束类型即可。
只支持:默认、非空、主键、唯一
1 | CREATE TABLE stuinfo( |
查看stuinfo中的所有索引,包括主键、外键、唯一
1 | SHOW INDEX FROM stuinfo; |
2.添加表级约束
语法:在各个字段的最下面
【constraint 约束名】 约束类型(字段名)
1 | DROP TABLE IF EXISTS stuinfo; |
通用的写法
除了外键,其余的都使用列级约束
1 | CREATE TABLE IF NOT EXISTS stuinfo( |
二、修改表时添加约束
1、添加列级约束
1 | alter table 表名 modify column 字段名 字段类型 新约束; |
2、添加表级约束
1 | alter table 表名 add 【constraint 约束名】 约束类型(字段名) 【外键的引用】; |
1 | DROP TABLE IF EXISTS stuinfo; |
1.添加非空约束
1 | ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NOT NULL; |
2.添加默认约束
1 | ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18; |
3.添加主键
①列级约束
1 | ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY; |
②表级约束
1 | ALTER TABLE stuinfo ADD PRIMARY KEY(id); |
4.添加唯一
①列级约束
1 | ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE; |
②表级约束
1 | ALTER TABLE stuinfo ADD UNIQUE(seat); |
5.添加外键
1 | ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id); |
三、修改表时删除约束
1.删除非空约束
1 | ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NULL; |
2.删除默认约束
1 | ALTER TABLE stuinfo MODIFY COLUMN age INT; |
3.删除主键
1 | ALTER TABLE stuinfo DROP PRIMARY KEY; |
4.删除唯一
1 | ALTER TABLE stuinfo DROP INDEX seat; |
5.删除外键
1 | ALTER TABLE stuinfo DROP FOREIGN KEY fk_stuinfo_major; |
标识列
又称为自增长列
含义:可以不用手动的插入值,系统提供默认的序列值
特点:
1、标识列可以作用在任意字段上
2、一个表可以有至多一个标识列
3、标识列的类型只能是数值型
4、标识列可以通过 SET auto_increment_increment=3;设置步长
5、可以通过手动插入值,设置起始值
6、自增字段插入时可以省略为null
创建表时设置标识列
1 | DROP TABLE IF EXISTS tab_identity; |
TRUNCATE将清除表中的内容,同时重置自增值
1 | TRUNCATE TABLE tab_identity; |
查看/设置自增步长
1 | SHOW VARIABLES LIKE '%auto_increment%'; |
DML
1.添加数据
语法:
1 | insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n); |
- 注意:
1.列名和值要一一对应。
2.如果表名后,不定义列名,则默认给所有列添加值
1 | insert into 表名 values(值1,值2,...值n); |
3.除了数字类型,其他类型需要使用引号(单双都可以)引起来
4.可以使用如下方式,一条SQL添加多条数据
1 | insert into 表名 values (值1,值2,...值n), (值1,值2,...值n), ....; |
5.values可以使用子查询代替
1 | insert into 表名 select * from other_table; |
2.删除数据
语法:
1 | delete from 表名 [where 条件] |
- 注意:
- 如果不加条件,则删除表中所有记录。
- 如果要删除所有记录
DELETE FROM 表名;– 不推荐使用。有多少条记录就会执行多少次删除操作TRUNCATE TABLE 表名;– 推荐使用,效率更高 先删除表,然后再创建一张一样的表。
1.truncate不能加where条件,而delete可以加where条件
2.truncate的效率高
3.truncate 删除带自增长的列的表后,如果再插入数据,数据从1开始
delete 删除带自增长列的表后,如果再插入数据,数据从上一次的断点处开始
4.truncate删除不能回滚,delete删除可以回滚
3.修改数据
- 语法:
1 | update 表名 set 列名1 = 值1, 列名2 = 值2,... [where 条件]; |
- 注意:
- 如果不加任何条件,则会将表中所有记录全部修改。
DQL
基础查询
语法:
SELECT 要查询的东西
【FROM 表名】;
特点:
①通过select查询完的结果,是一个虚拟的表格,不是真实存在
②要查询的东西 可以是常量值、可以是表达式、可以是字段、可以是函数
条件查询
条件查询:根据条件过滤原始表的数据,查询到想要的数据
语法:
1 | select |
分类:
一、条件表达式
示例:salary>10000
条件运算符:
1 | > < >= <= = != <> |
二、逻辑表达式
示例:salary>10000 && salary<20000
逻辑运算符:
and(&&):两个条件如果同时成立,结果为true,否则为falseor(||):两个条件只要有一个成立,结果为true,否则为falsenot(!):如果条件成立,则not后为false,否则为true
三、模糊查询
示例:
1 | last_name like 'a%' |
排序查询
语法:
1 | select |
常见函数
单行函数
每一行都将通过函数输出一个值
字符函数
1 | concat(str1, str2, ...) # 拼接 |
数学函数
1 | round 四舍五入 |
日期函数
1 | now 当前系统日期+时间 |
流程控制函数
if 处理双分支
case语句 处理多分支
情况1:处理等值判断
情况2:处理条件判断
其他函数
version版本
database当前库
user当前连接用户
分组函数
1 | sum 求和 |
特点:
1、以上五个分组函数都忽略null值,除了count()
2、sum和avg一般用于处理数值型
max、min、count可以处理任何数据类型
3、都可以搭配distinct使用,用于统计去重后的结果
4、count的参数可以支持:
字段、、常量值,一般放1
建议使用 count(*)
分组查询
语法:
1 | select 查询的字段,分组函数 |
特点:
1、可以按单个字段分组
2、和分组函数一同查询的字段最好是分组后的字段或者分组函数
3、分组筛选
针对的表 位置 关键字
分组前筛选: 原始表 group by的前面 where
分组后筛选: 分组后的结果集 group by的后面 having
4、可以按多个字段分组,字段之间用逗号隔开
5、可以支持排序
6、having后可以支持别名
多表连接查询
笛卡尔乘积:如果连接条件省略或无效则会出现
解决办法:添加上连接条件
内连接
一、传统模式下的连接 :等值连接——非等值连接
1.等值连接的结果 = 多个表的交集
2.n表连接,至少需要n-1个连接条件
3.多个表不分主次,没有顺序要求
4.一般为表起别名,提高阅读性和性能
二、sql99语法:通过join关键字实现连接
含义:1999年推出的sql语法
支持:
等值连接、非等值连接 (内连接)
外连接
交叉连接
语法:
1 | select 字段,... |
好处:语句上,连接条件和筛选条件实现了分离,简洁明了!
三、自连接
案例:查询员工名和直接上级的名称
sql99
1 | SELECT e.last_name,m.last_name |
sql92
1 | SELECT e.last_name,m.last_name |
外连接
join一侧的表作为主表,无论是否符合多表连接条件,都将在结果集中显示,没有对应的字段使用null填充
1 | SELECT * |
子查询
出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一行多列)
表子查询(结果集一般为多行多列)
按子查询出现的位置:
select后面:
仅仅支持标量子查询from后面:
支持表子查询where或having后面:
标量子查询(单行)
列子查询 (多行)
行子查询exists后面(相关子查询)
表子查询
where或having后面
1、标量子查询(单行子查询)
2、列子查询(多行子查询)
3、行子查询(多列多行)
特点:
①子查询放在小括号内
②子查询一般放在条件的右侧
③标量子查询,一般搭配着单行操作符使用
< >= <= = <>
列子查询,一般搭配着多行操作符使用
in、any/some、all
④子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
1.标量子查询
案例1:谁的工资比 Abel 高?
①查询Abel的工资
1 | SELECT salary |
②查询员工的信息,满足 salary>①结果
1 | SELECT * |
案例2:返回job_id与141号员工相同,salary比143号员工多的员工 姓名,job_id 和工资
①查询141号员工的job_id
1 | SELECT job_id |
②查询143号员工的salary
1 | SELECT salary |
③查询员工的姓名,job_id 和工资,要求job_id=①并且salary>②
1 | SELECT last_name,job_id,salary |
案例3:返回公司工资最少的员工的last_name,job_id和salary
①查询公司的 最低工资
1 | SELECT MIN(salary) |
②查询last_name,job_id和salary,要求salary=①
1 | SELECT last_name,job_id,salary |
案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资
①查询50号部门的最低工资
1 | SELECT MIN(salary) |
②查询每个部门的最低工资
1 | SELECT MIN(salary),department_id |
③ 在②基础上筛选,满足min(salary)>①
1 | SELECT MIN(salary),department_id |
2.列子查询(多行子查询)
案例1:返回location_id是1400或1700的部门中的所有员工姓名
①查询location_id是1400或1700的部门编号
1 | SELECT DISTINCT department_id |
②查询员工姓名,要求部门号是①列表中的某一个
1 | SELECT last_name |
3.行子查询(结果集一行多列或多行多列)
案例:查询员工编号最小并且工资最高的员工信息
1 | SELECT * |
①查询最小的员工编号
1 | SELECT MIN(employee_id) |
②查询最高工资
1 | SELECT MAX(salary) |
③查询员工信息
1 | SELECT * |
select后面
仅仅支持标量子查询
案例:查询每个部门的员工个数
1 | SELECT d.*,( |
案例2:查询员工号=102的部门名
1 | SELECT ( |
from后面
将子查询结果充当一张表,要求必须起别名
案例:查询每个部门的平均工资的工资等级
①查询每个部门的平均工资
1 | SELECT AVG(salary),department_id |
1 | SELECT * FROM job_grades; |
②连接①的结果集和job_grades表,筛选条件平均工资 between lowest_sal and highest_sal
1 | SELECT ag_dep.*,g.`grade_level` |
exists后面(相关子查询)
语法:
exists(完整的查询语句)
结果:
1或0
1 | SELECT EXISTS(SELECT employee_id FROM employees WHERE salary=300000); |
案例1:查询有员工的部门名
in
1 | SELECT department_name |
exists
1 | SELECT department_name |
分页查询
1 | select 字段|表达式,... |
NOTE:
1.起始条目索引从0开始
2.limit子句放在查询语句的最后
3.分页计算公式:
1 | select * from table_name limit(page-1)*sizePerPage,sizePerPage; |
联合查询
union 联合 合并:将多条查询语句的结果合并成一个结果
语法:
1 | 查询语句1 |
应用场景:
要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时
特点:
1、要求多条查询语句的查询列数是一致的
2、要求多条查询语句的查询的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all 可以包含重复项
事务
通过一组逻辑操作单元(一组DML——sql语句),将数据从一种状态切换到另外一种状态
ACID
(ACID)
Atomicity(原子性): 要么都执行,要么都回滚
Consistency(一致性): 保证数据的状态操作前和操作后保持一致
Isolation(隔离性): 多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰
Durability(持久性): 一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改
事务的分类
隐式事务
没有明显的开启和结束事务的标志
insert、update、delete语句本身就是一个事务,SQL在执行完成后自动提交事务
显式事务
具有明显的开启和结束事务的标志
1、开启事务
取消自动提交事务的功能,或手动开启一个事务
1 | SET autocommit=0; |
1 | START TRANSACTION; |
2、编写事务的一组逻辑操作单元(多条sql语句)
insert
update
delete
3、提交事务或回滚事务
1 | commit; |
1 | rollback; |
在事务中可以设置保存点,在回滚时会回滚到保存点前的事务状态,而不是将整个事务回滚
1 | savepoint 断点 |
事务隔离级别
- read uncommitted 读未提交(一般不使用)
- read committed 读已提交
- repeatable read 可重复读
- serializable 串行化(一般不使用)
隔离级别用于解决多个事务中读写并发执行时的问题,多个事务同时读取或同时写入的情况与隔离级别无关
- 脏读
读取到其他事务未提交的数据.无论如何都不应该发生 - 不可重复读
同一事务中,两次读取的数据不一致.可以发生 - 幻读
同一事务中,两次按同一条件读取的数据不一致.可以发生
NOTE: 在事务隔离级别为 repeatable-read 的情况下,事务每读取一个数据,就会为这行数据创建一个快照,在事务内后续对该数据的读取都将从快照中获取. 若在读取数据前,数据就发生了变化,则第一次读取的数据就是真实的、其他事务已提交的数据.
设置隔离级别
1 | set session|global transaction isolation level 隔离级别名; |
查看隔离级别
1 | select @@tx_isolation; |
视图
一张虚拟的表,但不占用存储空间,仅仅保存的是sql逻辑
视图的好处:
1、sql语句提高重用性,效率高
2、和表实现了分离,提高了安全性
视图的创建
1 | CREATE VIEW 视图名 |
1 | CREATE VIEW v1 |
视图逻辑的更新
方式一
1 | CREATE OR REPLACE VIEW test_v7 |
方式二
1 | ALTER VIEW test_v7 |
视图逻辑的删除
1 | DROP VIEW test_v1,test_v2,test_v3; |
视图结构的查看
1 | DESC test_v7; |
视图中数据的增删改查(视图的更新)
1.查询
1 | SELECT * FROM my_v4; |
2.插入视图的数据
1 | INSERT INTO my_v4(last_name,department_id) VALUES('虚竹',90); |
3.修改视图的数据
1 | UPDATE my_v4 SET last_name ='梦姑' WHERE last_name='虚竹'; |
4.删除视图的数据
1 | DELETE FROM my_v4; |
某些视图不能更新
1.包含以下关键字的sql语句
分组函数、distinct、group by、having、union或者union all
1 | CREATE OR REPLACE VIEW myv1 |
2.常量视图
1 | CREATE OR REPLACE VIEW myv2 |
3.Select中包含子查询
1 | CREATE OR REPLACE VIEW myv3 |
4.join
1 | CREATE OR REPLACE VIEW myv4 |
5.from一个不能更新的视图
1 | CREATE OR REPLACE VIEW myv5 |
5.where子句的子查询引用了from子句中的表
1 | CREATE OR REPLACE VIEW myv6 |
总结
视图能更新的前提是,视图中的字段与真实数据表中的字段一一对应,不存在函数的转换,多表的关联等
存储过程
一组经过预先编译的sql语句的集合
好处:
1、提高了sql语句的重用性,减少了开发程序员的压力
2、提高了效率
3、减少了传输次数
分类:
1、无返回无参
2、仅仅带in类型,无返回有参
3、仅仅带out类型,有返回无参
4、既带in又带out,有返回有参
5、带inout,有返回有参
注意:in、out、inout都可以在一个存储过程中带多个
创建存储过程
语法:
1 | create procedure 存储过程名(in|out|inout 参数名 参数类型,...) |
NOTE:
1、需要设置新的结束标记
使用默认默认换行符;会导致存储过程体中的语句提前结束
delimiter 新的结束标记
示例:
1 | delimiter $$ |
1 | CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...) |
2、存储过程体中可以有多条sql语句,如果仅仅一条sql语句,则可以省略begin end
3、参数前面的符号的意思
in:该参数只能作为输入(该参数不能做返回值)
out:该参数只能作为输出(该参数只能做返回值)
inout:既能做输入又能做输出
1 | CREATE PROCEDURE myp7(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT) |
调用存储过程
1 | call 存储过程名(实参列表) |
函数
创建函数
语法:
1 | CREATE FUNCTION 函数名(参数名 参数类型,...) RETURNS 返回类型 |
函数体中肯定会有return语句,如果没有会报错
如果return语句没有放在函数体的最后也不报错,但不建议
1 | CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE |
调用函数
1 | SELECT 函数名(实参列表) |
函数和存储过程的区别
| 关键字 | 调用语法 | 返回值 | 应用场景 |
|---|---|---|---|
| 函数FUNCTION | SELECT 函数() | 有且仅有一个 | 一般用于查询结果为一个值并返回时,有且仅有一个返回值 |
| 存储过程PROCEDURE | CALL 存储过程() | 可以有0个或多个 | 一般用于数据的批量更新 |
流程控制结构
系统变量
1.全局变量
作用域:针对于所有会话(连接)有效,但不能跨重启
若需要全局变量永久生效,需要在配置文件中配置
查看所有全局变量
1 | SHOW GLOBAL VARIABLES; |
查看满足条件的部分系统变量
1 | SHOW GLOBAL VARIABLES LIKE '%char%'; |
查看指定的系统变量的值
1 | SELECT @@global.autocommit; |
为某个系统变量赋值
1 | SET @@global.autocommit=0; |
2.会话变量
作用域:针对于当前会话(连接)有效
查看所有会话变量
1 | SHOW [SESSION] VARIABLES; |
查看满足条件的部分会话变量
1 | SHOW [SESSION] VARIABLES LIKE '%char%'; |
查看指定的会话变量的值
1 | SELECT @@autocommit; |
为某个会话变量赋值
1 | SET @@session.tx_isolation='read-uncommitted'; |
自定义变量
1.用户变量
声明并初始化:
1 | SET @变量名=值; |
赋值:
方式一:一般用于赋简单的值
1 | SET 变量名=值; |
方式二:一般用于赋表 中的字段值
1 | SELECT 字段名或表达式 INTO 变量 |
使用:
1 | select @变量名; |
2.局部变量
声明:
1 | declare 变量名 类型 [default 值]; |
赋值:
方式一:一般用于赋简单的值
1 | SET 变量名=值; |
方式二:一般用于赋表 中的字段值
1 | SELECT 字段名或表达式 INTO 变量 |
使用:
1 | select 变量名 |
二者的区别:
| 自定义变量类型 | 作用域 | 定义位置 | 语法 |
|---|---|---|---|
| 用户变量 | 当前会话 | 会话的任何地方 | 加@符号,不用指定类型 |
| 局部变量 | 定义它的BEGIN END中 | BEGIN END的第一句话 | 一般不用加@,需要指定类型 |
分支
1.if函数
语法:if(条件,值1,值2)
特点:可以用在任何位置
当条件满足时,返回值1,否则返回值2
2.case语句
语法:
情况一:类似于switch
1 | case 表达式 |
情况二:类似于多重if
1 | case |
特点:
可以用在任何位置
1 | CREATE FUNCTION test_case(score FLOAT) RETURNS CHAR |
3.if elseif语句
语法:
1 | if 情况1 then 语句1; |
特点:
只能用在begin end中
1 | CREATE FUNCTION test_if(score FLOAT) RETURNS CHAR |
三者比较
| 结构 | 应用场合 |
|---|---|
| if函数 | 简单双分支 |
| case结构 | 等值判断的多分支 |
| if结构 | 区间判断的多分支 |
循环
只能放在BEGIN END里面
循环控制
iterate类似于continue,继续,结束本次循环,继续下一次
leave 类似于break,跳出,结束当前所在的循环
如果要搭配leave跳转语句,需要使用标签,否则可以不用标签
1.while
语法:
1 | 【标签:】WHILE 循环条件 DO |
2.loop
语法:
1 | 【标签:】loop |
可以用来模拟简单的死循环
3.repeat
语法:
1 | 【标签:】repeat |
案例
1 | DROP PROCEDURE pro_while1$ |
1 | CREATE PROCEDURE test_while1(IN insertCount INT) |
1 | CREATE PROCEDURE test_while1(IN insertCount INT) |
DCL
DCL: 管理用户,授权
1.管理用户
MySQL的一个用户有用户名和允许访问的主机IP两个约束
即‘deltav‘@’localhost’和‘deltav‘@’%’是两个用户
1.添加用户
- 语法:
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
2.删除用户
- 语法:
DROP USER '用户名'@'主机名';
3.修改用户密码
1 | UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名'; |
- Windows MySQL-Server中忘记了root用户的密码
- cmd – > net stop mysql 停止mysql服务(需要管理员运行该cmd)
- 使用无验证方式启动mysql服务: mysqld –skip-grant-tables
- 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功
- use mysql;
- update user set password = password(‘你的新密码’) where user = ‘root’;
- 关闭两个窗口
- 打开任务管理器,手动结束mysqld.exe 的进程
- 启动mysql服务
- 使用新密码登录。
4.查询用户
1.切换到mysql数据库
1 | USE myql; |
2.查询user表
1 | SELECT * FROM USER; |
- 通配符: % 表示可以在任意主机使用用户登录数据库
2.权限管理
1. 查询权限
1 | SHOW GRANTS FOR '用户名'@'主机名'; |
2.授予权限
1 | GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名'; |
3.撤销权限
1 | REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名'; |
Chore
MySQL表结构以及表数据默认存放于/var/lib/mysql下,一个Schema对应一个目录。
MySQL数据库不区分SQL大小写,但建议使用大写。
MySQL运算符优先级
1 | ! |
编解码字符集
charset 和 collation 有多个级别的设置:服务器级、数据库级、表级、列级和连接级
1.服务器级
查看设置:show global variables like 'character_set_server'; 和 show global variables like 'collation_server';
修改设置:在OPTION FILE (/etc/mysql/my.cnf)里设置:
1 | [mysqld] |
2.数据库级
查看设置:
1 | select * from information_schema.schemata where schema_name = 'DataBase_Name';` |
设置:
1. 若没有显式设置,则自动使用服务器级的配置
2. 显式设置:在创建库时指定
create database database_name DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
3.表级
查看设置:show create table course;
设置:
1. 若没有显式设置,则自动使用数据库级的配置
2. 显式设置:在创建表时指定
create table table_name ( id int ) default charset=utf8 default collate=utf8_bin;
4.列级
查看设置:show create table course;
设置:
1. 若没有显式设置,则自动使用表级的配置
2. 显式设置:
CREATE TABLE Table1(column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci);
5.连接级别
查看设置:
1 | show variables like 'character_set_client'; # 服务端使用这个编码来理解客户端发来的statements |
对GROUP BY的理解
标准的 SQL 的解析顺序
- from子句组装来自不同数据源的数据;
- where子句基于指定的条件对记录行进行筛选;
- group by子句将数据划分为多个分组;
- 使用聚集函数进行计算;
- 使用having子句筛选分组;
- 计算所有的表达式;
- 使用order by对结果集进行排序。
执行过程:
- FROM:对FROM子句中前两个表执行笛卡尔积生成虚拟表vt1
- ON: 对vt1表应用ON筛选器只有满足 join_condition 为真的行才被插入vt2
- OUTER(join):如果指定了 OUTER JOIN保留表(preserved table)中未找到的行将行作为外部行添加到vt2,生成t3,如果from包含两个以上表,则对上一个联结生成的结果表和下一个表重复执行步骤和步骤直接结束。
- WHERE:对vt3应用 WHERE 筛选器只有使 where_condition 为true的行才被插入vt4
- GROUP BY:按GROUP BY子句中的列列表对vt4中的行分组生成vt5
- CUBE|ROLLUP:把超组(supergroups)插入vt6,生成vt6
- HAVING:对vt6应用HAVING筛选器只有使 having_condition 为true的组才插入vt7
- SELECT:处理select列表产生vt8
- DISTINCT:将重复的行从vt8中去除产生vt9
- ORDER BY:将vt9的行按order by子句中的列列表排序生成一个游标vc10
- TOP:从vc10的开始处选择指定数量或比例的行生成vt11 并返回调用者
注意:from后面的表关联,是自右向左解析的 ,而where条件的解析顺序是自下而上的。
注释
- 单行注释:
--# - 多行注释:
/**/
MySQL数据类型
- 数字类型
- 整数: tinyint、smallint、mediumint、int、bigint
- 浮点数: float、double、real、decimal
- 日期和时间: date、time、datetime、timestamp、year
- 字符串类型
- 字符串: char、varchar
- 文本: tinytext、text、mediumtext、longtext
- 二进制(可用来存储图片、音乐等): tinyblob、blob、mediumblob、longblob
数字类型
整型
| type | Storage | Minumun Value | Maximum Value |
|---|---|---|---|
| (Bytes) | (Signed/Unsigned) | (Signed/Unsigned) | |
| TINYINT | 1 | -128 | 127 |
| 0 | 255 | ||
| SMALLINT | 2 | -32768 | 32767 |
| 0 | 65535 | ||
| MEDIUMINT | 3 | -8388608 | 8388607 |
| 0 | 16777215 | ||
| INT | 4 | -2147483648 | 2147483647 |
| 0 | 4294967295 | ||
| BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
| 0 | 18446744073709551615 |
浮点型
| 属性 | 存储空间 | 精度 | 精确性 | 说明 |
|---|---|---|---|---|
| FLOAT(M, D) | 4 bytes | 单精度 | 非精确 | 单精度浮点型,m总个数,d小数位 |
| DOUBLE(M, D) | 8 bytes | 双精度 | 比Float精度高 | 双精度浮点型,m总个数,d小数位 |
- FLOAT容易造成精度丢失
定点数DECIMAL
- 高精度的数据类型,常用来存储交易相关的数据
- DECIMAL(M,N).M代表总精度,N代表小数点右侧的位数(标度)
- 1 < M < 254, 0 < N < 60;
- 存储空间变长
时间类型
| 类型 | 字节 | 例 | 精确性 |
|---|---|---|---|
| DATE | 三字节 | 2015-05-01 | 精确到年月日 |
| TIME | 三字节 | 11:12:00 | 精确到时分秒 |
| DATETIME | 八字节 | 2015-05-01 11:12:00 | 精确到年月日时分秒 |
| TIMESTAMP | 2015-05-01 11:12:00 | 精确到年月日时分秒 |
- MySQL在
5.6.4版本之后,TIMESTAMP和DATETIME支持到微秒。 TIMESTAMP会根据系统时区进行转换,DATETIME则不会- 存储范围的区别
TIMESTAMP存储范围:1970-01-01 00::00:01 to 2038-01-19 03:14:07DATETIME的存储范围:1000-01-01 00:00:00 to 9999-12-31 23:59:59
- 一般使用
TIMESTAMP国际化 - 如存时间戳使用数字类型
BIGINT
字符串类型
| 类型 | 单位 | 最大 | 特性 |
|---|---|---|---|
| CHAR | 字符 | 最大为255字符 | 存储定长,容易造成空间的浪费 |
| VARCHAR | 字符 | 可以超过255个字符 | 存储变长,节省存储空间 |
| TEXT | 字节 | 总大小为65535字节,约为64KB | - |
- TEXT在MySQL内部大多存储格式为溢出页,效率不如CHAR
- Mysql默认为utf-8,那么在英文模式下1个字符=1个字节,在中文模式下1个字符=3个字节。
并行写入
在事务中修改某行的数据,该行将产生一个行锁,只有这个事务提交了之后,其他事务才能修改这行数据