# MySQL必知必会
# 名词
- SQL: Structured Query Language 结构化查询语言
- DBMS: 数据库管理系统,如MySQL
- 模式: 用来描述数据库中特定的表以及整个数据库,即关于数据库和表的布局及特性的信息
# 基础知识
# 好习惯
# 主键使用
- 不更新主键列中的值
- 不重用主键列的值
- 不在主键列中使用可能更改的值
# 语法
DISTINCT: 去重
SELECT DISTINCT src_uid from relationship_table;
ORDER BY: 不指定排序方式时,默认为升序
# 通配符
LIKE操作符: 用于匹配值的一部分的特殊字符
百分号通配符: 表示任何非null字符出现任意次数
下划线通配符: 匹配单个字符
SELECT * FROM animals where name LIKE 'jo%';
SELECT * FROM animals where name LIKE 'jos_';
# 技巧
- 不要过度使用通配符,优先使用操作符
- 必要使用时,避免将通配符置于搜索模式的开始处
- 注意通配符的位置
# 正则表达式
REGEXP与LIKE操作符的差别是: LIKE需使用通配符才能返回行,正则需要正则表达式
SELECT * FROM animals WHERE name REGEXP 'josh';
# 数据分组
GROUP BY: 按字段相同分组
WITH ROLLUP: 按分组汇总
HAVING: 按条件过滤分组,WHERE过滤行,HAVING过滤组
SELECT type, age FROM animals GROUP BY type WITH ROLLUP;
SELECT type, age FROM animals GROUP BY type HAVING age > 10;
# 技巧
- 不可依赖GROUP BY的默认排序,使用时一定要使用ORDER BY进行排序
# 联结
外键: 外键为某表的一列,它包含另一个表的主键值
笛卡儿积: 由没有联结条件
的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。所以每个联结都需要WHERE筛选条件。
SELECT persons.name, age
FROM persons, infs;
# 内部联结
INNER JOIN: 和FROM相近,但指定联结条件时使用的是ON而非WHERE,用该语法以确保不会忘记联结条件,提升性能
SELECT persons.name, age
FROM persons
INNER JOIN infs
ON persons.name = infs.name;
# 自联结
通过自联结代替子查询
# 子查询
SELECT *
FROM persons
WHERE name IN (
SELECT name
FROM infs
);
# 自联结
SELECT persons.*
FROM persons, infs
WHERE persons.name = infs.name;
# 自然联结
一次查询中,一个列名只会出现一次,需人为保证不重复。
# 外部联结
通过LEFT
或RIGHT
关键字,指定包括其所有行的表
SELECT persons.name, age
FROM persons
LEFT OUTER JOIN infs
ON persons.name = infs.name;
# 组合
通过UNION
连接多条复杂查询语句,返回结果会去重,若需不去重,使用UNION ALL
。只允许最后一条查询语句带上ORDER BY
子句
SELECT name FROM persons WHERE created_at < 200
UNION
SELECT name FROM infs WHERE age < 20;
# 插入数据
# 性能优化
插入SQL可能很耗时,会降低处理SELECT语句的性能,可以通过LOW_PRIORITY
降低语句优先级
INSERT LOW_PRIORITY INTO persons
(name)
VALUES
(josh)
# 插入检索出的数据
通过INSERT SELECT
组合语句实现
INSERT INTO new_persons
(name)
SELECT
name
FROM persons
# 更新多行
UPDATE persons
SET age = 18, weight = 130
WHERE name in (josh, kevin);
# 删除数据
DELETE FROM persons
WHERE name = josh;
# 创建表
# 数据库引擎
- InnoDB: 一个可靠的事务处理引擎,不支持全文本搜索
- MyISAM: 一个性能极高的引擎,它支持全文本搜索,但不支持事务处理
- MEMORY: 功能同MyISAM,数据存储于内存而非硬盘
# 更新表
# 新增列
ALTER TABLE persons
ADD weight CHAR(20);
# 删除列
ALTER TABLE persons
DROP COLUMN weight;
# 删除表
DROP TABLE persons;
# 重命名表
RENAME TABLE new_persons TO persons;
当更新的列比较多,需要建新表时:
- 用新的列布局创建一个新表
- 使用
INSERT SELECT
语句 - 校验包含所需数据的新表
- 重命名旧表
- 用旧表原名重命名新表
- 根据需要创建触发器、存储过程、索引和外键
# 视图
好处:
- 复用SQL
- 可简化复杂SQL的操作
- 使用表的组成部分而不是整个表
- 保护数据,可给用户授权视图
- 更改数据格式和表示,视图可返回与底层表的表示和格式不同的数据
# 语法
CREATE VIEW
创建视图
CREATE VIEW view_name AS
SELECT cust_name, order_name
FROM customers, orders
WHERE customers.cust_id = orders.cust_id;
SHOW CREATE VIEW viewname
查看视图SQL
DROP VIEW viewname
删除视图
CREATE OR REPLACE VIEW
更新或新建视图,并非所有视图都可更新,使用了分组、联结、子查询、并、聚集函数等的不可更新
# 存储过程
# 优劣
优势:
- 简单
- 安全
- 高性能
劣势:
- 一般不会分配存储过程创建权限
- 不适合分布式场景、弱事务场景
- 不易进行问题排查
# 语法
# 创建存储过程
CREATE PROCEDURE getWeight(
IN name DECIMAL(8,2),
IN age DECIMAL(8,2),
OUT weight DECIMAL(8,2),
)
BEGIN
SELECT userweight
FROM persons
WHERE username = name, userage = age
INTO weight;
END;
# 调用存储过程
CALL getAvg(@max,@min,@average);
# 删除存储过程
DROP PROCEDURE getAvg;
# 游标
当需要在检索出来的行中,前进或后退一行或多行,就需要使用游标。游标是语句检索出来的结果集。
# 语法
DROP PROCEDURE test;
CREATE PROCEDURE test()
BEGIN
DECLARE done INT DEFAULT 0; # 创建遍历结束符号
DECLARE tmp INT default null; # 临时变量
DECLARE c CURSOR # 创建游标
FOR
SELECT age FROM table2;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; # 遍历完毕赋值 SQLSTATE '02000' 是未找到条件
OPEN c; # 打开游标
REPEAT # 重复遍历
FETCH c INTO tmp; # 临时变量赋值
UNTIL done END REPEAT; # 遍历结束
CLOSE c; # 关闭游标
SELECT tmp; # 输出临时变量
END;
CALL test();
# 触发器
当执行以下MYSQL语句时触发:
- INSERT
- UPDATE
- DELETE
# 语法
DROP TRIGGER ins; # 删除触发器
CREATE TRIGGER ins AFTER INSERT table1 # 创建insert触发器
FOR EACH ROW
INSERT INTO log
(name)
VALUES
(NEW.name); # NEW 指新插入的记录
UPDATE TRIGGER upt AFTER UPDATE table1
FOR EACH ROW
UPDATE INTO log
(name)
VALUES
(OLD.name); # OLD 指更新前的记录
# 事务
仅InnoDB数据库引擎支持,用于管理以下语句:
- INSERT
- UPDATE
- DELETE
# 语法
START TRANSACTION; # 开启事务
INSERT INTO table2
(id, name)
VALUES
(5,6);
SAVEPOINT step1; # 设置保留点1
INSERT INTO table2
(id, name)
VALUES
(6,7);
SAVEPOINT step2;
ROLLBACK TO step1; # 回滚到保留点1; 不指定时 全部回滚
COMMIT; # 提交事务
# 安全管理
# 语法
use mysql;
SELECT user FROM user; # 查看用户列表
CREATE USER ben IDENTIFIED BY 'passport'; # 创建用户和密码
DROP USER ben; # 删除用户
RENAME USER ben TO tester; # 重命名用户名
SET PASSPORT FOR tester = Password('newpassport'); # 修改他人密码
SET PASSPORT = Password('newpassport'); # 修改自己密码
SHOW GRANTS FOR tester; # 显示用户权限
GRANT SELECT ON test.* TO tester; # 授权数据库test的SELECT权限
GRANT ALL ON test.* TO tester; # 授权数据库test的所有权限
REVOKE SELECT ON test.* FROM tester; # 删除权限
# 权限表
# 基础函数
# 字符串处理
- CONCAT拼接字段
SELECT CONCAT(name, '_', age) FROM animals;
- TRIM: 移除左右空格
- LTRIM: 移除左空格
- RTRIM: 移除右空格
- LEFT: 返回字符串左字符
- RIGHT: 返回字符串右字符
- LOCATE(a,b): a出现在b中的位置索引
- LENTH: 返回串的长度
- LOWER: 转为小写
- UPPER: 转为大写
# 时间处理
- ADDDATE(date, INTERVAL expr unit) 增加一个日期
- ADDTIME(expr1,expr2) 增加一个时间
- CURDATE() 返回当前日期
- CURTIME() 返回当前时间
- DATE(expr) 返回日期时间的日期部分
- DATEDIFF(expr1,expr2) 计算两个日期之差
- DATE_ADD 同ADDDATE
- DATE_FORMAT(date,format) 返回一个格式化的日期或时间戳
- YEAR(datetime)
- MONTH(datetime)
- DAY(datetime)
- DAYOFWEEK(datetime)
- HOUR(datetime)
- MINUTE(datetime)
- SECOND(datetime)
- TIME(datetime)
- NOW()
# 数值处理
- ABS(x) 返回一个数的绝对值
- EXP(x) 返回一个数的指数值
- SQRT(x) 返回一个数的平方根
- MOD(N,M) 返回除操作的余数
- COS(x) 返回一个弧度值的余弦
- SIN(x) 返回一个弧度值的正弦
- TAN(x) 返回一个弧度值的正切
- PI() 返回圆周率
- RAND() 返回随机数
# 聚集函数
- AVG(colname) 返回某列的平均值
- SUM(colname) 返回某列值之和
- COUNT(colname) 返回某列的行数
- MAX(colname) 返回某列的最大值
- MIN(colname) 返回某列的最小值
# 数据库备份
可使用以下工具:
- mysqldump
- mysqlhotcopy
# mysqldump
# 语法
mysqldump -u${username} -p${password} --lock-all-tables --flush-logs ${db_name} > ${bakcup_path}/${file_name}.sql